Inactive members report
GET /v1/reports/inactive-members · permission reports:read
Lists the active members of an organization who have had no successful sign-in in that organization for the last days days. Use it to find accounts to remove when a connection has no SCIM provisioning: review the list, then suspend the selected memberships with POST /v1/organizations/{org_id}/memberships/{membership_id}:suspend.
The environment always comes from the API key; there is no environment parameter. Rows contain only identifiers and timestamps, no name, email address, IP address or User-Agent. Because user identifiers are personal data, the report is limited to keys with reports:read.
What counts as a sign-in
A successful authentication counts when it completed in the context of this organization. A sign-in without an organization selected does not count. A membership whose activation (activated_at, or its creation time when it was never activated) is newer than the threshold is not listed, so a member who joined yesterday never shows up in a 30-day report.
Request
| Parameter | In | Required | Description |
|---|---|---|---|
organization_id |
query | yes | The organization (org_…). |
days |
query | no | Inactivity threshold in days, 7 to 365. Default 30. |
limit |
query | no | Page size, 1 to 100. Default 50. |
cursor |
query | no | next_cursor of the previous page. Valid only for the environment, organization_id and days it was issued for. |
Rows follow the order in which memberships were last updated. The threshold (inactive_since) is calculated once, on the first page, and carried in the cursor, so every page of one report uses the same instant.
A page scans at most 500 memberships and can return fewer rows than limit, even none. Keep following next_cursor until it is null.
Response
200 OK.
| Field | Description |
|---|---|
organization_id |
The organization of the report. |
days |
The threshold used. |
inactive_since |
The threshold instant (request time minus days, RFC 3339, UTC). Members with no sign-in since then are listed. |
data_since |
Time of the first successful authentication recorded for the environment; sign-ins before it are unknown. null when the environment has no record yet. |
complete |
true when data_since is not after inactive_since, so the list covers the whole threshold window. |
data |
The rows on this page (see below). |
next_cursor |
Cursor for the next page, null on the last page. |
Each row in data:
| Field | Description |
|---|---|
membership_id |
mem_…. |
user_id |
usr_…. |
activated_at |
When the membership became active (its creation time when it was never activated). |
last_authenticated_at |
Last successful authentication in this organization, or null when none has been recorded since data_since. |
When complete is false, a listed member may have signed in before data_since, so do not treat the list as final. When data_since is null, no sign-in has been recorded for the environment yet and every member old enough is listed.
{
"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
}
Errors
Every error is an application/problem+json body with a stable code.
| HTTP | code |
When |
|---|---|---|
| 400 | invalid_cursor |
The cursor is malformed or was issued for another environment, organization or days. |
| 404 | not_found |
The organization does not exist, or belongs to another environment. |
| 422 | validation_failed |
organization_id is missing or malformed, days or limit is out of range, or a parameter is repeated. |
| 401 | unauthenticated |
The API key is missing, invalid or revoked. |
| 403 | insufficient_permissions |
The key lacks reports:read. |
| 429 | rate_limited |
The rate limit was exceeded; honor Retry-After. |
| 503 | service_unavailable |
The reporting service is temporarily unavailable; retry later. |
Example
curl "https://api.eu.keenauth.com/v1/reports/inactive-members?organization_id=org_01j9xk3m7q8r2s4t6v8w0y2z4d&days=60" \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
keenauth reports inactive-members org_01j9xk3m7q8r2s4t6v8w0y2z4d --days 60
Personal data
This endpoint carries personal data: organization memberships and invitations (user and membership identifiers with sign-in times). Personal data in the KeenAuth APIs describes what is stored, how long it is kept and how it is deleted. Do not send special categories of personal data (health, biometric data, religion, political opinions, sexual orientation) in any field.