Appearance
IAM — Users
An account belongs to exactly one tenant, where its email address is unique and is what a login resolves. It begins as an invitation or a claim code — only the code's hash is stored — and comes into being when that code is redeemed with a password. Not every rule on the entry is written by hand: pairing a device adds one naming that device, and unpairing takes it away.
Rules also arrive through roles and user groups, which an invitation may attach up front. Credentials and second factors are handled in authentication. Creation and invitation raise IAM_USER_CREATE and IAM_USER_CREATE_PENDING; the Quickstart walks through redeeming an invite.
| POST | Invite a user/api/v1/user |
| GET | List users/api/v1/user |
| GET | List outstanding invites/api/v1/user/pending |
| DELETE | Revoke an invite/api/v1/user/pending/:userId |
| POST | Reissue an invite/api/v1/user/pending/:userId/resend |
| POST | Redeem a code and register/api/v1/user/register |
| POST | Verify an email address/api/v1/user/verify-email |
| POST | Resend the verification mail/api/v1/user/resend-verification |
| POST | Request a password reset/api/v1/user/forgot-password |
| POST | Reset a password/api/v1/user/reset-password |
| GET | Read a user/api/v1/user/:userId |
| PATCH | Update a user/api/v1/user/:userId |
| DELETE | Delete a user/api/v1/user/:userId |
| POST | Mint a tenant claim code/api/v1/user/claim-codes |
Invite a user
Creates no account yet — it mints an invitation the invitee redeems at /user/register, and the returned identifier is the account it will become. The code is in the response unless sendMail is set, in which case it travels by mail only and the account skips email verification; attached roles and usergroups each take share.
POST
/api/v1/userBody
| Name | Description |
|---|---|
emailstring | |
accessarrayoptional | A resource access policy entry |
| identifier | The resource this policy applies to |
| Alternative 1 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 2 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 3 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 4 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 5 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 6 | Resource identifier pattern (CRN), may include wildcards |
effectenum | Access policy effect — either allow or deny Possible values: deny, allow |
actionsarray | List of actions permitted by this policy |
policyobjectoptional | Additional constraints for this access policy |
enforce2FAbooleanoptional | Requires the subject to have 2FA active before this access is granted |
targetoptional | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
| Alternative 1 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright.Possible values: user, role, group |
| Alternative 2 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
isOwnerbooleanoptional | Marks an owner-relative rule on a shared role: the crn#tenant:*.user:* head is rebound to the holder's own CRN before the rule is evaluated, so every member reaches only their own resources. |
inviteCodeTtlnumberoptional | How long an invite code remains valid, in seconds > 0 |
tenantIdstringoptional | Tenant identifier |
sendMailbooleanoptional | Mail the invitation to the address instead of returning the code. The code is then withheld from the response — the address being the only channel it travels on is what makes redemption evidence that the address is real. |
rolesarraystringoptional | CRNs of the roles the invited account joins on redemption. Each one takes share on that role. |
usergroupsarraystringoptional | CRNs of the user groups the invited account joins on redemption. Each one takes share on the group and never on the roles inside it. |
localestringoptional | Pattern: ^[a-z]{2}(-[A-Z]{2})?$ |
Response
| Name | Description |
|---|---|
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
inviteCodestringoptional | One-time invite code for user registration |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The email address already has an account in this tenant — invite a different address, or reset the password of the existing account. | code: USER_ALREADY_EXISTS |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
400 | The access rules asked for — on the account, or on the invitation that will create it — reach beyond the tenant's rootAccess. The response carries both the requested set and the tenant's ceiling, so drop or narrow the rules that exceed it. | code: USER_NO_SUBSET |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
List users
The accounts of the caller's tenant, filtered one by one by read, so a caller scoped to single users still sees those. Password hash and salt never leave the backend.
GET
/api/v1/userResponse
| Name | Description |
|---|---|
enforce2FAbooleanoptional | Whether two-factor authentication is required Default: false |
emailstring | The account's email address; within one tenant at most one account may hold it. |
emailVerifiedbooleanoptional | Whether this email address has been verified Default: false |
accessarray | A resource access policy entry |
| identifier | The resource this policy applies to |
| Alternative 1 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 2 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 3 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 4 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 5 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 6 | Resource identifier pattern (CRN), may include wildcards |
effectenum | Access policy effect — either allow or deny Possible values: deny, allow |
actionsarray | List of actions permitted by this policy |
policyobjectoptional | Additional constraints for this access policy |
enforce2FAbooleanoptional | Requires the subject to have 2FA active before this access is granted |
targetoptional | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
| Alternative 1 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright.Possible values: user, role, group |
| Alternative 2 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
isOwnerbooleanoptional | Marks an owner-relative rule on a shared role: the crn#tenant:*.user:* head is rebound to the holder's own CRN before the rule is evaluated, so every member reaches only their own resources. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
saltstringoptional | Random value used to salt the password hash |
hashstringoptional | Bcrypt password hash |
pepperVersionstringoptional | Which pepper the stored password hash was derived with; absent means the hash is unpeppered. Stripped from every response — it appears here only because the stored entity carries it. |
twoFactorAutharrayoptional | Two-factor authentication data for this user Default: [] |
createdBystring | Unique Coldwave resource name (CRN) that identifies a resource |
invitedBystringoptional | What admitted the account — the user who sent the invitation, or the device whose claim code was redeemed. Absent when the invitation was addressed to nobody, as with a broadcast tenant claim code or an account created outright. |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
List outstanding invites
Invitations that are neither redeemed nor expired. The code and the hash it is stored under are withheld, so an invite is addressed everywhere else by futureUserRi — the account it will become.
GET
/api/v1/user/pendingResponse
| Name | Description |
|---|---|
tenantRistring | Unique Coldwave resource name (CRN) that identifies a resource |
futureUserRistring | Unique Coldwave resource name (CRN) that identifies a resource |
emailstring | |
accessarrayoptional | A resource access policy entry Default: [] |
| identifier | The resource this policy applies to |
| Alternative 1 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 2 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 3 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 4 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 5 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 6 | Resource identifier pattern (CRN), may include wildcards |
effectenum | Access policy effect — either allow or deny Possible values: deny, allow |
actionsarray | List of actions permitted by this policy |
policyobjectoptional | Additional constraints for this access policy |
enforce2FAbooleanoptional | Requires the subject to have 2FA active before this access is granted |
targetoptional | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
| Alternative 1 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright.Possible values: user, role, group |
| Alternative 2 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
isOwnerbooleanoptional | Marks an owner-relative rule on a shared role: the crn#tenant:*.user:* head is rebound to the holder's own CRN before the rule is evaluated, so every member reaches only their own resources. |
roleRisarraystringoptional | CRNs of the roles the account joins when the invitation is redeemed. Default: [] |
usergroupRisarraystringoptional | CRNs of the user groups the account joins when the invitation is redeemed. A group is a bundle of roles and is granted whole — which is what lets an admin hand out a bundle they could not have assembled role by role. Default: [] |
emailVerifiedbooleanoptional | Whether this email address has been verified Default: false |
expiresAtnumber | When the code, token or invitation stops being redeemable, UTC epoch milliseconds. Past it the entry counts as absent rather than as expired: the pending list withholds it, and revoking or resending it answers 404. |
createdBystring | Unique Coldwave resource name (CRN) that identifies a resource |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Revoke an invite
{userId} is the id of the account the invite would create; an invite has no addressable id of its own. It takes delete on that future account, or on a group the invite would place it in, and the code stops working immediately.
DELETE
/api/v1/user/pending/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
userIdstring | User resource identifier |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Reissue an invite
Mints a fresh code and kills the old one — the plaintext of the previous code is stored nowhere, so it cannot be repeated. Roles and groups ride along unchanged and each takes share again; an address claimed in the meantime is refused.
POST
/api/v1/user/pending/Yk3pL7rWq2/resendPath Parameters
| Name | Description |
|---|---|
userIdstring | User resource identifier |
Body
| Name | Description |
|---|---|
inviteCodeTtlnumberoptional | How long an invite code remains valid, in seconds > 0 |
sendMailbooleanoptional | Mail the invitation to the address instead of returning the code. The code is then withheld from the response — the address being the only channel it travels on is what makes redemption evidence that the address is real. |
localestringoptional | Pattern: ^[a-z]{2}(-[A-Z]{2})?$ |
Response
| Name | Description |
|---|---|
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
inviteCodestringoptional | One-time invite code for user registration |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The email address already has an account in this tenant — invite a different address, or reset the password of the existing account. | code: USER_ALREADY_EXISTS |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Redeem a code and register
Public: turns a code into an account with a password. An INVITE_CODE carries its own address, so email is ignored; a CLAIM_CODE needs one, and a device's printed claim code also claims and pairs that device — emailVerified in the response says whether a verification code is on its way.
POST
/api/v1/user/registerBody
| Name | Description |
|---|---|
| code | A verification code entry |
Alternative 1object | A verification code entry |
| type | Type of verification code |
codestring | The verification code value |
Alternative 2object | A verification code entry |
| type | Type of verification code |
codestring | The verification code value |
emailstringoptional | |
passwordstring | Account password: 16 to 64 characters, with no character-class rules on top. The same bound holds at registration, reset and change, so a shorter one is refused before it can ever be set. min length 16 · max length 64 Pattern: ^[\s\S]{16,64}$ |
Response
| Name | Description |
|---|---|
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
emailVerifiedboolean | Whether this email address has been verified |
Errors
Rate limited.
5 requests / 3600 s per ip (register-per-ip)
| Status | Description | Body |
|---|---|---|
400 | The invite or verification code does not match. Codes are single-use; a code already redeemed reads as invalid. | code: USER_INVALID_CODE |
400 | The invite or verification code has passed its lifetime. Ask an administrator for a fresh invitation. | code: USER_CODE_EXPIRED |
400 | The email address already has an account in this tenant — invite a different address, or reset the password of the existing account. | code: USER_ALREADY_EXISTS |
503 | The tenant's password secret could not be resolved, so no password hash could be computed. The account was not created; the condition is transient, so retry. | code: USER_PEPPER_UNAVAILABLE |
429 | The rate limit for this endpoint was exceeded. The Retry-After header gives the length of the current window in seconds. | error: RATE_LIMITED |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Verify an email address
Consumes the code from the verification mail and marks the address verified. The code is good for ten minutes; it is matched case-insensitively and the usual O/0 and I/1 mix-ups are corrected before lookup.
POST
/api/v1/user/verify-emailBody
| Name | Description |
|---|---|
codestring | A verification code entry |
Errors
Rate limited.
20 requests / 3600 s per ip (verify-email-per-ip)
| Status | Description | Body |
|---|---|---|
400 | The invite or verification code does not match. Codes are single-use; a code already redeemed reads as invalid. | code: USER_INVALID_CODE |
400 | The invite or verification code has passed its lifetime. Ask an administrator for a fresh invitation. | code: USER_CODE_EXPIRED |
429 | The rate limit for this endpoint was exceeded. The Retry-After header gives the length of the current window in seconds. | error: RATE_LIMITED |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Resend the verification mail
Public, and always answers 200 — whether the address exists, and whether it is already verified, is deliberately not disclosed. The account is resolved from the address together with the request's host, and at most three mails per address go out in an hour.
POST
/api/v1/user/resend-verificationBody
| Name | Description |
|---|---|
emailstring |
Errors
Rate limited.
3 requests / 3600 s (mail-per-address)
10 requests / 3600 s per ip + route (mail-per-ip)
| Status | Description | Body |
|---|---|---|
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
429 | The rate limit for this endpoint was exceeded. The Retry-After header gives the length of the current window in seconds. | error: RATE_LIMITED |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Request a password reset
Public, and always answers 200 — the existence of the address is not disclosed. An address holding accounts in several tenants on this host is mailed once per account, each mail naming its tenant and carrying a token good for one hour; the link points at the Origin the request came from.
POST
/api/v1/user/forgot-passwordBody
| Name | Description |
|---|---|
emailstring |
Errors
Rate limited.
3 requests / 3600 s (mail-per-address)
10 requests / 3600 s per ip + route (mail-per-ip)
| Status | Description | Body |
|---|---|---|
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
429 | The rate limit for this endpoint was exceeded. The Retry-After header gives the length of the current window in seconds. | error: RATE_LIMITED |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Reset a password
Consumes the token from the reset mail, sets the new password and signs every session of that account out. The token is single-use and lives one hour; an unknown and an expired one are answered with different codes.
POST
/api/v1/user/reset-passwordBody
| Name | Description |
|---|---|
tokenstring | The one-time token from the password-reset link. Only its hash is stored, so it can be neither looked up nor resent — a lost token means asking for a new reset. |
passwordstring | Account password: 16 to 64 characters, with no character-class rules on top. The same bound holds at registration, reset and change, so a shorter one is refused before it can ever be set. min length 16 · max length 64 Pattern: ^[\s\S]{16,64}$ |
Errors
| Status | Description | Body |
|---|---|---|
400 | The invite or verification code does not match. Codes are single-use; a code already redeemed reads as invalid. | code: USER_INVALID_CODE |
400 | The invite or verification code has passed its lifetime. Ask an administrator for a fresh invitation. | code: USER_CODE_EXPIRED |
503 | The tenant's password secret could not be resolved, so no password hash could be computed. The account was not created; the condition is transient, so retry. | code: USER_PEPPER_UNAVAILABLE |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Read a user
The account with the rules written directly on it; hash and salt are stripped from the response. The roles and groups it holds are not fields of the entry — read those from the role or group side.
GET
/api/v1/user/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
userIdstring | User resource identifier |
Response
| Name | Description |
|---|---|
enforce2FAbooleanoptional | Whether two-factor authentication is required Default: false |
emailstring | The account's email address; within one tenant at most one account may hold it. |
emailVerifiedbooleanoptional | Whether this email address has been verified Default: false |
accessarray | A resource access policy entry |
| identifier | The resource this policy applies to |
| Alternative 1 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 2 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 3 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 4 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 5 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 6 | Resource identifier pattern (CRN), may include wildcards |
effectenum | Access policy effect — either allow or deny Possible values: deny, allow |
actionsarray | List of actions permitted by this policy |
policyobjectoptional | Additional constraints for this access policy |
enforce2FAbooleanoptional | Requires the subject to have 2FA active before this access is granted |
targetoptional | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
| Alternative 1 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright.Possible values: user, role, group |
| Alternative 2 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
isOwnerbooleanoptional | Marks an owner-relative rule on a shared role: the crn#tenant:*.user:* head is rebound to the holder's own CRN before the rule is evaluated, so every member reaches only their own resources. |
resourceIdentifierstring | Unique Coldwave resource name (CRN) that identifies a resource |
saltstringoptional | Random value used to salt the password hash |
hashstringoptional | Bcrypt password hash |
pepperVersionstringoptional | Which pepper the stored password hash was derived with; absent means the hash is unpeppered. Stripped from every response — it appears here only because the stored entity carries it. |
twoFactorAutharrayoptional | Two-factor authentication data for this user Default: [] |
createdBystring | Unique Coldwave resource name (CRN) that identifies a resource |
invitedBystringoptional | What admitted the account — the user who sent the invitation, or the device whose claim code was redeemed. Absent when the invitation was addressed to nobody, as with a broadcast tenant claim code or an account created outright. |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Update a user
Writes access and enforce2FA, nothing else. access replaces the rule set as a whole and is capped by the tenant's rootAccess — a rule written straight onto an account is worth exactly as much at request time as one on a role.
PATCH
/api/v1/user/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
userIdstring | User resource identifier |
Body
| Name | Description |
|---|---|
accessarrayoptional | A resource access policy entry |
| identifier | The resource this policy applies to |
| Alternative 1 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 2 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 3 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 4 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 5 | Resource identifier pattern (CRN), may include wildcards |
| Alternative 6 | Resource identifier pattern (CRN), may include wildcards |
effectenum | Access policy effect — either allow or deny Possible values: deny, allow |
actionsarray | List of actions permitted by this policy |
policyobjectoptional | Additional constraints for this access policy |
enforce2FAbooleanoptional | Requires the subject to have 2FA active before this access is granted |
targetoptional | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
| Alternative 1 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright.Possible values: user, role, group |
| Alternative 2 | Narrows a pair grant to where a claimed device may land: a kind — user, role or group — or one owner's CRN outright. |
isOwnerbooleanoptional | Marks an owner-relative rule on a shared role: the crn#tenant:*.user:* head is rebound to the holder's own CRN before the rule is evaluated, so every member reaches only their own resources. |
enforce2FAbooleanoptional | Whether two-factor authentication is required |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The access rules asked for — on the account, or on the invitation that will create it — reach beyond the tenant's rootAccess. The response carries both the requested set and the tenant's ceiling, so drop or narrow the rules that exceed it. | code: USER_NO_SUBSET |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Delete a user
Removes the account, releases its email address so it can be invited again, and drops it out of every role it held. Nothing beneath the tenant is cascaded.
DELETE
/api/v1/user/Yk3pL7rWq2Path Parameters
| Name | Description |
|---|---|
userIdstring | User resource identifier |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |
Mint a tenant claim code
Returns an opaque code — good for 30 days unless expiresIn says otherwise — that turns into an account at /user/register. Redeeming it does not spend it, so everyone it was handed to can use it; roleId makes every account created with it join that role and takes share on the role.
POST
/api/v1/user/claim-codesBody
| Name | Description |
|---|---|
expiresInnumberoptional | Time until expiry, in seconds > 0 |
tenantIdstringoptional | Tenant identifier |
roleIdstringoptional | Id of the role a redeemed claim code joins — the bare id, not a CRN. Minting a code bound to a role takes share on that role. |
Response
| Name | Description |
|---|---|
codestring | A verification code entry |
Errors
| Status | Description | Body |
|---|---|---|
403 | You do not have permission to perform this action | |
409 | A tenant with the given name already exists | code: IAM_TENANT_CONFLICT_ERROR |
404 | No account with this id exists in the tenant. | code: USER_NOT_FOUND |
400 | The request did not match the schema for this endpoint. The details field carries the specific failures. | error: Validation Error |
401 | No valid access token was presented, or the DPoP proof accompanying it was missing, expired or bound to a different key. | error: string |
500 | The request failed for a reason that is not the caller's to fix. Safe to retry. | error: string, message: string, statusCode: 50 |