Skip to content

Users, roles and keys ​

Users, roles and their mappings, API keys and everyone's sessions.

GET /v1/keys ​

List API keys.

Each key's lastUsed is when it last signed a request in, written at most once a minute (absent for never); rotatedFrom names the key a rotation replaced.

Responses

StatusDescriptionBody
200Keys, without secrets, each with its own rateLimits when it has any
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

POST /v1/keys ​

Create an API key.

Request body (application/json)

FieldTypeRequiredDescription
namestringyes
kindkey, agentDefault "key".
onBehalfOfstringAgent keys only. The user the agent acts for; its access is capped by theirs.
assignmentsarray of object
assignments[].rolestring
assignments[].environmentsarray of string
expiresAtstring (date-time)When the key stops working. Omit for a key that doesn't expire.
rateLimitsRateLimits

Responses

StatusDescriptionBody
201Key shown once; the record has createdAt, expiresAt and rateLimits
400rateLimits names a class that doesn't exist, or a negative rate
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

PATCH /v1/keys/{id} ​

Change an API key's own rate limits.

rateLimits replaces the key's own limits; {} goes back to limits.rate for every class. They apply from the key's next request, and only to that key: an agent key's limits don't change those of the user it acts for. Needs user.manage; audited as key.rate-limits <id>.

Parameters

NameInTypeRequiredDescription
idpathstringyes

Request body (application/json)

FieldTypeRequiredDescription
rateLimitsRateLimitsyes

Responses

StatusDescriptionBody
200The key's record, without its secret
400No rateLimits, a class that doesn't exist, or a negative rate
404No such key
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/keys/{id} ​

Revoke an API key.

The key stops working at once. Needs user.manage.

Parameters

NameInTypeRequiredDescription
idpathstringyes

Responses

StatusDescriptionBody
204Revoked
404No such key
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

GET /v1/users ​

Users (user.manage).

password says whether the user has one. identities are the OIDC identities that sign them in ({provider, issuer, subject, email, linkedAt}); invites bind one at the user's first sign-in through a provider ({provider, email}). mapped are the assignments the provider's role rules gave at their last sign-in: they add to assignments, and only the IdP changes them. lastSignIn is when the user last signed in, by any method (null for never).

Users come by name, a page at a time: next, when there is one, is the cursor of the page after.

Parameters

NameInTypeRequiredDescription
qquerystringOnly users whose name, or an identity's or invite's email, contains this, ignoring case
cursorquerystringThe next a previous page answered
limitqueryinteger

Responses

StatusDescriptionBody
200{users: [{username, assignments, disabled, mustChangePassword, password, identities, invites, mapped, mfa, lastSignIn}], next?}
400A limit out of range, or a cursor this list didn't give
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

POST /v1/users ​

Create a user (user.manage).

Give a password, or an invite instead: the user's first sign-in through that provider, with that email (verified, or the provider has trustEmail), binds their identity. An invited user without a password signs in only through providers.

Request body (application/json)

FieldTypeRequiredDescription
usernamestringyes
passwordstring
assignmentsarray of object
assignments[].rolestring
assignments[].environmentsarray of string
mustChangePasswordbooleanThe user chooses their own password at the first sign-in. Default true.
inviteobject
invite.providerstringyesA configured provider's id.
invite.emailstringyes

Responses

StatusDescriptionBody
201The user
400A bad username or password, an unknown role or provider, or neither a password nor an invite
409The username is taken, or another user has the same invite
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

GET /v1/users/{name} ​

One user (user.manage).

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
200The user
404No such user
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

PATCH /v1/users/{name} ​

Change a user's roles, disable or enable them, set a password, or change their invites (user.manage).

Fields left out don't change. A password set here must be changed at the user's next sign-in. Disabling a user or setting their password ends their sessions; a disabled user's agent keys have no access. The last enabled user who can manage users can't be disabled or lose that permission (409). invites replace the user's invites; an invite from a provider the user already has an identity from, or one another user has, is refused (409). mapped roles can't be changed here.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Request body (application/json)

FieldTypeRequiredDescription
assignmentsarray of object
assignments[].rolestring
assignments[].environmentsarray of string
disabledboolean
passwordstring
invitesarray of object
invites[].providerstringyes
invites[].emailstringyes

Responses

StatusDescriptionBody
200The user
404No such user
409The last user who can manage users, or an invite that clashes
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/users/{name} ​

Delete a user (user.manage).

Ends their sessions. Refused (409) for the last user who can manage users, and while agent keys act for the user: revoke those first.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
204Deleted
404No such user
409The last user who can manage users, or agent keys act for them
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/users/{name}/identities/{provider} ​

Unlink a user's identity from a provider (user.manage).

The user may be left with no way to sign in; an invite or a password gives them one.

Parameters

NameInTypeRequiredDescription
namepathstringyes
providerpathstringyes

Responses

StatusDescriptionBody
204Unlinked
404No such user, or no identity from this provider
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

GET /v1/users/{name}/sessions ​

A user's sessions.

