
# Rapport des membres inactifs

`GET /v1/reports/inactive-members` · autorisation `reports:read`

Liste les membres actifs d'une organisation qui n'ont eu aucune connexion réussie dans cette organisation au cours des `days` derniers jours. Utilisez-le pour repérer les comptes à supprimer lorsqu'une connexion ne dispose pas de provisionnement SCIM : examinez la liste, puis suspendez les adhésions sélectionnées avec `POST /v1/organizations/{org_id}/memberships/{membership_id}:suspend`.

L'environnement provient toujours de la clé d'API ; il n'existe aucun paramètre d'environnement. Les lignes ne contiennent que des identifiants et des horodatages, sans nom, adresse e-mail, adresse IP ni `User-Agent`. Les identifiants d'utilisateur étant des données personnelles, le rapport est limité aux clés disposant de `reports:read`.

## Ce qui compte comme connexion

Une authentification réussie compte lorsqu'elle a été effectuée dans le contexte de cette organisation. Une connexion effectuée sans organisation sélectionnée ne compte pas. Une adhésion dont l'activation (`activated_at`, ou sa date de création si elle n'a jamais été activée) est postérieure au seuil n'est pas listée ; ainsi, un membre arrivé hier n'apparaît jamais dans un rapport de 30 jours.

## Requête

| Paramètre | Dans | Requis | Description |
|---|---|---|---|
| `organization_id` | query | oui | L'organisation (`org_…`). |
| `days` | query | non | Seuil d'inactivité en jours, de 7 à 365. Valeur par défaut : 30. |
| `limit` | query | non | Taille de page, de 1 à 100. Valeur par défaut : 50. |
| `cursor` | query | non | `next_cursor` de la page précédente. Valide uniquement pour l'environnement, `organization_id` et `days` pour lesquels il a été émis. |

Les lignes suivent l'ordre de la dernière mise à jour des adhésions. Le seuil (`inactive_since`) est calculé une seule fois, sur la première page, et transporté dans le curseur ; ainsi, toutes les pages d'un même rapport utilisent le même instant.

Une page analyse au plus 500 adhésions et peut renvoyer moins de lignes que `limit`, voire aucune. Continuez à suivre `next_cursor` jusqu'à ce qu'il soit `null`.

## Réponse

`200 OK`.

| Champ | Description |
|---|---|
| `organization_id` | L'organisation du rapport. |
| `days` | Le seuil utilisé. |
| `inactive_since` | L'instant du seuil (heure de la requête moins `days`, RFC 3339, UTC). Les membres sans connexion depuis cet instant sont listés. |
| `data_since` | Heure de la première authentification réussie enregistrée pour l'environnement ; les connexions antérieures sont inconnues. `null` lorsque l'environnement n'a encore aucun enregistrement. |
| `complete` | `true` lorsque `data_since` n'est pas postérieur à `inactive_since`, de sorte que la liste couvre toute la fenêtre du seuil. |
| `data` | Les lignes de cette page (voir ci-dessous). |
| `next_cursor` | Curseur de la page suivante, `null` sur la dernière page. |

Chaque ligne de `data` :

| Champ | Description |
|---|---|
| `membership_id` | `mem_…`. |
| `user_id` | `usr_…`. |
| `activated_at` | Date d'activation de l'adhésion (sa date de création si elle n'a jamais été activée). |
| `last_authenticated_at` | Dernière authentification réussie dans cette organisation, ou `null` si aucune n'a été enregistrée depuis `data_since`. |

Lorsque `complete` est `false`, un membre listé peut s'être connecté avant `data_since` ; ne considérez donc pas la liste comme définitive. Lorsque `data_since` est `null`, aucune connexion n'a encore été enregistrée pour l'environnement et tous les membres suffisamment anciens sont listés.

```json
{
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4d",
  "days": 30,
  "inactive_since": "2027-02-03T09:30:00Z",
  "data_since": "2026-12-01T08:00:00Z",
  "complete": true,
  "data": [
    {
      "membership_id": "mem_01j9xk3m7q8r2s4t6v8w0y2z4e",
      "user_id": "usr_01j9xk3m7q8r2s4t6v8w0y2z4f",
      "activated_at": "2026-12-10T10:00:00Z",
      "last_authenticated_at": "2027-01-05T17:45:00Z"
    }
  ],
  "next_cursor": null
}
```

## Erreurs

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

| HTTP | `code` | Quand |
|---|---|---|
| 400 | `invalid_cursor` | Le curseur est mal formé ou a été émis pour un autre environnement, une autre organisation ou `days`. |
| 404 | `not_found` | L'organisation n'existe pas ou appartient à un autre environnement. |
| 422 | `validation_failed` | `organization_id` est absent ou mal formé, `days` ou `limit` est hors plage, ou un paramètre est répété. |
| 401 | `unauthenticated` | La clé d'API est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de `reports:read`. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; respectez `Retry-After`. |
| 503 | `service_unavailable` | Le service de génération de rapports est temporairement indisponible ; réessayez plus tard. |

## Exemple

```bash
curl "https://api.eu.keenauth.com/v1/reports/inactive-members?organization_id=org_01j9xk3m7q8r2s4t6v8w0y2z4d&days=60" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth reports inactive-members org_01j9xk3m7q8r2s4t6v8w0y2z4d --days 60
```

## Données personnelles

Ce point de terminaison traite des données personnelles : adhésions et invitations à une organisation (identifiants d'utilisateur et d'adhésion avec horodatages de connexion). [Données personnelles dans les API KeenAuth](/docs/policies/personal-data) décrit les données conservées, leur durée de conservation et leur suppression. N'envoyez aucune catégorie particulière de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.
