Add a person
const url = 'https://example.com/v1/identity/users';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"displayName":"example","primaryEmail":"example","sendInvite":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/identity/users \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "displayName": "example", "primaryEmail": "example", "sendInvite": true }'Adds a person to the tenant as a tenant member, written before it answers: they can read the tenant’s settings (providers, policies, adapters, signing keys, deployments), not its projects. Give them a role to work (project or team membership, or tenant admin), then mint their first API key at POST /v1/tokens with for. A person added with an email is invited (invite): they sign in within 7 days, or a tenant admin renews it (POST /v1/identity/users/{userId}/invite); the invitation is emailed where the deployment sends email, and inviteEmail says whether it was. Tenant admins only. Mounted when the identity directory can add people.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5).
Request Bodyrequired
Section titled “Request Bodyrequired”object
Unique among the tenant’s people.
Email them the invitation (default true). false still invites them, for an admin who tells them another way. A person without an email isn’t invited.
Examplegenerated
{ "displayName": "example", "primaryEmail": "example", "sendInvite": true}Responses
Section titled “Responses”The new person, and whether their invitation was emailed.
The person just added, and whether their invitation was emailed (inviteEmail: absent from a runtime that sends no invitations).
object
When they were removed from the tenant (POST /v1/identity/users/{userId}/unregister); absent while they are here.
Their invitation, while they haven’t signed in: absent once they have, for people added without an email, and for people added before invitations (from 0.1.9).
object
When it was last emailed; absent when it never was.
Their first sign-in that made a session. Absent before it, and for people who last signed in before it was kept (from 0.1.9).
object
Whether the invitation was emailed, and why not: no-email (the person has no email, so isn’t invited), not-requested (sendInvite: false), not-configured (the deployment sends no email), send-failed (the mail server refused it or didn’t answer), capped (the workspace, or the whole deployment, has sent as many invitation emails as it may in 24 hours). An invitation not emailed is still open: tell them yourself.
object
Example
{ "invite": { "state": "pending" }, "inviteEmail": { "reason": "no-email" }}Malformed request body.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Not a tenant admin.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Another person of the tenant has the email (identity-user-email-taken), or an idempotency conflict.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/identity/users: List users in the tenantGET /v1/identity/users/{userId}: Get a user by idGET /v1/identity/users/{userId}/sessions: List active sessions for a userPOST /v1/identity/users/{userId}/unregister: Remove a person- Error code
identity-user-email-taken - Error code
request-too-large - Every error code