
# Anmelde-Transaktion erstellen

`POST /fapi/v1/transactions` · wird vom Anmelde-Host der Umgebung aufgerufen

Startet eine Anmelde-Transaktion für eine Anwendung. Die gehostete Anmeldeseite, UI-Komponenten und Headless-Clients rufen diesen
Endpunkt auf dem Anmelde-Host der Umgebung auf (eine Subdomain von `keenauth.app` oder eine verifizierte eigene Domain). Die Antwort setzt das Transaktionscookie `__Host-idp_ltx` (Secure, HttpOnly, SameSite=Lax, 15 Minuten gültig); spätere Schritte verwenden dieses Cookie.

## Anfrage

Header:

| Header | Erforderlich | Beschreibung |
| --- | --- | --- |
| `Idp-Client` | ja | SDK-Kennung, `<package>/<version> (<runtime>/<version>)`. |
| `Origin` | ja | Muss exakt `https://<sign-in host>` sein. |

Body:

| Feld | Typ | Erforderlich | Beschreibung |
| --- | --- | --- | --- |
| `client_id` | string | ja | Die Client-ID der Anwendung. |
| `redirect_uri` | string (URI) | ja | Eine der registrierten Weiterleitungs-URIs der Anwendung. |

## Antwort

`201 Created` mit dem Transaktionsobjekt:

```json
{
  "schema_version": 1,
  "state": "identifier_pending",
  "next_steps": [{ "step": "identifier", "fields": ["identifier"] }],
  "csrf_token": "<token>",
  "expires_at": "2026-10-05T10:15:00Z"
}
```

Senden Sie `csrf_token` bei jeder zustandsverändernden Anfrage dieser Transaktion im Header `Idp-Csrf-Token` zurück.

Wenn die Autorisierungsanfrage eine Organisation nennt, die SSO verlangt, kann die Antwort bereits `federated_redirect` mit `redirect_url` lauten (eine Verbindung: navigieren Sie das oberste Fenster dorthin) oder `sso_connections` enthalten (mehrere: senden Sie die Auswahl mit dem Schritt `sso_start`).

## DPoP-gebundene Headless-Transaktionen

Eine First-Party-SPA oder native App auf ihrem eigenen Ursprung startet eine Headless-Anmeldung mit einem `DPoP`-Header (RFC 9449): einem Nachweis, der mit einem Schlüssel signiert ist, den der Client behält (ein nicht exportierbarer WebCrypto-Schlüssel im Browser, der Schlüsselspeicher der Plattform auf einem Gerät), mit `htm` `POST` und `htu` `https://<sign-in host>/fapi/v1/transactions`. Die Transaktion ist dann an diesen Schlüssel gebunden statt an ein Cookie: Es wird kein Cookie gesetzt und das Objekt enthält keinen `csrf_token`. Jede spätere Anfrage der Transaktion sendet einen neuen Nachweis mit demselben Schlüssel.

Zusätzliche Body-Felder, geprüft nach den Regeln des Autorisierungsendpunkts:

| Feld | Typ | Erforderlich | Beschreibung |
| --- | --- | --- | --- |
| `code_challenge` | string | ja | PKCE-S256-Challenge (RFC 7636). |
| `code_challenge_method` | string | ja | `S256`. |
| `scope` | string | nein | Durch Leerzeichen getrennte Scopes, zum Beispiel `openid profile email offline_access`. |
| `state` | string | nein | Wird zusammen mit dem Autorisierungscode zurückgegeben. |
| `nonce` | string | nein | Der `nonce` des ID-Tokens. |
| `organization` | string | nein | Organisations-ID oder Name. |
| `ui_locales` | string | nein | Bevorzugte Sprachen. |
| `resource` | string (URI) | nein | Ressourcenindikator (RFC 8707). |

`Origin` kann der Anmelde-Host oder einer der erlaubten Web-Ursprünge der Anwendung sein; eine native App sendet keinen. Nur First-Party-Anwendungen können eine solche Transaktion starten. Ein Feld, das der Autorisierungsendpunkt ablehnt, führt zu `422 validation_failed` mit dem OAuth-Fehlercode in `errors[].code`. Antwortet der Server mit `401 use_dpop_nonce`, signieren Sie einen neuen Nachweis mit dem Wert des Headers `DPoP-Nonce` der Antwort und wiederholen Sie die Anfrage. Werden diese Felder ohne `DPoP`-Header gesendet, folgt `422 validation_failed` (`dpop_required`).

