
# Eine Person zu einer Organisation einladen

`POST /v1/invitations` · Berechtigung `invitations:write`

Erstellt eine Einladung für eine E-Mail-Adresse, der Organisation beizutreten. Ohne `organization_id` ist die Einladung eine Umgebungseinladung: Sie ist der Registrierungslink für den Modus „Registrierung nur mit Einladung“, begründet keine Mitgliedschaft und kann keine Rollen enthalten (`role_ids` liefert `422 validation_failed`), und die Antwort enthält `organization_id: null`. `delivery` ist erforderlich: `email` sendet die Einladungs-E-Mail mit der Einladungsvorlage der Umgebung (`delivery_status: queued`). Der Link steht dann nur in der E-Mail, und die Antwort enthält keinen `accept_url`. `link_only` sendet keine E-Mail und gibt den Link zurück, den Sie teilen können. Der Annahmelink (`accept_url`) wird nur in dieser Antwort und nur einmal zurückgegeben; kein Endpunkt liefert ihn später erneut. Die Antwort enthält `Cache-Control: no-store`. Eine Antwort, die für denselben `Idempotency-Key` erneut ausgeliefert wird, enthält den Link nicht und trägt `secret_redacted: true`. Ist der Versand von Einladungs-E-Mails für die Bereitstellung nicht konfiguriert (nur in Nicht-Produktionsumgebungen), gibt die Zustellung per `email` `501 not_implemented` zurück, und es wird nichts geschrieben. Existiert bereits eine ausstehende Einladung mit denselben Rollen für die Organisation und E-Mail-Adresse, wird sie mit einem neuen Link erneut gesendet, und die Antwort lautet `200`. Eine ausstehende Einladung, die abgelaufen, aber noch nicht verarbeitet ist, wird in derselben Anfrage als `expired` markiert, und es wird eine neue Einladung geschrieben (protokolliert als `invitation.expired`). Eine ausstehende `email`-Einladung mit denselben Rollen wird per E-Mail erneut gesendet: Die Antwort lautet `200` mit `delivery: email` und ohne `accept_url`. Der Schreibvorgang wird als `invitation.created` protokolliert.

## Anfrage

| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
| `organization_id` | string | nein | Organisations-ID (`org_…`). Weglassen für eine Umgebungseinladung (ohne Rollen). |
| `email` | string | ja | E-Mail-Adresse der eingeladenen Person, bis zu 320 Zeichen. |
| `delivery` | string | ja | `email` (Link nur in der E-Mail) oder `link_only` (Link nur in dieser Antwort). |
| `role_ids` | string[] | nein | Bei Annahme gewährte Rollen (`rol_…`), höchstens 10. Ist das Feld leer, gilt die Standardrolle Mitglied. |
| `application_id` | string | nein | Anwendung, in der die eingeladene Person landet (`app_…`). Sie muss in dieser Umgebung existieren. |
| `ttl_days` | integer | nein | 1–30. Standard ist der Wert `invitation_ttl_days` der Umgebung (7). |

## Antwort

`201 Created` mit der Einladung und ihrem Annahmelink (`200 OK`, wenn eine ausstehende Einladung erneut gesendet wurde).

```json
{
  "id": "inv_01j9xt9v3w4y8z0a2b4c6d8e0g",
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
  "email": "ada@example.com",
  "role_ids": [
    "rol_01j9xr7s1t2w6x8y0z2a4b6c8e"
  ],
  "application_id": null,
  "delivery": "link_only",
  "delivery_status": "not_sent",
  "status": "pending",
  "send_count": 1,
  "last_sent_at": "2026-10-12T09:31:00.123456Z",
  "expires_at": "2026-10-19T09:31:00.123456Z",
  "accepted_user_id": null,
  "accepted_at": null,
  "revoked_at": null,
  "created_at": "2026-10-12T09:31:00.123456Z",
  "updated_at": "2026-10-12T09:31:00.123456Z",
  "version": 1,
  "accept_url": "https://acme.eu.keenauth.app/u/login?invitation=<token>"
}
```

## Fehler

| HTTP | Code | Wann |
|---|---|---|
| 404 | `not_found` | Die Organisation oder die Anwendung existiert in dieser Umgebung nicht. |
| 409 | `invitation_already_pending` | Für diese E-Mail-Adresse existiert eine ausstehende Einladung mit anderen Rollen. |
| 409 | `membership_already_exists` | Die E-Mail-Adresse gehört bereits zu einem Mitglied. |
| 409 | `organization_disabled` | Die Organisation ist deaktiviert. |
| 422 | `invitation_invalid` | Die Einladung kann mit diesen Werten nicht erstellt werden. |
| 422 | `validation_failed` | Ein Feld fehlt oder ist ungültig. |
| 429 | `invite_rate_limited` | Die Einladung wurde vor weniger als 10 Minuten oder bereits 5-mal erneut gesendet. |
| 501 | `not_implemented` | `delivery` ist `email`, und der Versand von Einladungs-E-Mails ist für die Bereitstellung nicht konfiguriert. |
| 401 | `unauthenticated` | Das Authentifizierungsmerkmal fehlt, ist ungültig oder wurde widerrufen. |
| 403 | `insufficient_permissions` | Das Authentifizierungsmerkmal hat nicht die erforderliche Berechtigung. Die Zuweisung einer privilegierten Rolle (`is_privileged`) erfordert zusätzlich `roles:write`. Ohne diese Berechtigung wird nichts geschrieben, und `required_permissions` nennt beide Berechtigungen. |
| 429 | `rate_limited` | Das Ratenlimit wurde überschritten. Wiederholen Sie die Anfrage nach dem Zeitraum aus `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar. Wiederholen Sie die Anfrage nach dem Zeitraum aus `Retry-After`. |

## Beispiel

```bash
curl -i -X POST "https://api.eu.keenauth.com/v1/invitations" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","email":"ada@example.com","delivery":"link_only","role_ids":["rol_01j9xr7s1t2w6x8y0z2a4b6c8e"]}'
```

## Personenbezogene Daten

Dieser Endpunkt verarbeitet personenbezogene Daten: Organisationsmitgliedschaften und Einladungen. [Personenbezogene Daten in den KeenAuth-APIs](/docs/policies/personal-data) beschreibt, was gespeichert wird, wie lange die Daten aufbewahrt werden und wie sie gelöscht werden. Übermitteln Sie in keinem Feld besondere Kategorien personenbezogener Daten (Gesundheit, biometrische Daten, Religion, politische Meinungen, sexuelle Orientierung).
