
# Lister les journaux d'un utilisateur

`GET /v1/users/{user_id}/logs` · autorisation `logs:read`

Liste les enregistrements de journal d'un utilisateur avec pagination par curseur, du plus récent au plus ancien. Ce sont les données qui alimentent la vue d'activité de l'utilisateur dans le tableau de bord. Cette requête suit les mêmes règles que [Lister les journaux](/docs/api/management/logs/list), mais n'accepte que les filtres `from`, `to`, `type` et `org_id` ; les autres filtres sont ignorés.

## Périmètre de l'organisation

Transmettez `org_id` pour afficher un diagnostic des membres à l'intention d'un administrateur d'organisation. La clé doit alors aussi disposer de l'autorisation `organizations:read`. Si l'utilisateur n'est pas membre de cette organisation (aucune adhésion `invited`, `active` ou `suspended`), la requête échoue avec `404 not_found`, la même réponse que pour un utilisateur inconnu. Si l'utilisateur en est membre, seuls les enregistrements survenus dans le contexte de cette organisation sont renvoyés, c'est-à-dire ceux dont `org_id` correspond à cette organisation. Les connexions de l'utilisateur en dehors de cette organisation, ou dans le contexte d'une autre organisation, ne sont jamais renvoyées. Sans `org_id`, la vue couvre tous les enregistrements de l'utilisateur dans l'environnement.

## Requête

| Paramètre | Emplacement | Obligatoire | Description |
|---|---|---|---|
| `user_id` | chemin | oui | Identifiant de l'utilisateur, préfixé `usr_`. |
| `limit` | requête | non | Taille de page, de 1 à 100. Valeur par défaut : 20. |
| `after` | requête | non | Curseur opaque issu de `list_metadata.after` (enregistrements plus anciens). Exclusif avec `before`. |
| `before` | requête | non | Curseur opaque issu de `list_metadata.before` (enregistrements plus récents). Exclusif avec `after`. |
| `from` | requête | non | Heure RFC 3339 ; enregistrements à cette heure ou après. Doit se situer dans la fenêtre de conservation. |
| `to` | requête | non | Heure RFC 3339 ; enregistrements antérieurs à cette heure. Doit être postérieure à `from`. |
| `type` | requête | non | Préfixe de type de journal, par exemple `authentication.` ou `session.created`. Répétez le paramètre pour un maximum de 20 valeurs ; un enregistrement correspondant à l'une d'elles est renvoyé. |
| `org_id` | requête | non | Identifiant de l'organisation, préfixé `org_`. Limite la vue aux enregistrements de cette organisation ; voir [Périmètre de l'organisation](#périmètre-de-lorganisation). Nécessite `organizations:read`. |

Les enregistrements sont toujours triés par `occurred_at`, du plus récent au plus ancien ; il n'existe pas de paramètre `order` (`order=desc` est accepté, toute autre valeur échoue avec `validation_failed`). Un curseur n'est valide qu'avec les filtres pour lesquels il a été émis.

## Réponse

`200 OK`. `data` contient les enregistrements de la page ; `list_metadata.after` pointe vers les enregistrements plus anciens et `list_metadata.before` vers les plus récents (`null` lorsqu'il n'y en a pas). Aucun nombre total n'est renvoyé. Les champs vides sont `null`.

`ip`, `ip_asn`, `user_agent` et `user_agent_family` ne sont présents que si la clé dispose de l'autorisation `audit-events:read_ip`, et `identifier_hint` uniquement si elle dispose de `users:read_pii`. Sans cette autorisation, le champ est entièrement omis (aucune valeur masquée). `ip_country` est toujours renvoyé.

```json
{
  "data": [
    {
      "id": "evt_01j9xk3m7q8r2s4t6v8w0y2z4a",
      "occurred_at": "2026-10-01T08:15:42.120Z",
      "type": "authentication.password.failed",
      "outcome": "failure",
      "reason_code": "invalid_credentials",
      "user_id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p",
      "org_id": null,
      "application_id": "app_01j9xk3m7q8r2s4t6v8w0y2z4b",
      "connection_id": "conn_01j9xk3m7q8r2s4t6v8w0y2z4c",
      "directory_id": null,
      "session_id": null,
      "identifier_hint": "a***@e***.com",
      "ip": "203.0.113.7",
      "ip_country": "DE",
      "ip_asn": 64500,
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64)",
      "user_agent_family": "Firefox",
      "risk": null,
      "auth_context": null,
      "act_chain": null,
      "details": {"attempt": 3},
      "request_id": "0192a6c1-7d3e-7a10-9b2c-3d4e5f607182",
      "correlation_id": null,
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
    }
  ],
  "list_metadata": {
    "before": null,
    "after": "<opaque cursor>"
  }
}
```

## Erreurs

Chaque erreur est un corps `application/problem+json` accompagné d'un `code` stable.

| HTTP | `code` | Quand |
|---|---|---|
| 400 | `invalid_cursor` | Le curseur est mal formé ou n'a pas été émis pour cette requête. |
| 400 | `invalid_filter` | Le service de journaux a rejeté un filtre ou le curseur. |
| 400 | `range_outside_retention` | `from` est antérieur à la fenêtre de conservation de votre forfait. |
| 422 | `validation_failed` | Un paramètre de requête est invalide (`limit` hors plage, horodatage incorrect, `to` non postérieure à `from`, plus de 20 valeurs `type`, `org_id` mal formé, paramètre répété). |
| 401 | `unauthenticated` | La clé API est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de l'autorisation `logs:read`, ou `org_id` est défini et la clé ne dispose pas de `organizations:read`. `required_permissions` liste ce dont la requête a besoin. |
| 404 | `not_found` | L'identifiant de l'utilisateur est mal formé, ou `org_id` est défini et l'utilisateur n'est pas membre de cette organisation. |
| 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 "https://api.eu.keenauth.com/v1/users/usr_0a1b2c3d4e5f6g7h8j9k0m1n2p/logs?limit=50" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

Uniquement les enregistrements d'une organisation :

```bash
keenauth users logs list usr_0a1b2c3d4e5f6g7h8j9k0m1n2p --org-id org_01j9xk3m7q8r2s4t6v8w0y2z4d --type authentication.
```

## Données personnelles

Ce point de terminaison contient des données personnelles : les journaux de l'environnement. [Données personnelles dans les API KeenAuth](/docs/policies/personal-data) décrit ce qui est stocké, pendant combien de temps et comment elles sont supprimées. N'envoyez de catégories particulières de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.
