# Authentifizierung

Jede Anfrage trägt einen API-Key als Bearer-Token:

```
Authorization: Bearer ks_live_…
```

Ohne Header antwortet die API mit `401` [`missing_api_key`](https://docs.kalender-sync.de/api/errors/missing_api_key/), mit falschem, widerrufenem oder abgelaufenem Key mit `401` [`invalid_api_key`](https://docs.kalender-sync.de/api/errors/invalid_api_key/). Das gilt auch für unbekannte Pfade: Ohne gültigen Key bekommst du `401`, nicht `404`. So verrät die API nicht, welche Pfade es gibt.

Öffentlich und ohne Key ist nur `GET /v1/openapi.json`.

## Keys anlegen

Keys legst du in der [App](https://app.kalender-sync.de/) unter **Einstellungen › Entwickler / API** an.

- **Sandbox-Key** (`ks_test_…`): in jedem Tarif. Sieht nur Testkalender.
- **Live-Key** (`ks_live_…`): ab Basic. Sieht nur Live-Kalender.

Der Key wird **genau einmal** angezeigt. Wir speichern nur einen Hash davon. Geht er verloren, legst du einen neuen an. Ein Konto kann bis zu **10 aktive Keys** haben, sodass du Keys ohne Unterbrechung austauschen kannst: neuen Key anlegen, im Plugin eintragen, alten widerrufen.

## Aufbau eines Keys

```
ks_live_<32 Zeichen>_<6 Zeichen Prüfsumme>
ks_test_<32 Zeichen>_<6 Zeichen Prüfsumme>
```

Die Prüfsumme am Ende erlaubt Secret-Scannern, einen geleakten Key zu erkennen, und uns, einen vertippten Key ohne Datenbankabfrage abzulehnen. Zugangsschlüssel für den MCP-Server (`ksa_…`) funktionieren hier nicht.

## Key prüfen: `GET /v1/me`

Ideal für einen Button „Verbindung testen“ in deinem Plugin.

```bash
curl https://api.kalender-sync.de/v1/me -H "Authorization: Bearer $KS_KEY"
```

```json
{
  "account_id": "…",
  "key": {
    "id": "…",
    "name": "Meine Website",
    "mode": "live",
    "scopes": ["publisher:read", "publisher:write", "publisher:stats"],
    "calendar_ids": null
  }
}
```

| Feld | Bedeutung |
|---|---|
| `mode` | `live` oder `test` (Sandbox). |
| `scopes` | Was der Key darf: `publisher:read` (lesen), `publisher:write` (anlegen, ändern, löschen), `publisher:stats` (Statistik). Keys aus den Einstellungen haben alle drei. |
| `calendar_ids` | `null`, wenn der Key alle Kalender des Kontos sieht. Sonst die Liste der Kalender, auf die er beschränkt ist. Ein beschränkter Key kann keine neuen Kalender anlegen. |

Fehlt ein Scope, antwortet die API mit `403` [`insufficient_scope`](https://docs.kalender-sync.de/api/errors/insufficient_scope/).

## Sandbox und Live

Beide Key-Arten sprechen dieselbe API unter derselben URL an. Ein Sandbox-Key sieht nur Testkalender, ein Live-Key nur Live-Kalender. Ein Kalender des jeweils anderen Modus antwortet mit `404` [`calendar_not_found`](https://docs.kalender-sync.de/api/errors/calendar_not_found/).

| | Sandbox | Live |
|---|---|---|
| Kalender je Konto | 3 | je nach Tarif: Basic 1, Professional 10 |
| Termine je Kalender | 500 | 5.000 |
| Name im Feed | mit `[TEST]` davor | wie angelegt |
| Abo-Seite | mit Hinweis „Testkalender“ | ohne Hinweis |

## Key sicher aufbewahren

- Speichere den Key nur **serverseitig**, zum Beispiel in WordPress als Option, die nicht automatisch geladen wird. Nie im HTML, im JavaScript deiner Seite oder in einem öffentlichen Repository.
- Schreibe ihn nicht in Logs oder Fehlermeldungen.
- Der Button auf deiner Website braucht **keinen** Key, nur die Kalender-ID.

## Key widerrufen

Unter **Einstellungen › Entwickler / API** auf **Widerrufen**. Das wirkt ab der nächsten Anfrage; alles, was den Key nutzt, bekommt dann `401 invalid_api_key`. Bestehende Kalender, Feeds und Abos bleiben unverändert.