List directory users
GET /v1/directories/{directory_id}/users · permission directories:read
Lists the live user records the identity provider provisioned into the directory, ordered by ID: the normalized attributes, the user's directory groups, the link to the environment user and the drift flag. Deleted records are not returned. The state and group_id filters can be combined. Only forward paging exists; the cursor is bound to the directory and the filters.
Without the users:read_pii permission the credential receives masked personal data: user_name as its first character and ***, emails[].value as a***@e***.com, given_name, family_name and display_name as initials, and attributes as null. external_id, locale, zoneinfo, the groups and the IDs are never masked. A secret key carries every permission.
Request
| Field | Type | Required | Description |
|---|---|---|---|
directory_id |
path | yes | SCIM directory ID (dir_…). |
state |
query | no | Only users in this state: active, inactive or held (in a mass deprovision hold). |
group_id |
query | no | Only members of this directory group (dsg_…); a group of another directory returns an empty page. |
limit |
query | no | 1–100, default 20. |
after |
query | no | The cursor from list_metadata.after. |
There is no request body.
Response
200 OK with a page of directory users.
{
"data": [
{
"id": "dsu_01j9xp4q6r8s0t2v4w6x8y0z2b",
"directory_id": "dir_01j9xm2n4p6q8r0s2t4v6w8y0z",
"external_id": "00u1a2b3c4",
"user_name": "jane@example.com",
"emails": [{ "value": "jane@example.com", "primary": true }],
"given_name": "Jane",
"family_name": "Doe",
"display_name": "Jane Doe",
"locale": "en-US",
"zoneinfo": "Europe/Berlin",
"state": "active",
"attributes": { "department": "Engineering" },
"groups": [{ "id": "dsg_01j9xn3p5q7r9s1t3v5w7x9y1a", "name": "Engineering" }],
"user_id": "usr_01j9xq5r7s9t1v3w5x7y9z1a3c",
"link_status": "linked",
"drift": false,
"created_at": "2026-10-20T09:00:00Z",
"updated_at": "2026-10-20T09:05:00Z"
}
],
"list_metadata": {
"before": null,
"after": null
}
}
link_status is one of linked, invited, blocked_other_org, duplicate, mirror_only or unlinked; user_id is null when the record is not linked. Empty values are null.
Errors
| HTTP | code | When |
|---|---|---|
| 400 | invalid_cursor |
The cursor is invalid or belongs to another directory or filter. |
| 404 | not_found |
The directory does not exist in this environment. |
| 422 | validation_failed |
state or group_id is invalid or repeated, limit is out of range, or before or order was given (unsupported). |
| 401 | unauthenticated |
The credential is missing, invalid or revoked. |
| 403 | insufficient_permissions |
The credential lacks the required permission. |
| 429 | rate_limited |
The rate limit was exceeded; retry after the Retry-After period. |
| 503 | service_unavailable |
Directory sync is temporarily unavailable or not configured in this deployment; retry after the Retry-After period. |
Example
curl -i "https://api.eu.keenauth.com/v1/directories/dir_01j9xm2n4p6q8r0s2t4v6w8y0z/users?state=active&limit=20" \
-H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
Personal data
This endpoint carries personal data: directory (SCIM) users. 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.