## Organisation wechseln

Eine Anwendung, die für den angemeldeten Benutzer ein Front-API-Zugriffstoken besitzt (siehe [Front-API-Zugriffstoken](/docs/api/fapi/front-api-token)), wechselt den Benutzer ohne Bildschirmanzeige in eine andere Organisation. Senden Sie das Token in `Authorization: DPoP <token>` mit einem Nachweis des Schlüssels des Tokens (mit `ath`) und im Body das Feld `flow` mit dem Wert `organization_switch`, die oben genannten DPoP-gebundenen Headless-Felder (`client_id` der Anwendung des Tokens, `redirect_uri`, `code_challenge`, `state`, `nonce`, `scope`) sowie `organization`, die ID `org_…` einer Organisation aus `GET /fapi/v1/me/organizations`.

Die Anfrage wird sofort mit der Sitzung des Tokens entschieden, so wie eine Anmeldung, die die Sitzung wiederverwendet, entschieden würde: die Richtlinie der Organisation (MFA, Leerlaufzeitlimit, SSO, IP-Liste), Zustimmung und ausstehende rechtliche Dokumente. Die Antwort ist `201` mit einer `completed`-Transaktion, die `authorization_response` enthält; tauschen Sie deren `code` am Token-Endpunkt mit Ihrem `code_verifier` und einem Nachweis desselben Schlüssels ein. Die neuen Tokens enthalten die Organisation in `org_id`. Es bleibt keine Transaktion offen und es wird kein Cookie gesetzt.

```json
{
  "schema_version": 1,
  "state": "completed",
  "next_steps": [],
  "authorization_response": { "code": "<code>", "state": "<state>", "iss": "https://example.keenauth.app" },
  "expires_at": "2026-10-05T10:15:00Z"
}
```

| Status | Code | Wann |
| --- | --- | --- |
| 401 | `unauthenticated` | Das Token ist ungültig, abgelaufen, widerrufen oder nicht an einen Schlüssel gebunden, seine Anwendung ist keine aktive First-Party-Anwendung, oder seine Sitzung wurde beendet. |
| 422 | `validation_failed` | `flow` ist nicht `organization_switch`, `client_id` ist nicht die Anwendung des Tokens, `organization` ist keine `org_…`-ID, oder der Benutzer kann in dieser Anwendung nicht zu ihr wechseln (`not_eligible`). |
| 403 | `authorization_failed` | Die Organisation benötigt einen Bildschirm, den der Wechsel nicht anzeigen kann; `error` ist der OAuth-Fehler (`login_required`, `interaction_required`, `consent_required`). Starten Sie eine neue Anmeldung mit gesetztem `organization`. |

`flow` mit dem Wert `organization_switch` ohne Token führt zu `422 validation_failed` (`access_token_required`).

## Fehler

| Status | Code | Wann |
| --- | --- | --- |
| 400 | `malformed_request` | `Idp-Client` fehlt oder der Body ist kein gültiges JSON. |
| 403 | `origin_not_allowed` | `Origin` ist nicht der Anmelde-Host. |
| 403 | `headless_not_allowed` | Eine Drittanbieter-Anwendung hat versucht, einen Headless-Ablauf zu starten. |
| 404 | `not_found` | Der Host ist keiner Umgebung als Anmelde-Host zugeordnet. |
| 422 | `validation_failed` | `client_id` ist keine Anwendung dieser Umgebung, `redirect_uri` ist dafür nicht registriert, oder ein Feld ist ungültig. |
| 401 | `invalid_dpop_proof` | Der `DPoP`-Nachweis fehlt, ist ungültig oder wurde wiederverwendet, oder der Host stellt keine DPoP-gebundenen Transaktionen bereit. |
| 401 | `use_dpop_nonce` | Signieren Sie einen neuen Nachweis mit dem Wert des Headers `DPoP-Nonce` der Antwort. |
| 503 | `temporarily_unavailable` | Eine Abhängigkeit ist nicht verfügbar; versuchen Sie es später erneut. |

## Beispiel

```bash
curl -X POST https://example.keenauth.app/fapi/v1/transactions \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{"client_id":"<client_id>","redirect_uri":"https://app.example.com/callback"}'
```

## Personenbezogene Daten

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