
# Altersrichtlinie ersetzen

`PUT /v1/age-policy` · Berechtigung `identity-settings:write`

Schreibt die gesamte Altersrichtlinie. `If-Match` ist erforderlich (`428`, wenn er fehlt, `412`, wenn er nicht übereinstimmt); eine Richtlinie, die nie geschrieben wurde, hat die Version `"0"`. Regeln: `min_age` und Altersgrenzen für Länder liegen bei 13-21; Ländercodes sind ISO 3166-1 alpha-2 (Großbuchstaben), höchstens 250 Einträge; `parental_consent_below` ist `null` oder 1..`min_age`; `store_birthdate` kann nur dann `true` sein, wenn `mode` `birthdate` ist. Die Richtlinie gilt nur für spätere Registrierungen; bestehende Nutzer ändern sich nicht.

## Anfrage

JSON-Body (unbekannte Felder werden mit `400 unknown_field` abgelehnt):

| Feld | Typ | Pflichtfeld | Beschreibung |
|---|---|---|---|
| `If-Match` | header | ja | Header: der Wert `ETag` aus `GET /v1/age-policy`. |
| `mode` | string | ja | `off`, `attestation` (neutrale Frage nach Geburtsjahr und -monat, Wert wird nicht gespeichert) oder `birthdate`. |
| `min_age` | integer | ja | 13-21. |
| `country_min_age` | object | ja | Ländercode → Grenzwert (13-21); für fehlende Länder gilt `min_age`. |
| `country_source` | string | ja | `ip` oder `declared`. |
| `under_age_action` | string | ja | `block` oder `create_minor`. |
| `parental_consent_below` | integer \| null | nein | `null` (keine elterliche Zustimmung) oder 1..`min_age`. |
| `pending_consent_action` | string | ja | `block_sign_in` oder `issue_limited`. |
| `store_birthdate` | boolean | ja | `true` nur mit `mode: birthdate`. |
| `applies_to` | string | ja | `self_signup` oder `all`. |

## Antwort

`200 OK` mit der Richtlinie und dem Header `ETag`.

```json
{
  "mode": "attestation",
  "min_age": 16,
  "country_min_age": {"DE": 16, "FR": 15, "IT": 14},
  "country_source": "ip",
  "under_age_action": "block",
  "parental_consent_below": null,
  "pending_consent_action": "block_sign_in",
  "store_birthdate": false,
  "applies_to": "self_signup",
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## Tokens

Solange `mode` nicht `off` ist, enthalten ID-Tokens, Access-Tokens und die UserInfo-Antwort die `age_group` des Nutzers (`adult`, `minor` oder `unknown`), unabhängig von den angeforderten Scopes, sowie `parental_consent_status` (`not_required`, `pending`, `granted`, `denied` oder `revoked`), wenn sie einen Wert hat. Mit `mode: off` wird keiner der beiden Claims ausgegeben. Beide werden ausschließlich von KeenAuth geschrieben (Ihre Hooks und Claim-Vorlagen können sie nicht setzen); ändern Sie sie mit `PATCH /v1/users/{user_id}`.

Unter `pending_consent_action: block_sign_in` erhält ein Nutzer, dessen `parental_consent_status` `pending`, `denied` oder `revoked` ist, kein Token: Die Autorisierungsanfrage endet mit `access_denied`, und der Token-Endpunkt antwortet mit `invalid_grant` (`Parental consent has not been granted.`) für die Grants Authorization Code, Device Code und Refresh Token. Ein Refresh Token wird nicht widerrufen; es funktioniert wieder, sobald die Zustimmung `granted` ist. Unter `issue_limited` werden Tokens ausgestellt, und Ihre Anwendung schränkt den Nutzer anhand der Claims ein.

## Fehler

| HTTP | code | Wann |
|---|---|---|
| 400 | `unknown_field` | Der Body enthält ein unbekanntes Feld. |
| 412 | `precondition_failed` | `If-Match` stimmt nicht mit der aktuellen Version überein. |
| 415 | `unsupported_media_type` | Der Content-Type ist nicht `application/json`. |
| 422 | `validation_failed` | Ein Feld fehlt (`required`) oder verletzt eine der obigen Regeln; der Pointer benennt das Feld, zum Beispiel `/country_min_age/DE`. |
| 428 | `precondition_required` | Der Header `If-Match` fehlt. |
| 401 | `unauthenticated` | Die Anmeldedaten fehlen, sind ungültig oder widerrufen. |
| 403 | `insufficient_permissions` | Den Anmeldedaten fehlt die erforderliche Berechtigung. |
| 429 | `rate_limited` | Das Ratenlimit wurde überschritten; wiederholen Sie die Anfrage nach Ablauf des Zeitraums `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar; wiederholen Sie die Anfrage nach Ablauf des Zeitraums `Retry-After`. |

## Beispiel

```bash
curl -X PUT https://api.eu.keenauth.com/v1/age-policy \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "0"' \
  -d '{"mode":"attestation","min_age":16,"country_min_age":{"DE":16,"FR":15},"country_source":"ip","under_age_action":"block","parental_consent_below":null,"pending_consent_action":"block_sign_in","store_birthdate":false,"applies_to":"self_signup"}'
```
