# API-Grundlagen

Basisadresse, Anmeldung mit API-Schlüssel, Grenzen und Antwortformat.

## Hinweise für KI-Agenten

- API-Basisadresse: `https://api.eventwerk.eu/api/v1`
- OpenAPI 3.1: `https://api.eventwerk.eu/openapi.json` und `/api/v1/openapi.json`. Daraus lassen sich Clients und Typprüfungen generieren.
- Anmeldung: `Authorization: Bearer ew_...`
- Schlüssel: Einstellungen unter `/dashboard/einstellungen`, nur mit Eventwerk Plus und nur für Eigentümer. Der volle Schlüssel wird nur einmal angezeigt. Name und Zeitpunkt der letzten Nutzung werden geführt und ausgegeben.
- Zeiten: Alle Zeitpunkte kommen in UTC mit Suffix `Z`. Die Zeitzone des Events steht getrennt in `timezone` als IANA-Name, Standard `Europe/Vienna`. Clients rechnen selbst um.
- Paginierung: Die Event- und Anmeldelisten liefern `{items, has_more, next_cursor}` mit `limit` (Standard 50, höchstens 200), `cursor` und `updated_since`.
- Grenzen: 200 Anfragen pro Minute je Schlüssel. Der Zähler liegt im Speicher je Instanz, ist hinter mehreren Instanzen ein Vielfaches und beginnt nach einem Deploy neu. Bei Überschreitung antwortet die API mit 429, `rate_limited` und `Retry-After`.
- Gastgrenzen: Anmelde-Link 20 je Stunde je IP-Adresse, Anmeldung 60 je Stunde je IP-Adresse und 3 je Stunde je E-Mail-Adresse und Event.
- Fehler: JSON mit `code` und `message`, optional mit `details`.

Die öffentliche API ist eine JSON-API über HTTP. Sie ist versioniert und liegt unter `/api/v1`. Alle Endpunkte der öffentlichen API erfordern Eventwerk Plus.

## Basisadresse

Die Basisadresse lautet `https://api.eventwerk.eu/api/v1`. Ein Aufruf von `/me` wird damit zu `GET https://api.eventwerk.eu/api/v1/me`.

## Anmeldung

Jede Anfrage trägt einen API-Schlüssel im Header `Authorization`. Das Format ist `Bearer ew_...`. Ein Schlüssel beginnt mit `ew_`, gefolgt von 40 Zeichen. Er handelt immer als Eigentümer der Organisation.

```bash
curl -s https://api.eventwerk.eu/api/v1/me \
  -H "Authorization: Bearer ew_..."
```

## Schlüssel anlegen und zurückziehen

1. Plan in den Einstellungen auf Eventwerk Plus stellen.
2. Als Eigentümer unter Einstellungen, API-Schlüssel einen Namen angeben und den Schlüssel anlegen.
3. Den vollen Schlüssel jetzt kopieren. Er wird nur einmal angezeigt.
4. Nicht benötigte Schlüssel in den Einstellungen zurückziehen.

- Höchstens 25 aktive Schlüssel pro Organisation.
- Höchstens 10 neue Schlüssel in einem rollierenden Zeitfenster von 24 Stunden.
- Ein zurückgezogener Schlüssel wird sofort abgelehnt und ergibt `invalid_api_key`.
- Der angezeigte Prefix besteht aus den ersten acht Zeichen.
- Zu jedem Schlüssel werden der Name und der Zeitpunkt der letzten Nutzung geführt. Die Einstellungen zeigen beides an. Der Zeitpunkt steht als `last_used_at` in der Antwort der Schlüssel-Endpunkte. Vor der ersten Nutzung ist er null.

> **Warnung:** Der volle Schlüssel ist ein Geheimnis. Speichern Sie ihn nur an einem sicheren Ort und niemals in einem Repository oder in einer öffentlichen Variable.

## Antwortformat