Needs user.manage. {sessions: [Session]}, as GET /v1/me/sessions shows a user their own.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
200The sessionsobject
403The caller lacks user.manage
404No such user
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

200 body (application/json)

FieldTypeRequiredDescription
sessionsarray of Session

DELETE /v1/users/{name}/sessions ​

End all of a user's sessions.

Needs user.manage. Ends every session of the user's, on every node; each is audited as user.sign-out <name> (session <id>) (by <admin>). Answers {ended}.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
200
403The caller lacks user.manage
404No such user
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/users/{name}/sessions/{id} ​

End one of a user's sessions.

Needs user.manage. Audited as user.sign-out <name> (session <id>) (by <admin>).

Parameters

NameInTypeRequiredDescription
namepathstringyes
idpathstringyes

Responses

StatusDescriptionBody
204Ended
403The caller lacks user.manage
404No such user, or no session with this id
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/users/{name}/mfa ​

Reset a user's MFA.

Needs user.manage. Removes every factor and recovery code of a user who lost theirs, and ends their sessions; the audit entry is user.mfa-reset <name>. Under auth.mfa admins or required, the user enrols again at their next sign-in. For admin.username while reportd is stopped, use reportd mfa reset <user>.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
204Reset
403The caller lacks user.manage
404No such user, or the user has no MFA
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

PUT /v1/roles/{name} ​

Change a custom role's permissions.

Needs user.manage. permissions replaces the role's; whoever holds it has the new ones from their next request. Built-in roles don't change. A change that would leave no enabled user with user.manage, or make designers past the licence's seats, is refused. Audited as role.change <name>.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Request body (application/json)

FieldTypeRequiredDescription
permissionsarray of stringyes

Responses

StatusDescriptionBody
200
400built-in-role, or an unknown permission
403The caller lacks user.manage
404No such role
409No one would be left who can manage users, or licence-limit (designer seats)
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

DELETE /v1/roles/{name} ​

Delete a custom role.

Needs user.manage. Only a custom role that no user or key holds, granted or mapped from an IdP, can be deleted; built-in roles stay. Audited as role.delete <name>.

Parameters

NameInTypeRequiredDescription
namepathstringyes

Responses

StatusDescriptionBody
204Deleted
400built-in-role
403The caller lacks user.manage
404No such role
409role-in-useobject
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

GET /v1/roles/mappings ​

Each SSO provider's role rules.

Needs user.manage. Each OIDC provider's claim and SAML provider's attribute, the rules that map its values to roles, and the default for a user no rule matches, as auth.oidc and auth.saml configure them. They are shown, not changed, here: the roles they gave each user are the users' mapped.

Responses

StatusDescriptionBody
200The providers' rulesobject
403The caller lacks user.manage
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

200 body (application/json)

FieldTypeRequiredDescription
providersarray of object
providers[].idstring
providers[].namestring
providers[].kindoidc, saml
providers[].claimstringOIDC only.
providers[].attributestringSAML only.
providers[].rulesarray of object
providers[].rules[].valuestring
providers[].rules[].rolestring
providers[].rules[].environmentsarray of string
providers[].defaultarray of object
providers[].default[].rolestring
providers[].default[].environmentsarray of string

POST /v1/keys/{id}/rotate ​

Rotate an API key.

Needs user.manage. Issues the key a new secret, shown once, as a new key with the same name, kind, user, roles, rate limits and expiry; its rotatedFrom names the old one. The old secret keeps working for overlapDays (7 by default; 0 stops it at once), or until its own expiry if that is sooner. Audited as key.rotate <old id> <new id>.

Parameters

NameInTypeRequiredDescription
idpathstringyes

Request body, optional (application/json)

FieldTypeRequiredDescription
overlapDaysintegerDefault 7. At least 0. At most 90.

Responses

StatusDescriptionBody
201{key, record, previous}: the new secret, the new key's record and the old key's, without secrets
400overlapDays out of range
403The caller lacks user.manage
404No such key
409The key has expired
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

GET /v1/sessions ​

Every user's sessions.

Needs user.manage. Every user's live sessions, or one user's, the most recently used first, each with its username. Sessions are named by id, never by token; current marks the caller's own. End one with DELETE /v1/users/{name}/sessions/{id}.

Parameters

NameInTypeRequiredDescription
userquerystringOnly this user's

Responses

StatusDescriptionBody
200The sessionsobject
403The caller lacks user.manage
404No such user
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

200 body (application/json)

FieldTypeRequiredDescription
sessionsarray of any

GET /v1/roles ​

Built-in and custom roles.

designer holds template.unlock and may change locked content and meta.locked; author may edit drafts but not locked content.

Responses

StatusDescriptionBody
200Roles
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object

POST /v1/roles ​

Add a custom role.

Needs user.manage. Audited as role.create <name>.

Responses

StatusDescriptionBody
201Created
409licence-limit (designer seats)
429The request's class is over its rate limit (limits.rate, or the API key's own rateLimits): {error: "rate-limited", class, message, retryAfter}. The MCP tool-call and agent edit limits answer the same body without class.object