
# Mettre à jour un utilisateur

`PATCH /v1/users/{user_id}` · permission `users:write`

Met à jour un utilisateur à l'aide d'un JSON merge patch (`Content-Type: application/merge-patch+json`). Seuls les champs que vous envoyez sont modifiés. Les champs texte sont vidés avec `null` ou une chaîne vide ; `email_verified` et `phone_verified` ne peuvent pas être vidés ; `address` est remplacée dans son ensemble ; `user_metadata` et `app_metadata` sont fusionnées clé par clé, et une valeur `null` supprime cette clé ; si `user_metadata` ou `app_metadata` lui-même est envoyé à `null`, toutes ses données sont supprimées et il devient `{}`. Le statut ne peut pas être modifié ici ; utilisez le blocage et le déblocage. Un utilisateur en attente de suppression ne peut pas être mis à jour. `If-Match` est facultatif : lorsqu'il est envoyé, il doit correspondre à l'`ETag` actuel de l'utilisateur.

## Requête

| Paramètre | Dans | Obligatoire | Description |
|---|---|---|---|
| `user_id` | chemin | oui | Identifiant de l'utilisateur, préfixé `usr_`. |
| `If-Match` | en-tête | non | L'`ETag` issu d'une lecture précédente. |

Le corps accepte les mêmes champs que [Créer un utilisateur](/docs/api/management/users/create), tous facultatifs, ainsi que les champs d'âge ci-dessous. Les champs inconnus sont rejetés avec `unknown_field`.

### Âge et consentement parental

Lorsque votre propre processus de vérification de l'âge ou de consentement parental est terminé, enregistrez son résultat sur l'utilisateur à l'aide de ces champs. Ils sont aussi renvoyés sur chaque objet utilisateur ; `null` signifie que l'utilisateur n'a pas été évalué.

| Champ | Valeurs | Remarques |
|---|---|---|
| `age_group` | `adult`, `minor`, `unknown` | Ne peut pas être vidé ; envoyez `unknown` lorsque l'âge n'est pas connu. |
| `parental_consent_status` | `not_required`, `pending`, `granted`, `denied`, `revoked` | `null` le vide. Toute valeur autre que `not_required` n'est acceptée que lorsque le `age_group` de l'utilisateur est `minor`. |
| `age_assurance_level` | `self_declared`, `birthdate_declared`, `third_party_verified` | `null` le vide. Indique le degré de fiabilité avec lequel votre processus a établi l'âge. |

Une modification de `age_group` ou de `parental_consent_status` émet un événement `user.updated`. N'indiquez ni date de naissance ni numéro de document d'identité dans ces champs ou dans les métadonnées pour les compléter ; envoyez uniquement le résultat.

## Réponse

`200 OK`. Le corps est l'objet utilisateur. L'en-tête `ETag` contient la version de l'utilisateur.

Les données personnelles sont masquées lorsque la clé ne dispose pas de l'autorisation `users:read_pii` : `email` devient `a***@e***.com`, `phone_number` ne conserve que ses 2 derniers chiffres (`+**********67`), `name`, `given_name`, `family_name`, `middle_name` et `nickname` deviennent des initiales (`A. L.`), `username` ne conserve que son premier caractère (`a***`), `birthdate` devient `****-**-**` et `address` devient `{"redacted": true}`. `user_metadata` et `app_metadata` ne sont pas masquées.

```json
{
  "id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p",
  "kind": "regular",
  "status": "active",
  "external_id": null,
  "username": null,
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "email_verified": true,
  "phone_number": null,
  "phone_verified": false,
  "age_group": "adult",
  "parental_consent_status": null,
  "age_assurance_level": "self_declared",
  "user_metadata": {},
  "app_metadata": {},
  "created_via": "admin_api",
  "created_at": "2026-01-15T09:30:00Z",
  "updated_at": "2026-01-15T09:30:00Z",
  "last_sign_in_at": null,
  "deletion_requested_at": null,
  "deletion_due_at": null
}
```

## Erreurs

Chaque erreur est un corps `application/problem+json` avec un `code` stable.

| HTTP | `code` | Quand |
|---|---|---|
| 400 | `malformed_request`, `unknown_field` | Le patch n'est pas un objet JSON, ou un champ ne figure pas dans le schéma ; ou `If-Match` est mal formé. |
| 409 | `conflict` | La valeur est déjà utilisée, ou l'utilisateur est en attente de suppression (`errors[].code` vaut `user_pending_deletion`). |
| 412 | `precondition_failed` | `If-Match` ne correspond pas à la version actuelle. |
| 415 | `unsupported_media_type` | `Content-Type` n'est pas `application/merge-patch+json`. |
| 422 | `validation_failed` | Une valeur est invalide ou a un type incorrect ; `errors[].pointer` désigne le champ. |
| 404 | `not_found` | L'utilisateur n'existe pas dans cet environnement (ou l'identifiant est mal formé). |
| 401 | `unauthenticated` | La clé d'API est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de l'autorisation `users:write`. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; respectez `Retry-After`. |
| 503 | `service_unavailable` | Une dépendance est temporairement indisponible ; réessayez plus tard. |

## Exemple

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/users/usr_0a1b2c3d4e5f6g7h8j9k0m1n2p \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"name": "Ada King", "app_metadata": {"tier": "gold"}}'
```

Enregistrer un consentement parental accordé pour un mineur :

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/users/usr_0a1b2c3d4e5f6g7h8j9k0m1n2p \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"age_group": "minor", "parental_consent_status": "granted", "age_assurance_level": "third_party_verified"}'
```

## Données personnelles

Cet endpoint traite des données personnelles : le profil de l'utilisateur final. [Données personnelles dans les API KeenAuth](/docs/policies/personal-data) décrit ce qui est stocké, la durée de conservation et la manière dont elles sont supprimées. Ne transmettez de catégories particulières de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.