- JSON mit UTF-8 und `Content-Type: application/json; charset=utf-8`.
- Zeitpunkte kommen als RFC-3339-Strings in UTC, immer mit dem Suffix `Z`.
- Die Zeitzone des Events steht getrennt im Feld `timezone`. Sie ist ein IANA-Name, Standard `Europe/Vienna`.
- Clients müssen Zeitpunkte selbst in die gewünschte Zeitzone umrechnen. Die API liefert keine lokale Zeit.
- Geldbeträge als ganze Zahl in Cent.
- Unbekannte Felder im Rumpf werden abgelehnt. Die Anfrage ergibt `unknown_field`, `details.field` nennt den Feldnamen.
- Der Rumpf darf höchstens 1 MiB groß sein. Sonst ergibt sich `request_too_large`.

## Paginierung

Die Listen unter `/events` und `/events/{eventID}/registrations` liefern seitenweise Ergebnisse. Die Antwort hat immer dieselbe Form.

```json
{
  "items": [],
  "has_more": false,
  "next_cursor": null
}
```

- `limit` legt die Seitengröße fest. Erlaubt sind 1 bis 200, Standard 50. Ein anderer Wert ergibt `invalid_limit`.
- `cursor` setzt die Liste an der Stelle fort, die `next_cursor` nennt. Ohne Cursor beginnt die Liste vorn.
- `updated_since` liefert nur Datensätze, die nach dem angegebenen RFC-3339-Zeitpunkt geändert wurden.
- `has_more` sagt, ob weitere Datensätze folgen. Ist er false, ist `next_cursor` null.
- Der Cursor ist undurchsichtig. Übernehmen Sie ihn unverändert und verwenden Sie ihn nur für dieselbe Liste.

## Idempotenz

`POST /events` akzeptiert den optionalen Header `Idempotency-Key`. Damit lässt sich eine Anfrage wiederholen, etwa nach einer Zeitüberschreitung, ohne ein zweites Event anzulegen.

- Gleicher Schlüssel und gleicher Rumpf: Die API liefert dieselbe Antwort erneut.
- Gleicher Schlüssel und anderer Rumpf: Die API antwortet mit Status 409 und dem Code `idempotency_conflict`.
- Ohne Header legt jeder Aufruf ein neues Event an.
- Verwenden Sie je beabsichtigter Anlage einen eigenen, zufälligen Schlüssel.

## Grenzen

Es gelten 200 Anfragen pro Minute je API-Schlüssel. Der Zähler liegt im Arbeitsspeicher jeder Instanz und wird nicht über Instanzen geteilt.

- Hinter mehreren Instanzen liegt das wirksame Limit deshalb faktisch bei einem Vielfachen von 200 pro Minute.
- Nach einem Neustart oder Deploy beginnt die Zählung neu.
- Ist das Limit erreicht, antwortet die API mit Status 429, dem Code `rate_limited` und dem Header `Retry-After` in Sekunden.

### Grenzen der Gastrouten

Öffentliche Routen ohne API-Schlüssel haben eigene Grenzen je IP-Adresse.

- Anmelde-Link (Magic-Link) anfordern: 20 Anfragen pro Stunde je IP-Adresse.
- Anmeldung zu einem Event: 60 Anfragen pro Stunde je IP-Adresse.
- Zusätzlich höchstens 3 Anmeldungen pro Stunde je E-Mail-Adresse und Event.

## Fehler

Fehler haben immer die Form `{ "code": "...", "message": "..." }`. Das Feld `details` kann zusätzliche Angaben enthalten, etwa `field` bei `unknown_field`, `count` bei `event_has_registrations` oder `limit`, `used` und `plan` beim Versandkontingent. `code` ist stabil, `message` ist für Menschen gedacht.

> **Warnung:** Werten Sie nicht den deutschen Text von `message` aus. Prüfen Sie stattdessen `code` und den HTTP-Status.

## Nicht verfügbar

- Schreiben von Ticketarten, Nachrichten, Umfragen, Programm oder Team über einen API-Schlüssel.
- CSV-Import, Empfehlungscodes und Erinnerungen über einen API-Schlüssel.
- Zapier-Workflows und Zoom-Anbindung.
