List users (admin)
/v1/admin/orgs/{slug}/usersReturns one page of local users using opaque cursor (keyset) pagination.
Bound the page size with limit and choose an ordering with sort (see
x-sort-fields for what this endpoint accepts; the user id is appended so
the ordering is total). Then walk the listing by passing the previous
response's page.next_cursor back as cursor for as long as
page.has_more is true; page.prev_cursor steps back the same way.
Defaults to id order, which for this server's time-ordered ids is creation
order. Requires the nauthera.users:read scope and the users.read
permission; the listing is confined to slug's organization. Password
hashes are never returned.
q narrows the listing to the users one of the match fields of whom
starts with it, case-insensitively; every character is matched
literally. The username is a field every caller may match on. The
display name and the email are personal data: only a caller holding the
users.pii.read permission may match on them, since a prefix search
would rebuild them one character at a time. Without match a search
matches every field the caller may match on; a match naming a field
the caller may not is refused with 403 rather than answered from the
others. A cursor is bound to the search and the fields it was issued
for, so send them with it; the order it carries itself.
The filters narrow the listing further and compose as a conjunction; a
filter taking several values matches any of them. status and locked
are decided at the moment of the request: a suspension whose end has
passed counts as active, and a lock whose deadline has passed does not
count. The time ranges include their start and exclude their end. A user
who never signed in has signed in before any instant, so
last_sign_in_to keeps them and last_sign_in_from does not. A cursor
is bound to the filters it was issued for as it is to the search.
last_login_at sorts users who never signed in before everyone else
ascending and after everyone else descending, among themselves by id.
The organization slug. It names the TENANT OF RECORD for the operation: the rows it reads and writes, the policy its secrets are derived under, and the organization its audit record is filed against all come from this organization. A token is admitted only through its own slug, except a main-org token, which may be admitted through any — so cross-tenant administration is performed through the TARGET tenant's slug, never by naming its resources through another. A token reaching for a slug it may not be admitted through is refused identically whether that organization exists or not.
1–64 characters
- limitinteger
Maximum number of items to return in one page (1–200; default 50). A value outside that range is rejected with a 400. It may be changed freely between pages of the same walk — a cursor marks a position, not a page number.
Default50between 1 and 200
- sortstring
Ordering for the listing: a comma-separated list of fields, most significant first, a leading
-marking a descending term. For examplesort=last_name,-first_namesorts by last name ascending, then by first name descending.Show moreShow less
Which fields a given endpoint accepts is listed in its
x-sort-fieldsextension; naming anything else is a 400. A field may appear only once.The server always appends the resource's primary key as a final term, so the ordering is TOTAL — rows that tie on every field you named still have a defined relative order, without which a page could skip or repeat them. The full ordering, including that appended term, is echoed as
page.sort.Send it on the FIRST request of a walk only: every cursor records the ordering it was issued under, so it carries forward automatically, and a
sortthat contradicts the suppliedcursoris rejected with a 400 rather than silently reordering mid-walk.Sortable fields:
created_at,email,id,last_login_at,username. Prefix a field with-to sort descending.at most 256 characters · pattern
^-?[a-z][a-z0-9_]*(,-?[a-z][a-z0-9_]*)*$ - cursorstring
Opaque keyset cursor identifying where a page begins. Omit it for the first page; afterwards pass the
next_cursor(orprev_cursor) value from the previous response verbatim — the token itself records which direction it steps in, so there is no separate direction parameter.Show moreShow less
The token is server-defined and MUST be treated as opaque: it is bound to the listing and sort order that issued it, and a cursor that is malformed, tampered with, or belongs to a different listing or order is rejected with a 400 rather than silently paging through the wrong set.
at most 1024 characters
- qstring
Narrow the listing to the users one of whose
matchfields starts with this text, compared case-insensitively. Every character is matched literally. A cursor is bound to the search it was issued for.2–100 characters
- matcharray of enums
The fields
qmatches on, comma-separated. Defaults to every field the caller may match on;display_nameandemailneed theusers.pii.readpermission. Ignored withoutq.Possible values"username""display_name""email"at most 3 items
- statusarray of enums
Account statuses in force now, comma-separated: a user whose status is any of them matches.
Possible values"active""suspended""blocked"at most 3 items
- lockedboolean
Only users the automatic lock after repeated wrong passwords refuses now (true), or only users it does not (false).
- second_factorboolean
Only users with an active second factor (true), or only users without one (false).
- created_fromstring · date-time
Only users created at or after this instant (RFC3339).
- created_tostring · date-time
Only users created before this instant (RFC3339).
- last_sign_in_fromstring · date-time
Only users whose last sign-in was at or after this instant (RFC3339). Users who never signed in do not match.
- last_sign_in_tostring · date-time
Only users whose last sign-in was before this instant (RFC3339), including users who never signed in.
- DPoPstring
DPoP proof JWT (RFC 9449 §4). REQUIRED on a request presenting a DPoP-bound access token, and it must be signed by the key named in the token's
cnf.jktand cover this request's method and URI. The proof is read from the request itself rather than from this decoded parameter, so every protected operation is covered whether or not it declares it.
200 OKapplication/jsonOne page of users.
One page of users.
Headers
Cache-Controlno-store
Body
One page of users under cursor (keyset) pagination:
itemsholds the page, ordered by the request'ssort, andpagesays where it sits in the listing. Followpage.next_cursorwhilepage.has_moreis true; there is no total to count towards.The users on this page.
Each item:A local user as seen by the admin API. The argon2id password hash is NEVER included.
attributesis the free-form string map stored on the identity (e.g. the display "name"). The nullable timestamps (locked_until, last_login_at) are omitted when unset. Admin access is not a property of the user: it follows the roles the user is granted in an organization (e.g. org-user-admin), which are resolved on every admin request.Show item attributesHide item attributes
The user id (UUID).
Example"3f1a5b2c-8d4e-4f6a-9b0c-1d2e3f4a5b6c"- Example
"alice@example.com" - Example
"alice@example.com" Whether the user has a password. An invited user has none until they accept the invitation, and an account an identity provider created has none at all.
Whether the user still waits on an invitation: they have no password and no linked identity provider account to sign in with.
Consecutive failed password verifications since the last success.
What an administrator decided about an account, separate from the automatic lock after repeated wrong passwords.
activemay sign in;suspendedmay not until it is reactivated or itssuspended_untilpasses, after which it readsactiveagain with no write in between;blockedmay not until it is reactivated. A suspended or blocked account can neither sign in nor obtain or renew a token through any grant. Translated undervocabulary.UserAccountStatus.<value>. Compatibility: closed. A client should render a value it does not know as unavailable rather than active.Possible values"active""suspended""blocked"- email_verified_atstring · date-time
When
emailwas proven to be the user's (RFC3339); omitted while it has not been. It is released as theemail_verifiedclaim, and a change of address clears it. - attributesmap of strings
Free-form string attributes stored on the identity.
- locked_untilstring · date-time
Soft-lock deadline (RFC3339); omitted when the account is not locked.
- last_login_atstring · date-time
Last successful sign-in (RFC3339); omitted when the user has never signed in.
- status_reasonstring
The administrator's note on the current status; omitted when there is none.
- suspended_untilstring · date-time
When a suspension lifts by itself (RFC3339); omitted when the account is not suspended or the suspension has no end.
- status_changed_atstring · date-time
When the status last changed (RFC3339); omitted when it never has.
Where one page sits in a cursor (keyset) paginated list, returned beside that page's
items.Show moreShow less
Walk a list by following
next_cursorfor as long ashas_moreis true, passing the token back verbatim as thecursorquery parameter. Keep the listing and its filters the same for the whole walk;limitMAY change between pages (a cursor marks a position, not a page number), andsorttravels in the cursor so it need not be resent.has_moreis authoritative: it is derived from whether a further row actually exists, so a page that happens to be full is not mistaken for a page that has a successor, and a walk never costs a trailing empty request.prev_cursorsteps back the same way.A cursor is opaque — server-defined, bound to this listing and sort order, and not parseable by clients. It stays valid across page-size changes but not across a change of sort order or filters; a cursor that does not belong to the request is rejected with a 400 rather than silently paging through the wrong set.
Keyset paging is stable under concurrent writes, with one qualification. A row whose SORT KEY does not change is returned exactly once for the whole walk. Rows created or deleted mid-walk may or may not appear, depending on which side of the cursor they fall — and so may a row whose sort key is UPDATED mid-walk, since that moves it across the boundary: it can be seen twice or missed. Sorting by a field that does not change (the default id ordering, or
created_at) avoids this entirely.Show child attributesHide child attributes
The page size in effect: the
limitthat was sent, or the server's default when it was omitted. Echoed so a client resuming from a stored cursor knows the page size without having to remember it.Example50The ordering this walk is pinned to, in the
sortparameter's syntax and INCLUDING the primary-key term the server appends to make it total. Cursors carry it, so it need only be sent on the first request.Example"last_name,-first_name,id"Whether a page follows this one and
next_cursorcan reach it. When false this is the last page andnext_cursoris absent.Whether a page precedes this one and
prev_cursorcan reach it. False on the first page of a walk.Show moreShow less
Both flags report REACHABILITY, not bare existence. A cursor that overshoots the set — a stale bookmark, or rows deleted mid-walk — returns an empty page with both flags false even though rows precede it, because an empty page has no row to anchor a cursor on. Restart the walk if you land there; a client following
has_morenever does.- next_cursorstring
Opaque cursor for the next page. Present exactly when
has_moreis true, and ABSENT (the field is omitted, not null) otherwise. Pass it back verbatim as thecursorquery parameter; never parse it.at most 512 characters
- prev_cursorstring
Opaque cursor for the previous page. Present exactly when
has_previs true, and absent otherwise. Passed back ascursor, exactly likenext_cursor— the token itself records which way it steps.at most 512 characters
400 Bad Requestapplication/problem+jsonThe pagination parameters or the search were invalid — a malformed or foreign cursor, a cursor contradicting
sort, asortnaming a field this endpoint does not accept or naming one twice, alimitoutside its declared range, aqoutside its declared length, amatchorstatusvalue outside its vocabulary, a malformed instant, or a range whose start is not before its end.The pagination parameters or the search were invalid — a malformed or foreign cursor, a cursor contradicting
sort, asortnaming a field this endpoint does not accept or naming one twice, alimitoutside its declared range, aqoutside its declared length, amatchorstatusvalue outside its vocabulary, a malformed instant, or a range whose start is not before its end.Body
RFC 9457 (formerly RFC 7807) problem details (application/problem+json).
codeis a stable machine-readable slug for the problem kind (it mirrors the suffix oftype), so consumers can branch on it without parsing prose.errorsis present on validation failures and lists every offending field.- Example
"Request validation failed" - Example
400 - typestring · uriExample
"urn:problem-type:validation_error" - detailstringExample
"One or more fields did not satisfy the API schema." - codeenum
The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing
titleordetail, which are English prose for logs. A problem whose status says everything the server knows carries nocode.Show moreShow less
validation_erroris the one code whose message is not a sentence about the code itself: the request failed the schema, and the specifics are theerrorslist — one entry per offending field — which a form renders on those fields.requiredandmalformedare spelled like two of the per-field violation codes (FieldError.code) but mean something else; the two vocabularies are told apart by position, never by spelling.Compatibility: this is a CLOSED enum, with the same cost as
AuditAction: a client generated against an older version of this document rejects a problem carrying a code added after it was built. Regenerate on upgrade, or decode the field as a plain string. It is enumerated anyway so that what a client must translate is knowable from the contract alone.Possible values"invalid_request""invalid_credentials""forbidden""unauthorized""insufficient_user_authentication""protected_account""last_role_administrator""invalid_code""too_many_requests""too_many_attempts""account_locked""account_unavailable""already_enrolled""registration_disabled""registration_conflict""captcha_failed""invalid_reset_link""invalid_verification_link""invalid_invitation_link""mail_relay_missing""not_found""conflict""unavailable""busy""window_too_large""too_many_series""internal_error""rate_limited""malformed""body_too_large""required""validation_error""unknown_org""invalid_token""invalid_dpop_proof""use_dpop_nonce""server_error" - instancestringExample
"/introspect" - request_idstringExample
"8d94ed49-1caf-4ab3-9594-557142f2d023" - trace_idstring
Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share.
Example"4bf92f3577b34da6a3ce929d0e0e4736" - errorsarray of objects
Field-level violations (present for validation errors).
Each item:A single field-level validation violation.
Show item attributesHide item attributes
Offending field, dotted for nested bodies (e.g. child.id).
Example"token_type_hint"Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed.
Example"not_allowed"- Example
"field token_type_hint must be one of [access_token, refresh_token]"
401 Unauthorizedapplication/problem+jsonProblem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.
Headers
Cache-Controlno-storeWWW-AuthenticatestringDPoP-Noncestring
Body
RFC 9457 (formerly RFC 7807) problem details (application/problem+json).
codeis a stable machine-readable slug for the problem kind (it mirrors the suffix oftype), so consumers can branch on it without parsing prose.errorsis present on validation failures and lists every offending field.- Example
"Request validation failed" - Example
400 - typestring · uriExample
"urn:problem-type:validation_error" - detailstringExample
"One or more fields did not satisfy the API schema." - codeenum
The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing
titleordetail, which are English prose for logs. A problem whose status says everything the server knows carries nocode.Show moreShow less
validation_erroris the one code whose message is not a sentence about the code itself: the request failed the schema, and the specifics are theerrorslist — one entry per offending field — which a form renders on those fields.requiredandmalformedare spelled like two of the per-field violation codes (FieldError.code) but mean something else; the two vocabularies are told apart by position, never by spelling.Compatibility: this is a CLOSED enum, with the same cost as
AuditAction: a client generated against an older version of this document rejects a problem carrying a code added after it was built. Regenerate on upgrade, or decode the field as a plain string. It is enumerated anyway so that what a client must translate is knowable from the contract alone.Possible values"invalid_request""invalid_credentials""forbidden""unauthorized""insufficient_user_authentication""protected_account""last_role_administrator""invalid_code""too_many_requests""too_many_attempts""account_locked""account_unavailable""already_enrolled""registration_disabled""registration_conflict""captcha_failed""invalid_reset_link""invalid_verification_link""invalid_invitation_link""mail_relay_missing""not_found""conflict""unavailable""busy""window_too_large""too_many_series""internal_error""rate_limited""malformed""body_too_large""required""validation_error""unknown_org""invalid_token""invalid_dpop_proof""use_dpop_nonce""server_error" - instancestringExample
"/introspect" - request_idstringExample
"8d94ed49-1caf-4ab3-9594-557142f2d023" - trace_idstring
Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share.
Example"4bf92f3577b34da6a3ce929d0e0e4736" - errorsarray of objects
Field-level violations (present for validation errors).
Each item:A single field-level validation violation.
Show item attributesHide item attributes
Offending field, dotted for nested bodies (e.g. child.id).
Example"token_type_hint"Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed.
Example"not_allowed"- Example
"field token_type_hint must be one of [access_token, refresh_token]"
403 Forbiddenapplication/problem+jsonProblem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.
Headers
Cache-Controlno-storeWWW-AuthenticatestringDPoP-Noncestring
Body
RFC 9457 (formerly RFC 7807) problem details (application/problem+json).
codeis a stable machine-readable slug for the problem kind (it mirrors the suffix oftype), so consumers can branch on it without parsing prose.errorsis present on validation failures and lists every offending field.- Example
"Request validation failed" - Example
400 - typestring · uriExample
"urn:problem-type:validation_error" - detailstringExample
"One or more fields did not satisfy the API schema." - codeenum
The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing
titleordetail, which are English prose for logs. A problem whose status says everything the server knows carries nocode.Show moreShow less
validation_erroris the one code whose message is not a sentence about the code itself: the request failed the schema, and the specifics are theerrorslist — one entry per offending field — which a form renders on those fields.requiredandmalformedare spelled like two of the per-field violation codes (FieldError.code) but mean something else; the two vocabularies are told apart by position, never by spelling.Compatibility: this is a CLOSED enum, with the same cost as
AuditAction: a client generated against an older version of this document rejects a problem carrying a code added after it was built. Regenerate on upgrade, or decode the field as a plain string. It is enumerated anyway so that what a client must translate is knowable from the contract alone.Possible values"invalid_request""invalid_credentials""forbidden""unauthorized""insufficient_user_authentication""protected_account""last_role_administrator""invalid_code""too_many_requests""too_many_attempts""account_locked""account_unavailable""already_enrolled""registration_disabled""registration_conflict""captcha_failed""invalid_reset_link""invalid_verification_link""invalid_invitation_link""mail_relay_missing""not_found""conflict""unavailable""busy""window_too_large""too_many_series""internal_error""rate_limited""malformed""body_too_large""required""validation_error""unknown_org""invalid_token""invalid_dpop_proof""use_dpop_nonce""server_error" - instancestringExample
"/introspect" - request_idstringExample
"8d94ed49-1caf-4ab3-9594-557142f2d023" - trace_idstring
Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share.
Example"4bf92f3577b34da6a3ce929d0e0e4736" - errorsarray of objects
Field-level violations (present for validation errors).
Each item:A single field-level validation violation.
Show item attributesHide item attributes
Offending field, dotted for nested bodies (e.g. child.id).
Example"token_type_hint"Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed.
Example"not_allowed"- Example
"field token_type_hint must be one of [access_token, refresh_token]"
429 Too Many Requestsapplication/problem+jsonToo many requests.
Too many requests.
Body
RFC 9457 (formerly RFC 7807) problem details (application/problem+json).
codeis a stable machine-readable slug for the problem kind (it mirrors the suffix oftype), so consumers can branch on it without parsing prose.errorsis present on validation failures and lists every offending field.- Example
"Request validation failed" - Example
400 - typestring · uriExample
"urn:problem-type:validation_error" - detailstringExample
"One or more fields did not satisfy the API schema." - codeenum
The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing
titleordetail, which are English prose for logs. A problem whose status says everything the server knows carries nocode.Show moreShow less
validation_erroris the one code whose message is not a sentence about the code itself: the request failed the schema, and the specifics are theerrorslist — one entry per offending field — which a form renders on those fields.requiredandmalformedare spelled like two of the per-field violation codes (FieldError.code) but mean something else; the two vocabularies are told apart by position, never by spelling.Compatibility: this is a CLOSED enum, with the same cost as
AuditAction: a client generated against an older version of this document rejects a problem carrying a code added after it was built. Regenerate on upgrade, or decode the field as a plain string. It is enumerated anyway so that what a client must translate is knowable from the contract alone.Possible values"invalid_request""invalid_credentials""forbidden""unauthorized""insufficient_user_authentication""protected_account""last_role_administrator""invalid_code""too_many_requests""too_many_attempts""account_locked""account_unavailable""already_enrolled""registration_disabled""registration_conflict""captcha_failed""invalid_reset_link""invalid_verification_link""invalid_invitation_link""mail_relay_missing""not_found""conflict""unavailable""busy""window_too_large""too_many_series""internal_error""rate_limited""malformed""body_too_large""required""validation_error""unknown_org""invalid_token""invalid_dpop_proof""use_dpop_nonce""server_error" - instancestringExample
"/introspect" - request_idstringExample
"8d94ed49-1caf-4ab3-9594-557142f2d023" - trace_idstring
Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share.
Example"4bf92f3577b34da6a3ce929d0e0e4736" - errorsarray of objects
Field-level violations (present for validation errors).
Each item:A single field-level validation violation.
Show item attributesHide item attributes
Offending field, dotted for nested bodies (e.g. child.id).
Example"token_type_hint"Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed.
Example"not_allowed"- Example
"field token_type_hint must be one of [access_token, refresh_token]"
Errorapplication/problem+jsonProblem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.
Headers
Cache-Controlno-storeWWW-AuthenticatestringDPoP-Noncestring
Body
RFC 9457 (formerly RFC 7807) problem details (application/problem+json).
codeis a stable machine-readable slug for the problem kind (it mirrors the suffix oftype), so consumers can branch on it without parsing prose.errorsis present on validation failures and lists every offending field.- Example
"Request validation failed" - Example
400 - typestring · uriExample
"urn:problem-type:validation_error" - detailstringExample
"One or more fields did not satisfy the API schema." - codeenum
The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing
titleordetail, which are English prose for logs. A problem whose status says everything the server knows carries nocode.Show moreShow less
validation_erroris the one code whose message is not a sentence about the code itself: the request failed the schema, and the specifics are theerrorslist — one entry per offending field — which a form renders on those fields.requiredandmalformedare spelled like two of the per-field violation codes (FieldError.code) but mean something else; the two vocabularies are told apart by position, never by spelling.Compatibility: this is a CLOSED enum, with the same cost as
AuditAction: a client generated against an older version of this document rejects a problem carrying a code added after it was built. Regenerate on upgrade, or decode the field as a plain string. It is enumerated anyway so that what a client must translate is knowable from the contract alone.Possible values"invalid_request""invalid_credentials""forbidden""unauthorized""insufficient_user_authentication""protected_account""last_role_administrator""invalid_code""too_many_requests""too_many_attempts""account_locked""account_unavailable""already_enrolled""registration_disabled""registration_conflict""captcha_failed""invalid_reset_link""invalid_verification_link""invalid_invitation_link""mail_relay_missing""not_found""conflict""unavailable""busy""window_too_large""too_many_series""internal_error""rate_limited""malformed""body_too_large""required""validation_error""unknown_org""invalid_token""invalid_dpop_proof""use_dpop_nonce""server_error" - instancestringExample
"/introspect" - request_idstringExample
"8d94ed49-1caf-4ab3-9594-557142f2d023" - trace_idstring
Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share.
Example"4bf92f3577b34da6a3ce929d0e0e4736" - errorsarray of objects
Field-level violations (present for validation errors).
Each item:A single field-level validation violation.
Show item attributesHide item attributes
Offending field, dotted for nested bodies (e.g. child.id).
Example"token_type_hint"Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed.
Example"not_allowed"- Example
"field token_type_hint must be one of [access_token, refresh_token]"