
# Remplacer la politique d'âge

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

Écrit la politique d'âge complète. `If-Match` est requis (`428` si absent, `412` si la valeur ne correspond pas) ; une politique jamais écrite a la version `"0"`. Règles : `min_age` et les seuils par pays vont de 13 à 21 ; les codes pays sont ISO 3166-1 alpha-2 (majuscules), au maximum 250 entrées ; `parental_consent_below` vaut `null` ou 1..`min_age` ; `store_birthdate` ne peut valoir `true` que lorsque `mode` vaut `birthdate`. La politique s'applique uniquement aux inscriptions ultérieures ; les utilisateurs existants ne changent pas.

## Requête

Corps JSON (les champs inconnus sont rejetés avec `400 unknown_field`) :

| Champ | Type | Requis | Description |
|---|---|---|---|
| `If-Match` | en-tête | oui | En-tête : la valeur `ETag` provenant de `GET /v1/age-policy`. |
| `mode` | chaîne | oui | `off`, `attestation` (question neutre sur l'année et le mois de naissance, valeur non stockée) ou `birthdate`. |
| `min_age` | entier | oui | 13 à 21. |
| `country_min_age` | objet | oui | Code pays → seuil (13 à 21) ; les pays absents utilisent `min_age`. |
| `country_source` | chaîne | oui | `ip` ou `declared`. |
| `under_age_action` | chaîne | oui | `block` ou `create_minor`. |
| `parental_consent_below` | entier \| null | non | `null` (pas de consentement parental) ou 1..`min_age`. |
| `pending_consent_action` | chaîne | oui | `block_sign_in` ou `issue_limited`. |
| `store_birthdate` | booléen | oui | `true` uniquement avec `mode: birthdate`. |
| `applies_to` | chaîne | oui | `self_signup` ou `all`. |

## Réponse

`200 OK` avec la politique et l'en-tête `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"
}
```

## Jetons

Tant que `mode` n'est pas `off`, les jetons ID, les jetons d'accès et la réponse UserInfo transportent le `age_group` de l'utilisateur (`adult`, `minor` ou `unknown`) quels que soient les scopes demandés, et `parental_consent_status` (`not_required`, `pending`, `granted`, `denied` ou `revoked`) lorsqu'il a une valeur. Avec `mode: off`, aucun des deux claims n'est émis. Les deux sont écrits uniquement par KeenAuth (vos hooks et modèles de claims ne peuvent pas les définir) ; modifiez-les avec `PATCH /v1/users/{user_id}`.

Sous `pending_consent_action: block_sign_in`, un utilisateur dont `parental_consent_status` vaut `pending`, `denied` ou `revoked` ne reçoit aucun jeton : la requête d'autorisation se termine avec `access_denied` et le point de terminaison de jeton répond `invalid_grant` (`Parental consent has not been granted.`) pour les types d'octroi code d'autorisation, code d'appareil et jeton de rafraîchissement. Un jeton de rafraîchissement n'est pas révoqué ; il fonctionne à nouveau dès que le consentement vaut `granted`. Sous `issue_limited`, les jetons sont émis et votre application restreint l'utilisateur à partir des claims.

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le corps contient un champ inconnu. |
| 412 | `precondition_failed` | `If-Match` ne correspond pas à la version actuelle. |
| 415 | `unsupported_media_type` | Le type de contenu n'est pas `application/json`. |
| 422 | `validation_failed` | Un champ est absent (`required`) ou enfreint une règle ci-dessus ; le pointeur désigne le champ, par exemple `/country_min_age/DE`. |
| 428 | `precondition_required` | L'en-tête `If-Match` est absent. |
| 401 | `unauthenticated` | L'identifiant est absent, invalide ou révoqué. |
| 403 | `insufficient_permissions` | L'identifiant ne dispose pas de l'autorisation requise. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; réessayez après la période `Retry-After`. |
| 503 | `service_unavailable` | Une dépendance est temporairement indisponible ; réessayez après la période `Retry-After`. |

## Exemple

```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"}'
```
