
# 비활성 회원 보고서

`GET /v1/reports/inactive-members` · 권한 `reports:read`

최근 `days`일 동안 해당 조직에서 성공적으로 로그인하지 않은 조직의 활성 회원을 나열합니다. SCIM 프로비저닝이 없는 연결에서 제거할 계정을 찾을 때 사용하십시오. 목록을 검토한 다음 선택한 멤버십은 `POST /v1/organizations/{org_id}/memberships/{membership_id}:suspend`로 일시 중지하십시오.

환경은 항상 API 키에서 결정되며 환경 매개변수는 없습니다. 행에는 식별자와 타임스탬프만 포함되며 이름, 이메일 주소, IP 주소 또는 `User-Agent`는 포함되지 않습니다. 사용자 식별자는 개인정보이므로 이 보고서는 `reports:read` 권한이 있는 키로만 제한됩니다.

## 로그인으로 간주되는 기준

이 조직의 컨텍스트에서 완료된 인증만 로그인으로 간주됩니다. 조직을 선택하지 않은 로그인은 집계되지 않습니다. 활성화 시각(`activated_at`, 또는 한 번도 활성화되지 않은 경우 생성 시각)이 기준 기간보다 최근인 멤버십은 나열되지 않습니다. 따라서 어제 합류한 회원은 30일 보고서에 나타나지 않습니다.

## 요청

| 매개변수 | 위치 | 필수 | 설명 |
|---|---|---|---|
| `organization_id` | query | 예 | 조직(`org_…`)입니다. |
| `days` | query | 아니요 | 비활성 기준 기간(일), 7~365. 기본값 30. |
| `limit` | query | 아니요 | 페이지 크기, 1~100. 기본값 50. |
| `cursor` | query | 아니요 | 이전 페이지의 `next_cursor`입니다. 발급된 환경, `organization_id` 및 `days`에 대해서만 유효합니다. |

행은 멤버십이 마지막으로 업데이트된 순서를 따릅니다. 기준 시점(`inactive_since`)은 첫 페이지에서 한 번 계산되어 커서에 담기므로, 하나의 보고서에 속한 모든 페이지가 같은 시점을 사용합니다.

한 페이지는 최대 500개의 멤버십을 검사하므로 `limit`보다 적은 행, 심지어 행이 없을 수도 있습니다. `next_cursor`가 `null`가 될 때까지 계속 따라가십시오.

## 응답

`200 OK`.

| 필드 | 설명 |
|---|---|
| `organization_id` | 보고서의 조직입니다. |
| `days` | 사용된 기준 기간입니다. |
| `inactive_since` | 기준 시점(요청 시각에서 `days` 값을 뺀 시점, RFC 3339, UTC)입니다. 이 시점 이후 로그인하지 않은 회원이 나열됩니다. |
| `data_since` | 환경에 기록된 첫 번째 성공 인증 시각입니다. 이전 로그인은 알 수 없습니다. 환경에 기록이 아직 없으면 `null`입니다. |
| `complete` | `data_since`가 `inactive_since` 이후가 아니면 `true`입니다. 따라서 목록이 기준 기간 전체를 포함합니다. |
| `data` | 이 페이지의 행입니다(아래 참조). |
| `next_cursor` | 다음 페이지의 커서이며, 마지막 페이지에서는 `null`입니다. |

`data`의 각 행:

| 필드 | 설명 |
|---|---|
| `membership_id` | `mem_…`. |
| `user_id` | `usr_…`. |
| `activated_at` | 멤버십이 활성화된 시각입니다(한 번도 활성화되지 않은 경우 생성 시각). |
| `last_authenticated_at` | 이 조직에서의 마지막 성공 인증입니다. `data_since` 이후 기록된 인증이 없으면 `null`입니다. |

`complete`이(가) `false`인 경우 나열된 회원이 `data_since` 이전에 로그인했을 수 있으므로 목록을 최종 결과로 간주하지 마십시오. `data_since`이(가) `null`인 경우 환경에 아직 로그인이 기록되지 않은 것이므로 기준 기간을 충족하는 모든 회원이 나열됩니다.

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

## 오류

모든 오류는 안정적인 `code`가 포함된 `application/problem+json` 본문으로 반환됩니다.

| HTTP | `code` | 발생 조건 |
|---|---|---|
| 400 | `invalid_cursor` | 커서 형식이 잘못되었거나 다른 환경, 조직 또는 `days`에 대해 발급된 경우입니다. |
| 404 | `not_found` | 조직이 존재하지 않거나 다른 환경에 속한 경우입니다. |
| 422 | `validation_failed` | `organization_id`이(가) 없거나 형식이 잘못되었거나, `days` 또는 `limit`이(가) 범위를 벗어났거나, 매개변수가 반복된 경우입니다. |
| 401 | `unauthenticated` | API 키가 없거나 유효하지 않거나 폐기된 경우입니다. |
| 403 | `insufficient_permissions` | 키에 `reports:read` 권한이 없는 경우입니다. |
| 429 | `rate_limited` | 요청 한도를 초과한 경우입니다. `Retry-After`를 준수하십시오. |
| 503 | `service_unavailable` | 보고 서비스를 일시적으로 사용할 수 없습니다. 나중에 다시 시도하십시오. |

## 예제

```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
```

## 개인정보

이 엔드포인트는 개인정보를 포함합니다. 조직 멤버십과 초대(로그인 시각이 포함된 사용자 및 멤버십 식별자)가 여기에 해당합니다. [KeenAuth API의 개인정보](/docs/policies/personal-data)에서는 저장되는 항목, 보관 기간 및 삭제 방법을 설명합니다. 어떤 필드에도 특수 범주의 개인정보(건강, 생체 정보, 종교, 정치적 견해, 성적 지향)를 전송하지 마십시오.
