# Publisher API

Mit der **Publisher API** veröffentlichst du Termine aus deiner Website, deinem Plugin oder deinem System als [Abo-Kalender](https://docs.kalender-sync.de/abo-kalender/). Du schreibst Termine per `PUT` unter deiner eigenen ID. Kalender Sync hostet daraus einen ICS-Feed, eine Abo-Seite und einen einbettbaren Button.

:::tip[OpenAPI 3.1]
Die maschinenlesbare Beschreibung aller Endpunkte liegt öffentlich und ohne Key unter
**[https://api.kalender-sync.de/v1/openapi.json](https://api.kalender-sync.de/v1/openapi.json)**.
Du kannst sie in Postman, Insomnia oder einen Code-Generator laden, oder deinem KI-Agenten geben.
:::

## Auf einen Blick

| | |
|---|---|
| Basis-URL | `https://api.kalender-sync.de/v1` |
| Format | JSON in und out, UTF-8, nur HTTPS |
| Authentifizierung | `Authorization: Bearer ks_live_…` oder `ks_test_…` → [Authentifizierung](https://docs.kalender-sync.de/api/authentication/) |
| Fehler | `application/problem+json` (RFC 9457) mit stabilem `code` → [Fehler](https://docs.kalender-sync.de/api/errors/) |
| Rate Limit | 120 Anfragen pro Minute und Key → [Limits](https://docs.kalender-sync.de/api/limits/) |
| Sandbox | Keys mit `ks_test_` sehen nur Testkalender, auf derselben API |

## Endpunkte

Alle Pfade relativ zur Basis-URL.

| Methode und Pfad | Zweck |
|---|---|
| `GET /me` | Key prüfen: Konto, Modus, Scopes |
| `POST /publisher/calendars` | Kalender anlegen |
| `GET /publisher/calendars` | Kalender auflisten |
| `GET /publisher/calendars/{calendar_id}` | Kalender lesen, mit Feed-URL und Abo-Links |
| `PATCH /publisher/calendars/{calendar_id}` | Kalender ändern |
| `DELETE /publisher/calendars/{calendar_id}` | Kalender löschen |
| `PUT /publisher/calendars/{calendar_id}/images/{logo\|banner}` | Logo oder Banner hochladen |
| `DELETE /publisher/calendars/{calendar_id}/images/{logo\|banner}` | Logo oder Banner entfernen |
| `PUT /publisher/calendars/{calendar_id}/events/{external_id}` | Termin anlegen oder ändern |
| `GET /publisher/calendars/{calendar_id}/events/{external_id}` | Termin lesen |
| `DELETE /publisher/calendars/{calendar_id}/events/{external_id}` | Termin löschen |
| `GET /publisher/calendars/{calendar_id}/events` | Termine auflisten (Cursor, `updated_since`) |
| `POST /publisher/calendars/{calendar_id}/events/batch` | Bis zu 100 Änderungen in einem Aufruf |
| `POST /publisher/calendars/{calendar_id}/syncs` | Full Sync starten |
| `POST /publisher/calendars/{calendar_id}/syncs/{sync_id}/complete` | Full Sync abschließen |
| `GET /publisher/calendars/{calendar_id}/stats` | Abonnenten und Klicks |

## Grundprinzipien

- **Deine IDs, nicht unsere.** Termine adressierst du mit deiner eigenen `external_id`, zum Beispiel der WordPress-Post-ID. Du musst keine ID von uns speichern außer der Kalender-ID.
- **Sicher wiederholbar.** `PUT` und `DELETE` auf Termine sind idempotent. Ein unveränderter Termin liefert `"changed": false`, und keine Kalender-App muss neu laden. Für `POST /publisher/calendars` gibt es den Header `Idempotency-Key`. → [Idempotenz](https://docs.kalender-sync.de/api/idempotency/)
- **Unbekannte Felder werden abgelehnt.** Ein Tippfehler im Feldnamen führt zu `400 invalid_request` statt still ignoriert zu werden.
- **Additive Änderungen.** `/v1` wird nur erweitert: neue Felder, neue optionale Parameter, neue Fehlercodes. Ignoriere Felder in Antworten, die du nicht kennst.
- **Abonnenten bekommen Änderungen beim nächsten Abruf.** Kalender-Apps holen den Feed nach eigenem Zeitplan ab. → [Wie schnell kommen Änderungen an?](https://docs.kalender-sync.de/abo-kalender/faq/#wie-schnell-kommen-änderungen-bei-abonnenten-an)

## Los geht's

- [Schnellstart](https://docs.kalender-sync.de/api/quickstart/): in fünf curl-Aufrufen vom Key zum abonnierbaren Kalender
- [Termine und Wiederholungen](https://docs.kalender-sync.de/api/events/): Felder, RRULE, Mapping typischer Plugin-Felder
- [Button und ks:subscribe](https://docs.kalender-sync.de/api/button/): den Abo-Button einbauen
- [Für KI-Agenten](https://docs.kalender-sync.de/api/ai-agents/): Copy-Prompt und OpenAPI für deinen Agenten