Iam
Package iam is Hanzo's identity provider: users, organizations, applications, and the OIDC/OAuth2 endpoints every Hanzo service authenticates against.
Package iam is Hanzo's identity provider: users, organizations, applications, and the OIDC/OAuth2 endpoints every Hanzo service authenticates against.
| Base URL | https://api.hanzo.ai |
| Operations | 193 |
| Auth | Authorization: Bearer $HANZO_API_KEY |
iam
GET /v1/iam/.well-known/jwks
Publishes the public keys that verify the tokens issued here — the one URL you point a service at so it can check a token itself, offline, without calling back and without holding any secret of ours.
Keys appear here before they start signing and stay after they stop, so a rotation never leaves a live token unverifiable. Nothing private is ever published.
GET /v1/iam/.well-known/oauth-authorization-server
Returns the OpenID Connect discovery document — the one URL you point a standards-compliant client at so it can find every other endpoint on its own, instead of you configuring them by hand.
It advertises only what is actually implemented, so a client that reads it cannot ask for a flow that will fail: the authorization-code flow, PKCE with S256, the supported grants, and the signing algorithms whose public keys the JWKS really publishes.
The issuer is derived from the host you asked on and is the same value the tokens carry, so a client that pins the issuer never sees it change.
GET /v1/iam/.well-known/openid-configuration
Returns the OpenID Connect discovery document — the one URL you point a standards-compliant client at so it can find every other endpoint on its own, instead of you configuring them by hand.
It advertises only what is actually implemented, so a client that reads it cannot ask for a flow that will fail: the authorization-code flow, PKCE with S256, the supported grants, and the signing algorithms whose public keys the JWKS really publishes.
The issuer is derived from the host you asked on and is the same value the tokens carry, so a client that pins the issuer never sees it change.
GET /v1/iam/account
Returns the signed-in person's own account and the organization they belong to — what a console reads to draw the account menu.
Passwords, API secrets and MFA material are stripped. It answers for a session cookie or a bearer token alike.
POST /v1/iam/add-application
Registers an application in your organization — one product or site your people sign in to, with its own client credentials, sign-in methods and allowed redirect URIs.
The older spelling of POST /v1/iam/application. A name already used in the organization is refused rather than overwritten.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
POST /v1/iam/add-membership
Lets a person or an application act in an organization. It is the grant behind "add someone to the team", and it is safe to repeat — granting a membership that already exists changes nothing. Granting membership IS the org's authority to give, so it takes the same gate a write to that org's own registry row takes: a SuperAdmin, an admin of the org itself, or an org-admin-capable confidential client. One rule, one place (internal/authz).
POST /v1/iam/add-organization
Creates an organization — the account everything else in your directory hangs from. Users, applications, roles, projects and workspaces are all named inside one organization, so this is the first write in a new tenant.
The older spelling of POST /v1/iam/organizations. Both reach the same create, so a name already taken is refused here too.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accountItems | iam.AccountItem[] | — | |
accountMenu | string | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
countryCodes | string[] | — | |
createdAt | string | — | |
createdTime | string | — | |
dcrPolicy | string | — | |
defaultApplication | string | — | |
defaultAvatar | string | — | |
defaultPassword | string | — | |
deleted | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
enableSoftDeletion | boolean | — | |
enableTour | boolean | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
founder | string | — | |
hasPrivilegeConsent | boolean | — | |
id | string | — | |
initScore | integer | — | |
ipRestriction | string | — | |
ipWhitelist | string | — | |
isPersonal | boolean | — | |
isProfilePublic | boolean | — | |
kerberosKdcHost | string | — | |
kerberosKeytab | string | — | |
kerberosRealm | string | — | |
kerberosServiceName | string | — | |
languages | string[] | — | |
ldapAttributes | string[] | — | |
logo | string | — | |
logoDark | string | — | |
masterPassword | string | — | |
masterVerificationCode | string | — | |
mfaItems | iam.MfaItem[] | — | |
mfaRememberInHours | integer | — | |
name | string | — | |
| … | 19 more fields in the schema |
POST /v1/iam/add-project
Creates a project inside your organization — the scope people pick between when their work is separated by product or client rather than by team.
The older spelling of POST /v1/iam/projects. Creating one takes an administrator of the owning organization.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — | |
workspace | string | — |
POST /v1/iam/add-provider
Adds an identity provider your people can sign in with, or a service your applications send through — a social or enterprise login, an email or SMS sender, a storage or payment connector.
A provider is configured once here and then switched on per application, so several applications can share one set of credentials.
The older spelling of POST /v1/iam/providers.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
appId | string | — | |
bucket | string | — | |
category | string | — | |
cert | string | — | |
clientId | string | — | |
clientId2 | string | — | |
clientSecret | string | — | |
clientSecret2 | string | — | |
content | string | — | |
createdAt | string | — | |
createdTime | string | — | |
customAuthUrl | string | — | |
customLogo | string | — | |
customTokenUrl | string | — | |
customUserInfoUrl | string | — | |
deleted | boolean | — | |
disableSsl | boolean | — | |
displayName | string | — | |
domain | string | — | |
emailRegex | string | — | |
enablePkce | boolean | — | |
enableProxy | boolean | — | |
enableSignAuthnRequest | boolean | — | |
endpoint | string | — | |
host | string | — | |
httpHeaders | object | — | |
id | string | — | |
idP | string | — | |
intranetEndpoint | string | — | |
issuerUrl | string | — | |
metadata | string | — | |
method | string | — | |
name | string | — | |
owner | string | — | |
pathPrefix | string | — | |
port | integer | — | |
providerUrl | string | — | |
receiver | string | — | |
regionId | string | — | |
scopes | string | — | |
| … | 8 more fields in the schema |
POST /v1/iam/add-role
Creates a role — a named group of people that permissions are granted to. Granting to a role rather than to each person is what keeps access correct as your team changes: add someone to the role and they inherit everything it can do.
The older spelling of POST /v1/iam/roles.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
groups | string[] | — | |
isEnabled | boolean | — | |
name | string | — | |
owner | string | — | |
roles | string[] | — | |
users | string[] | — |
POST /v1/iam/add-user
Adds a person to your organization and, if you send a password, sets the one they will sign in with. The password is hashed before it is stored and is never returned to you or to anyone else.
Usernames are checked against one rule wherever an account is created — this verb, password signup, a social sign-in, or SCIM — so a name accepted here is a name accepted everywhere.
The older spelling of POST /v1/iam/users, and it posts the user's fields at the top level rather than wrapped in {user, password}.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | |
accessSecret | string | — | |
accessSecretHash | string | — | |
accessToken | string | — | |
address | string[] | — | |
addresses | iam.Address[] | — | |
adfs | string | — | |
affiliation | string | — | |
alipay | string | — | |
amazon | string | — | |
apple | string | — | |
applicationScopes | iam.ConsentRecord[] | — | |
auth0 | string | — | |
avatar | string | — | |
avatarType | string | — | |
azuread | string | — | |
azureadb2c | string | — | |
baidu | string | — | |
balance | number | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
battlenet | string | — | |
bilibili | string | — | |
bio | string | — | |
birthday | string | — | |
bitbucket | string | — | |
box | string | — | |
cart | iam.CartItem[] | — | |
cloudfoundry | string | — | |
countryCode | string | — | |
createdAt | string | — | |
createdIp | string | — | |
createdTime | string | — | |
currency | string | — | |
custom | string | — | |
custom2 | string | — | |
custom3 | string | — | |
custom4 | string | — | |
custom5 | string | — | |
custom6 | string | — | |
| … | 147 more fields in the schema |
POST /v1/iam/add-workspace
Creates a workspace inside your organization — the scope a team works in, alongside projects rather than instead of them.
The older spelling of POST /v1/iam/workspaces. Creating one takes an administrator of the owning organization.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
bucket | string | — | |
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — |
POST /v1/iam/admin/applications/upsert
Creates an application or updates it in place, so a deployment can declare the applications it needs and run the same declaration on every environment and on every redeploy.
It says which of the two it did. Leave the client secret out and the existing one is kept — so re-running your deployment does not rotate a credential your running services are holding.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Authorization | header | string | — |
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
cert | string | — | |
clientId | string | — | |
clientSecret | string | — | |
displayName | string | — | |
enableCodeSignin | boolean | — | EnableCodeSignin offers sign-in by an emailed or texted one-time code beside the password. |
expireInHours | number | — | ExpireInHours and RefreshExpireInHours are the application's token lifetimes. |
grantTypes | string[] | — | |
isShared | boolean | — | IsShared declares that this application serves EVERY organization, not only the one named in Organization. |
name | string | — | |
organization | string | — | |
public | boolean | — | Public declares a client that CANNOT hold a credential — a browser SPA, a CLI, a desktop app. |
redirectUris | string[] | — | |
refreshExpireInHours | number | — |
POST /v1/iam/admin/provision
Sets up an account on someone's behalf — the same onboarding a person gets themselves, driven by one of your own services instead of by them.
It authenticates as your service rather than as a person, which is why the person to provision is named in the request. The setup it performs is identical to self-service onboarding; there is one provisioning path, not two that can drift.
POST /v1/iam/admin/users/upsert
Creates a person or updates them in place, so a deployment can declare the accounts it needs and re-run that declaration safely.
Passwords are hashed before they are stored. Leave the password out and their current one is kept, so a redeploy never locks somebody out.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Authorization | header | string | — |
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
displayName | string | — | |
email | string | — | |
isAdmin | boolean | — | |
name | string | — | |
owner | string | — | |
password | string | — | |
passwordType | string | — | |
phone | string | — |
GET /v1/iam/application
Returns one application: its sign-in methods, its allowed redirect URIs and the client credentials your integration authenticates with.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes | |
name | query | string | yes |
POST /v1/iam/application
Registers an application in your organization — one product or site your people sign in to, with its own client credentials, sign-in methods and allowed redirect URIs. A name already used in the organization is refused rather than overwritten.
Exported so the legacy add-application alias reuses this exact path — one create, two spellings.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
PUT /v1/iam/application
Changes an application's display, its sign-in methods and the redirect URIs it may return to — the call that makes login work from a new host. Which organization it belongs to and what it is named are fixed when it is created and are not editable here.
Exported so the legacy update-application alias reuses this exact path — one update, two spellings.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
DELETE /v1/iam/application
Removes an application. Anyone mid-sign-in through it is turned away and its client credentials stop working, so retire the integration before deleting it.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes | |
name | query | string | yes |
POST /v1/iam/applications/delete
Removes an application. Anyone mid-sign-in through it is turned away and its client credentials stop working, so retire the integration before deleting it.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
GET /v1/iam/applications/get
Returns one application: its sign-in methods, its allowed redirect URIs and the client credentials your integration authenticates with.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes | |
name | query | string | yes |
POST /v1/iam/applications/update
Changes an application's display, its sign-in methods and the redirect URIs it may return to — the call that makes login work from a new host. Which organization it belongs to and what it is named are fixed when it is created and are not editable here.
Exported so the legacy update-application alias reuses this exact path — one update, two spellings.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
GET /v1/iam/applications
Returns the applications in one organization, newest first — each product or site your people sign in to, with the sign-in methods and redirect URIs it allows.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes |
POST /v1/iam/applications
Registers an application in your organization — one product or site your people sign in to, with its own client credentials, sign-in methods and allowed redirect URIs. A name already used in the organization is refused rather than overwritten.
Exported so the legacy add-application alias reuses this exact path — one create, two spellings.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
POST /v1/iam/audit-logs/delete
Removes an audit entry. Retention policy is normally what should expire a trail; deleting by hand leaves a gap a reviewer will notice.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/audit-logs/get
Returns one audit entry in full: the action, the person or key behind it, and the request it came in on.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/audit-logs/update
Corrects an audit entry. The trail is append-only in normal operation and nothing in the Hanzo Cloud rewrites it — this exists for an administrator to correct an entry their own systems recorded wrongly.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
action | string | — | |
clientIp | string | — | |
createdTime | string | — | |
isTriggered | boolean | — | |
language | string | — | |
method | string | — | |
name | string | — | |
object | string | — | |
organization | string | — | |
owner | string | — | |
requestUri | string | — | |
response | string | — | |
statusCode | integer | — | |
user | string | — |
GET /v1/iam/audit-logs
Returns your organization's audit trail, newest first — who did what, when, and from where. It is the record you reach for during a security review or an incident.
You see your own organization's audit trail and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/audit-logs
Records an audit entry, so activity from your own systems lands in the same trail as everything the Hanzo Cloud records for you.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
action | string | — | |
clientIp | string | — | |
createdTime | string | — | |
isTriggered | boolean | — | |
language | string | — | |
method | string | — | |
name | string | — | |
object | string | — | |
organization | string | — | |
owner | string | — | |
requestUri | string | — | |
response | string | — | |
statusCode | integer | — | |
user | string | — |
GET /v1/iam/auth/application
Returns everything a login screen needs to draw itself for one application: its branding, and each sign-in method it offers with the provider details that method needs.
The client secret is masked. Read before anyone has signed in, so it carries only what is safe for a browser to see.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
clientId | query | string | — | ClientId is the application's OAuth client id — the one field that selects which login screen this is. |
responseType | query | string | — | ResponseType is the OAuth response type the screen will ask for. |
GET /v1/iam/auth/methods
Returns the sign-in methods one application actually has switched on, so a login screen can render the right buttons for it without you hard-coding a list that drifts the moment you add a provider.
Public by design: it is read before anyone has signed in, and it exposes only which methods exist, never their credentials.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
clientId | query | string | — | ClientId is the application's OAuth client id. |
POST /v1/iam/certs/delete
Removes a signing certificate. Tokens signed with it can no longer be verified, so retire it only once nothing is still presenting them.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/certs/get
Returns one signing certificate — its algorithm, its validity window and its public half. The private key is masked.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/certs/update
Changes a signing certificate's settings. What it is called does not change, and neither does when it was added.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | |
accessSecret | string | — | |
account | string | — | |
bitSize | integer | — | |
certificate | string | — | |
createdAt | string | — | |
createdTime | string | — | |
cryptoAlgorithm | string | — | |
deleted | boolean | — | |
displayName | string | — | |
domainExpireTime | string | — | |
expireInYears | integer | — | |
expireTime | string | — | |
id | string | — | |
name | string | — | |
owner | string | — | |
privateKey | string | — | |
provider | string | — | |
scope | string | — | |
type | string | — | |
updatedAt | string | — |
GET /v1/iam/certs
Returns your organization's signing certificates, newest first — the keys the tokens your applications verify are signed with. Private key material is masked.
You see your own organization's certificates and no one else's; which organization that is comes from your credentials, not from the request, so a query parameter can never widen the listing.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/certs
Adds a signing certificate your applications can verify tokens against — the call you make to bring your own key, or to stage the next one before a rotation. A name already used in your organization is refused.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | |
accessSecret | string | — | |
account | string | — | |
bitSize | integer | — | |
certificate | string | — | |
createdAt | string | — | |
createdTime | string | — | |
cryptoAlgorithm | string | — | |
deleted | boolean | — | |
displayName | string | — | |
domainExpireTime | string | — | |
expireInYears | integer | — | |
expireTime | string | — | |
id | string | — | |
name | string | — | |
owner | string | — | |
privateKey | string | — | |
provider | string | — | |
scope | string | — | |
type | string | — | |
updatedAt | string | — |
GET /v1/iam/consent
Returns the calling person's own privacy and communication choices. Somebody who has never set them gets the defaults rather than nothing, so a consent screen always has something to show — insights on, and training UNANSWERED, which is the state that means the screen still has to ask.
PUT /v1/iam/consent
Records the calling person's privacy and communication choices. Only their own — there is no way to set consent for somebody else.
Send only the answers you are changing. A question you leave out keeps the answer it already had, so a screen that saves one switch never revokes the other, and two screens saving at once do not undo each other.
An answer this version does not recognize is refused here rather than stored, so nothing is ever persisted for a later reader to have to interpret.
POST /v1/iam/delete-application
Deletes an application. Anyone mid-sign-in through it is turned away and its client credentials stop working, so retire the integration first.
The older spelling of DELETE /v1/iam/application.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
POST /v1/iam/delete-membership
Takes away a person's or an application's right to act in an organization. Their account survives; what ends is their access to that organization. Revoking a membership that is already gone reports that nothing was removed rather than failing, so a retry is safe. It is the mirror of ensure and takes the SAME gate: revoking membership is the org's authority to give or take, so a SuperAdmin, an admin of the org itself, or an org-admin-capable confidential client. Idempotent through the store — deleting an absent membership reports removed=false, never an error — so a retried revoke is safe.
POST /v1/iam/delete-mfa
Turns off the authenticator app for an account, so sign-in stops asking for a code. People may do this for themselves; doing it for somebody else takes an administrator, which is what makes it the reset path when a phone is lost.
POST /v1/iam/delete-organization
Deletes an organization and everything named inside it — its users, applications, roles, projects and workspaces. There is no undo, and every session issued under it stops working.
The older spelling of POST /v1/iam/organizations/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/delete-project
Deletes a project. The people and roles in your organization are unchanged; what goes is the scope itself, so anything addressed by it must move first.
The older spelling of POST /v1/iam/projects/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/delete-provider
Removes a provider. Sign-in through it stops for every application that used it, so detach those applications first if they have no other method.
The older spelling of POST /v1/iam/providers/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
appId | string | — | |
bucket | string | — | |
category | string | — | |
cert | string | — | |
clientId | string | — | |
clientId2 | string | — | |
clientSecret | string | — | |
clientSecret2 | string | — | |
content | string | — | |
createdAt | string | — | |
createdTime | string | — | |
customAuthUrl | string | — | |
customLogo | string | — | |
customTokenUrl | string | — | |
customUserInfoUrl | string | — | |
deleted | boolean | — | |
disableSsl | boolean | — | |
displayName | string | — | |
domain | string | — | |
emailRegex | string | — | |
enablePkce | boolean | — | |
enableProxy | boolean | — | |
enableSignAuthnRequest | boolean | — | |
endpoint | string | — | |
host | string | — | |
httpHeaders | object | — | |
id | string | — | |
idP | string | — | |
intranetEndpoint | string | — | |
issuerUrl | string | — | |
metadata | string | — | |
method | string | — | |
name | string | — | |
owner | string | — | |
pathPrefix | string | — | |
port | integer | — | |
providerUrl | string | — | |
receiver | string | — | |
regionId | string | — | |
scopes | string | — | |
| … | 8 more fields in the schema |
POST /v1/iam/delete-role
Deletes a role. Everyone in it loses the access it carried; their accounts and any other roles they hold are untouched.
The older spelling of POST /v1/iam/roles/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/delete-user
Removes a person from your organization. Their sessions stop working and the account is gone, not suspended — to keep the record and only stop sign-in, update the user instead.
The older spelling of POST /v1/iam/users/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | |
accessSecret | string | — | |
accessSecretHash | string | — | |
accessToken | string | — | |
address | string[] | — | |
addresses | iam.Address[] | — | |
adfs | string | — | |
affiliation | string | — | |
alipay | string | — | |
amazon | string | — | |
apple | string | — | |
applicationScopes | iam.ConsentRecord[] | — | |
auth0 | string | — | |
avatar | string | — | |
avatarType | string | — | |
azuread | string | — | |
azureadb2c | string | — | |
baidu | string | — | |
balance | number | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
battlenet | string | — | |
bilibili | string | — | |
bio | string | — | |
birthday | string | — | |
bitbucket | string | — | |
box | string | — | |
cart | iam.CartItem[] | — | |
cloudfoundry | string | — | |
countryCode | string | — | |
createdAt | string | — | |
createdIp | string | — | |
createdTime | string | — | |
currency | string | — | |
custom | string | — | |
custom2 | string | — | |
custom3 | string | — | |
custom4 | string | — | |
custom5 | string | — | |
custom6 | string | — | |
| … | 147 more fields in the schema |
POST /v1/iam/delete-workspace
Deletes a workspace. The people and roles in your organization are unchanged; what goes is the scope itself.
The older spelling of POST /v1/iam/workspaces/delete.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
GET /v1/iam/get-account
Returns the signed-in person's own account and the organization they belong to — what a console reads to draw the account menu.
Passwords, API secrets and MFA material are stripped. It answers for a session cookie or a bearer token alike.
GET /v1/iam/get-app-login
Returns everything a login screen needs to draw itself for one application: its branding, and each sign-in method it offers with the provider details that method needs.
The client secret is masked. Read before anyone has signed in, so it carries only what is safe for a browser to see.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
clientId | query | string | — | ClientId is the application's OAuth client id — the one field that selects which login screen this is. |
responseType | query | string | — | ResponseType is the OAuth response type the screen will ask for. |
GET /v1/iam/get-application
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-applications
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-cert
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-certs
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-global-users
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-invitations
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-memberships
Answers either question about who belongs where: which organizations one person can act in, or who can act in one organization.
Both are org-scoped: a non-SuperAdmin may ask about ITS OWN org's roster, or about a user whose home org is its own, and nothing else. The bound comes from the verified credential via authz.Scope, so a request parameter can never widen it — a membership row names who may act and spend in an org, so a cross-tenant read is a customer roster leak.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
user | query | string | — | User is "<homeOrg>/<username>" — which organizations that identity may act in. |
org | query | string | — | Org is an organization — who may act in it. |
GET /v1/iam/get-organization-projects
Returns one organization's projects — what a scope switcher lists so somebody can move between them.
You see your own organization and no other, whatever the request asks for.
GET /v1/iam/get-organization-workspaces
Returns one organization's workspaces — what a scope switcher lists so somebody can move between them.
You see your own organization and no other, whatever the request asks for.
GET /v1/iam/get-organization
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-organizations
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-permission
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-permissions
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-provider
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-providers
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-records
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-role
Reads one record — the older spelling of the single reads on the REST surface, over the same data and the same permissions.
Secrets are stripped. Naming a record in another organization does not reach it, however the request spells it.
GET /v1/iam/get-roles
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
GET /v1/iam/get-user
Reads one person, two ways.
Name them and it is an ordinary read, with secrets stripped. Or hand it a SECRET API key and it answers with the person that key belongs to — how a service of yours turns a credential on an incoming request into an identity.
A publishable key resolves to nobody here, deliberately: it is safe to ship in a browser precisely because it names an organization and never a person.
get-user is handler-authorized (authz.handlerAuthorizedExact) because the key variant carries no owner/name for the Guard to authorize; so the owner/name variant reinstates the SAME read authorization the Guard applies, through the ONE policy function (authz.Can) — identical behavior, a cross-tenant or non-self read still refused 403 — then reuses the generic getHandler verbatim for resolution and redaction. No authz and no CRUD is reimplemented.
GET /v1/iam/get-users
Lists one kind of record in your organization — the older spelling of the collection reads on the REST surface, over the same data and the same permissions.
Secrets are stripped from every row. Send both a page number and a page size to page, and the total comes back alongside; send neither and you get the whole set. You see your own organization and no other, whatever the request asks for.
Scoping note (intentional, fail-closed): iam's ownership model is mixed — users/roles/permissions are owned by their tenant org, while organizations/ applications/providers/certs are platform-owned (Owner "admin"). A SuperAdmin (Scope → the requested owner, empty = all) therefore lists every entity, which is the console-admin path. A non-super is pinned by Scope to its own org, so it lists its tenant-owned entities correctly and is refused the platform-owned lists at the Guard (owner "" or "admin" both deny) — a safe 403, never another tenant's rows. Non-super, membership-scoped views of the platform-owned entities (e.g. an org console's own app list keyed on Application.Organization) are a separate, additive surface, not a silent behavior of this generic lister.
POST /v1/iam/invitations/delete
Withdraws an invitation. It stops being redeemable at once; anyone who already joined through it keeps their account.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/invitations/get
Returns one invitation: who it is for, what it grants on acceptance, and when it expires.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/invitations/update
Changes an invitation's terms — the role it grants, how many may redeem it, or when it expires. What it is called does not change.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | — | |
code | string | — | |
createdTime | string | — | |
defaultCode | string | — | |
displayName | string | — | |
email | string | — | |
isRegexp | boolean | — | |
name | string | — | |
owner | string | — | |
phone | string | — | |
quota | integer | — | |
signupGroup | string | — | |
state | string | — | |
updatedTime | string | — | |
usedCount | integer | — | |
username | string | — |
GET /v1/iam/invitations
Returns your organization's invitations, newest first — who has been asked to join, on what terms, and how many seats each invitation still has left.
You see your own organization's invitations and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/invitations
Issues an invitation to join your organization — the code or link a new member redeems, with the role they arrive holding and the date it stops working. A name already used in the organization is refused.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | — | |
code | string | — | |
createdTime | string | — | |
defaultCode | string | — | |
displayName | string | — | |
email | string | — | |
isRegexp | boolean | — | |
name | string | — | |
owner | string | — | |
phone | string | — | |
quota | integer | — | |
signupGroup | string | — | |
state | string | — | |
updatedTime | string | — | |
usedCount | integer | — | |
username | string | — |
POST /v1/iam/issue-user-token
Mints an access token for the ?id=<owner>/<name> target
user (optional ?aud= resource, RFC 8707), issued by the authenticated +
allow-listed confidential client. The token's subject + owner are the TARGET
USER's, so a resource server scopes on the validated owner claim to the user's
tenant — indistinguishable from a token the user obtained directly. Response is
the camelCase {accessToken, expiresIn} body identity.ts consumes. Equivalent to
the RFC 8693 token-exchange grant, minus the subject_token proof (the console has
the user's id, not a token) — the reason this compat shim exists.
POST /v1/iam/keys/delete
Revokes an API key. Anything still presenting it stops being authorized at once, so roll the replacement out before you revoke.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
GET /v1/iam/keys/get
Returns one API key: what it is called, what it may reach, and when it was issued.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — | |
name | query | string | — |
POST /v1/iam/keys/mint
(re)generates the target user's key of the requested TYPE and
returns it once, over the shared authorizeMinter + mintTarget seam. ?type=secret
(the default) yields the confidential sk-; ?type=publishable yields the pk- that
is safe to ship in client JS and resolves to an org, never a principal.
It writes the schema.Key row that the resolvers actually read. schema.User.AccessKey is not a credential and nothing resolves it, so a key stamped there would authenticate nobody.
POST /v1/iam/keys/revoke
Clears the target user's key of the requested TYPE (immediate
revoke). Scoped by the same ?type field mint takes, so revoking the browser key
leaves the server key working. A secret key's stored value is the sk- in its
schema.Key row.
POST /v1/iam/keys/update
Changes what a key is called or what it may reach. The credential itself is not reissued — the key in your deployment keeps working.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | AccessKey (pk-) is the publishable identifier and lookup index; AccessSecret (sk-) is the confidential secret. |
accessSecret | string | — | |
application | string | — | |
createdAt | string | — | |
createdTime | string | — | CreatedTime and UpdatedTime are RFC3339 audit stamps carried as strings for byte-parity with the v1 row (orm.Model… |
deleted | boolean | — | |
displayName | string | — | DisplayName is the human-facing label. |
expireTime | string | — | ExpireTime is when the key stops being honored (empty = never). |
id | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | Owner is the tenant that holds the key; Name is unique within Owner. |
scope | string | — | Scope is the key's ACCESS CLASS, orthogonal to Type (which names the bound principal). |
state | string | — | |
type | string | — | Type is the scope the key is bound to — "Organization", "Application", "User", or "General" — and Organization /… |
updatedAt | string | — | |
updatedTime | string | — | |
user | string | — |
GET /v1/iam/keys
Returns your organization's API keys, newest first — what each is called, what it may reach, and its publishable half. Secret halves are never listed.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/keys
Issues an API key. A standard key comes back as a publishable half you may ship in client code and a secret half you must not — the secret is shown once, at creation, and cannot be retrieved afterwards. A publish-scoped key is issued with the publishable half only, so there is no secret to leak.
A name already used in your organization is refused rather than reissued, so creating twice never silently invalidates a key that is in production.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | AccessKey (pk-) is the publishable identifier and lookup index; AccessSecret (sk-) is the confidential secret. |
accessSecret | string | — | |
application | string | — | |
createdAt | string | — | |
createdTime | string | — | CreatedTime and UpdatedTime are RFC3339 audit stamps carried as strings for byte-parity with the v1 row (orm.Model… |
deleted | boolean | — | |
displayName | string | — | DisplayName is the human-facing label. |
expireTime | string | — | ExpireTime is when the key stops being honored (empty = never). |
id | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | Owner is the tenant that holds the key; Name is unique within Owner. |
scope | string | — | Scope is the key's ACCESS CLASS, orthogonal to Type (which names the bound principal). |
state | string | — | |
type | string | — | Type is the scope the key is bound to — "Organization", "Application", "User", or "General" — and Organization /… |
updatedAt | string | — | |
updatedTime | string | — | |
user | string | — |
GET /v1/iam/linked-accounts
Returns the sign-in identities linked to the calling person's account — every provider they can currently sign in with. It is what a security page lists next to the option to disconnect one.
POST /v1/iam/login
Signs a person in with the credential they typed, and — when the request is part of an OAuth flow — hands back the one-time code that finishes it. A second factor, if the account has one, is asked for and required here.
The password is compared against a stored one-way hash and is never logged, echoed or stored as typed.
GET /v1/iam/memberships
Answers either question about who belongs where: which organizations one person can act in, or who can act in one organization.
Both are org-scoped: a non-SuperAdmin may ask about ITS OWN org's roster, or about a user whose home org is its own, and nothing else. The bound comes from the verified credential via authz.Scope, so a request parameter can never widen it — a membership row names who may act and spend in an org, so a cross-tenant read is a customer roster leak.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
user | query | string | — | User is "<homeOrg>/<username>" — which organizations that identity may act in. |
org | query | string | — | Org is an organization — who may act in it. |
POST /v1/iam/memberships
Lets a person or an application act in an organization. It is the grant behind "add someone to the team", and it is safe to repeat — granting a membership that already exists changes nothing. Granting membership IS the org's authority to give, so it takes the same gate a write to that org's own registry row takes: a SuperAdmin, an admin of the org itself, or an org-admin-capable confidential client. One rule, one place (internal/authz).
POST /v1/iam/mfa/disable
Turns off the authenticator app for an account, so sign-in stops asking for a code. People may do this for themselves; doing it for somebody else takes an administrator, which is what makes it the reset path when a phone is lost.
POST /v1/iam/mfa/preferred
Picks which second factor an account is asked for first when it has more than one enrolled.
POST /v1/iam/mfa/setup/enable
Finishes the enrolment: from here the account's sign-ins ask for a code from the authenticator app. Repeating it re-enrols rather than failing.
POST /v1/iam/mfa/setup/initiate
Starts enrolling an authenticator app: it returns a fresh secret, a URL to render as a QR code, and one recovery code to keep somewhere safe.
Nothing is switched on yet. The enrolment counts only once it is confirmed with a code from the app, so abandoning this step leaves the account exactly as it was. Response: {status:"ok", data:{secret, url, recoveryCodes:[code]}}.
POST /v1/iam/mfa/setup/verify
Checks a six-digit code against an enrolment in progress, so somebody can confirm their authenticator app is set up correctly before it starts being required. Clocks a step out either way are accepted. A valid code → {status:"ok"}; an invalid one → 200 {status:"error"} (the casibase convention: clients branch on status, not the HTTP code).
POST /v1/iam/mint-user-keys
(re)generates the target user's key of the requested TYPE and
returns it once, over the shared authorizeMinter + mintTarget seam. ?type=secret
(the default) yields the confidential sk-; ?type=publishable yields the pk- that
is safe to ship in client JS and resolves to an org, never a principal.
It writes the schema.Key row that the resolvers actually read. schema.User.AccessKey is not a credential and nothing resolves it, so a key stamped there would authenticate nobody.
GET /v1/iam/oauth/authorize
Starts a sign-in — the address you send a browser to, and the beginning of every OAuth and OpenID Connect flow.
If the person is ALREADY signed in here, it does not ask them again: it returns them to the application with a one-time code and they never see this page. Otherwise it shows the right way to sign in for the application they are signing in to, or hands off to another identity provider if that is what they pick.
A client can say what it wants with prompt: none means answer without any
screen at all — with the code if a session exists, with an error if not, but
never with a page; login means ask for the password again even if a session
exists; select_account means let the person choose which identity to use.
It returns only to an address the application has registered. That check happens before anything else, so a request naming an unregistered address is refused where the person can see it rather than being bounced onwards.
POST /v1/iam/oauth/authorize
Starts a sign-in — the address you send a browser to, and the beginning of every OAuth and OpenID Connect flow.
If the person is ALREADY signed in here, it does not ask them again: it returns them to the application with a one-time code and they never see this page. Otherwise it shows the right way to sign in for the application they are signing in to, or hands off to another identity provider if that is what they pick.
A client can say what it wants with prompt: none means answer without any
screen at all — with the code if a session exists, with an error if not, but
never with a page; login means ask for the password again even if a session
exists; select_account means let the person choose which identity to use.
It returns only to an address the application has registered. That check happens before anything else, so a request naming an unregistered address is refused where the person can see it rather than being bounced onwards.
GET /v1/iam/oauth/callback
Completes the round-trip: it resolves and burns the single-use transaction (checking expiry + browser binding), exchanges and verifies the IdP response, links or provisions the local user, and mints the iam authorization code the relying party expects — then redirects to the original redirect_uri with code + state.
POST /v1/iam/oauth/device/info
Name the application a pending device code is asking to sign in.
Answers "what am I approving?" for a pending user_code, so the approval page can name the application a human is about to authorize. Both fields come off the pending code's OWN application — never off the portal the browser happens to be on — so the screen cannot name one application while the code belongs to another.
Requires a signed-in session, resolved from the browser's session cookie exactly as the approval itself resolves it. Not signed in is not a refusal to explain: it carries the stable login-required code the approval page branches on to sign the human in first.
POST for a read, deliberately, for the same reason RFC 7662 introspection beside it is POST: the argument is a SECRET. A user_code in a request line is copied into ingress and proxy access logs, which a POST body is not.
Unknown, expired, already used and already approved all get ONE opaque refusal — the same one the approval attempt would get. The user_code carries only 40 bits, so an answer that distinguished those states would be an oracle for hunting live codes; gated and opaque, this reveals strictly less than the approval the same caller could already attempt.
POST /v1/iam/oauth/device
Starts a sign-in on a device with no browser and no keyboard — a TV, a CLI, a headless box. It returns a short code to show the person and the address to send them to on a phone or laptop.
Nothing is granted until a human approves it there; until then the code is just a pending request.
POST /v1/iam/oauth/federation/mfa
Completes a sign-in that came in through another identity provider and still owes a second factor. The person supplies the factor here and the login finishes.
The account is fixed when the challenge is issued, not by the request, so no one can redirect a half-finished login onto somebody else's account. A wrong factor uses the challenge up: retrying means starting the sign-in again, the same as a mistyped password.
POST /v1/iam/oauth/introspect
Answers whether an access token is still good, and what it is good for — the check a resource server of yours makes before honouring a token it did not mint.
A token counts as active only if it verifies AND has not been revoked, so a revoked token reads as dead here immediately rather than until it expires. A token that is unknown, expired or revoked answers simply that it is not active, and nothing more — the endpoint is not a way to learn about tokens you were not given.
GET /v1/iam/oauth/logout
Ends a sign-in and sends the browser somewhere sensible. Accepts GET or POST, so it works as a plain link.
It ACTUALLY signs you out, which is worth stating because the endpoint spent a release not doing it: the whole body computed a redirect and answered {"status":"ok"} unconditionally — no session ended, no token revoked. A logout that reports success while leaving the session live is worse than no logout at all, because the person on the shared machine believes it worked. Three things happen here now, in this order:
- The browser session dies — sid revoked server-side AND the cookie expired (sessions.Clear). Server-side revocation is the load-bearing half: a copy of the cookie taken before logout must not still resolve.
- The relying party's tokens are revoked when an id_token_hint names it, so
the refresh token cannot mint a fresh access token after the human left.
Revocation state is authoritative — a JWT's
expstill reads valid for days, so expiry is necessary but never sufficient. - Only then is a redirect considered, and only to a REGISTERED uri.
The open-redirect guard is unchanged: a redirect happens only when a VERIFIED id_token_hint identifies the application and that application has registered the target. Anything else refuses to redirect — nobody can turn your logout link into a redirect to a site of their choosing.
POST /v1/iam/oauth/logout
Ends a sign-in and sends the browser somewhere sensible. Accepts GET or POST, so it works as a plain link.
It ACTUALLY signs you out, which is worth stating because the endpoint spent a release not doing it: the whole body computed a redirect and answered {"status":"ok"} unconditionally — no session ended, no token revoked. A logout that reports success while leaving the session live is worse than no logout at all, because the person on the shared machine believes it worked. Three things happen here now, in this order:
- The browser session dies — sid revoked server-side AND the cookie expired (sessions.Clear). Server-side revocation is the load-bearing half: a copy of the cookie taken before logout must not still resolve.
- The relying party's tokens are revoked when an id_token_hint names it, so
the refresh token cannot mint a fresh access token after the human left.
Revocation state is authoritative — a JWT's
expstill reads valid for days, so expiry is necessary but never sufficient. - Only then is a redirect considered, and only to a REGISTERED uri.
The open-redirect guard is unchanged: a redirect happens only when a VERIFIED id_token_hint identifies the application and that application has registered the target. Anything else refuses to redirect — nobody can turn your logout link into a redirect to a site of their choosing.
POST /v1/iam/oauth/revoke
Retires a token before it expires — what you call when someone signs out or a credential may have leaked.
Revoking an access token kills that token. Revoking a REFRESH token kills the whole chain it belongs to, so no further access tokens can be minted from it and every token already minted from it dies with it.
A token that is not yours, or that never existed, answers success and does nothing — so the endpoint cannot be used to discover which tokens are real.
PUBLIC clients revoke too, and must: sign-out is the only control a long-lived
refresh token has. hanzo-cli is a public PKCE client holding a 30-day rotating
refresh token, so a confidential-only revocation endpoint made hanzo auth logout a LOCAL DELETE — the credential it dropped stayed spendable at
hanzo.id for the rest of the month, with nothing able to kill it. Measured
2026-08-01: revoke answered 401 invalid_client and the refresh token went on
minting access tokens.
Widening authentication does not widen authority. The caller must still POSSESS the token — and possession already permits USE, of which revocation is the strict opposite — and the row must belong to the client that presents it, so a public client_id buys the ability to destroy exactly what its holder could otherwise spend. RFC 6749 §3.2.1 is the same reading: a client with no credentials identifies itself with client_id.
POST /v1/iam/oauth/token
Exchanges what your application is holding for the tokens it needs — the one-time code from a finished sign-in, a refresh token, or your own client credentials when the caller is a program rather than a person.
A refresh returns a NEW refresh token and retires the one you sent. If a retired one is ever presented again the whole chain is revoked, on the assumption that a token which came back from the dead was copied — so a stolen refresh token buys an attacker one use and costs them the session.
Responses are never cached, by any hop.
GET /v1/iam/oauth/userinfo
Returns the profile claims for whoever the access token belongs to — the standard OpenID Connect way to find out who is calling you without your application storing anything itself.
The token must still be live: revoke it and this stops answering.
POST /v1/iam/oauth/userinfo
Returns the profile claims for whoever the access token belongs to — the standard OpenID Connect way to find out who is calling you without your application storing anything itself.
The token must still be live: revoke it and this stops answering.
POST /v1/iam/onboard
Finishes setting up the account of whoever is calling — it creates their organization if they have none and puts them in it, so a person who has just signed up lands somewhere they can work.
It always acts on the caller and never on somebody named in the request, so there is no way to onboard another person's account through it.
POST /v1/iam/organizations/delete
Removes an organization and everything named inside it. There is no undo, and every session issued under it stops working.
The built-in admin organization cannot be deleted — losing it would leave the account with no way back in.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
GET /v1/iam/organizations/get
Returns one organization: its display, its defaults and the sign-in rules everyone in it inherits.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — | |
name | query | string | — |
POST /v1/iam/organizations/update
Changes an organization's display, its defaults and the sign-in rules everyone in it inherits. Which organization it is does not change, and neither does when it was created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accountItems | iam.AccountItem[] | — | |
accountMenu | string | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
countryCodes | string[] | — | |
createdAt | string | — | |
createdTime | string | — | |
dcrPolicy | string | — | |
defaultApplication | string | — | |
defaultAvatar | string | — | |
defaultPassword | string | — | |
deleted | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
enableSoftDeletion | boolean | — | |
enableTour | boolean | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
founder | string | — | |
hasPrivilegeConsent | boolean | — | |
id | string | — | |
initScore | integer | — | |
ipRestriction | string | — | |
ipWhitelist | string | — | |
isPersonal | boolean | — | |
isProfilePublic | boolean | — | |
kerberosKdcHost | string | — | |
kerberosKeytab | string | — | |
kerberosRealm | string | — | |
kerberosServiceName | string | — | |
languages | string[] | — | |
ldapAttributes | string[] | — | |
logo | string | — | |
logoDark | string | — | |
masterPassword | string | — | |
masterVerificationCode | string | — | |
mfaItems | iam.MfaItem[] | — | |
mfaRememberInHours | integer | — | |
name | string | — | |
| … | 19 more fields in the schema |
GET /v1/iam/organizations
Returns the organizations you can see, newest first. Narrow it to one parent account, and set a limit and offset to page through the rest.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — | |
limit | query | integer | — | |
offset | query | integer | — |
POST /v1/iam/organizations
Makes a new organization — the account your users, applications, roles, projects and workspaces are all named inside. It is the first write in a new tenant, and a name already in use is refused rather than taken over.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accountItems | iam.AccountItem[] | — | |
accountMenu | string | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
countryCodes | string[] | — | |
createdAt | string | — | |
createdTime | string | — | |
dcrPolicy | string | — | |
defaultApplication | string | — | |
defaultAvatar | string | — | |
defaultPassword | string | — | |
deleted | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
enableSoftDeletion | boolean | — | |
enableTour | boolean | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
founder | string | — | |
hasPrivilegeConsent | boolean | — | |
id | string | — | |
initScore | integer | — | |
ipRestriction | string | — | |
ipWhitelist | string | — | |
isPersonal | boolean | — | |
isProfilePublic | boolean | — | |
kerberosKdcHost | string | — | |
kerberosKeytab | string | — | |
kerberosRealm | string | — | |
kerberosServiceName | string | — | |
languages | string[] | — | |
ldapAttributes | string[] | — | |
logo | string | — | |
logoDark | string | — | |
masterPassword | string | — | |
masterVerificationCode | string | — | |
mfaItems | iam.MfaItem[] | — | |
mfaRememberInHours | integer | — | |
name | string | — | |
| … | 19 more fields in the schema |
POST /v1/iam/permissions/delete
Revokes a permission. Everyone who held access only through it loses that access immediately; grants they hold by another route are untouched.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
GET /v1/iam/permissions/get
Returns one permission: who it grants to, what it allows, and the resources it covers.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — | |
name | query | string | — |
POST /v1/iam/permissions/update
Changes who a permission grants to, what it allows, or the resources it covers. Access changes as soon as the write lands. What the permission is called does not change, and neither does when it was created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
actions | string[] | — | |
adapter | string | — | |
approveTime | string | — | |
approver | string | — | |
createdAt | string | — | |
createdTime | string | — | Descriptive metadata. |
deleted | boolean | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
effect | string | — | |
groups | string[] | — | |
id | string | — | |
isEnabled | boolean | — | |
model | string | — | Authorization model, targets, and decision. |
name | string | — | |
owner | string | — | Identity — the (owner, name) natural key. |
resourceType | string | — | |
resources | string[] | — | |
roles | string[] | — | |
state | string | — | |
submitter | string | — | Submission / approval workflow. |
updatedAt | string | — | |
users | string[] | — | Subjects the grant is evaluated for. |
GET /v1/iam/permissions
Returns the permissions in one organization, newest first — each one a grant saying which people or roles may do what, and to which resources.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/permissions
Grants a permission — the call that gives a person or a role the ability to do something. Adding refuses to overwrite a grant that already exists, so widening an existing one is an update, never an accident.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
actions | string[] | — | |
adapter | string | — | |
approveTime | string | — | |
approver | string | — | |
createdAt | string | — | |
createdTime | string | — | Descriptive metadata. |
deleted | boolean | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
effect | string | — | |
groups | string[] | — | |
id | string | — | |
isEnabled | boolean | — | |
model | string | — | Authorization model, targets, and decision. |
name | string | — | |
owner | string | — | Identity — the (owner, name) natural key. |
resourceType | string | — | |
resources | string[] | — | |
roles | string[] | — | |
state | string | — | |
submitter | string | — | Submission / approval workflow. |
updatedAt | string | — | |
users | string[] | — | Subjects the grant is evaluated for. |
POST /v1/iam/preferences
Saves the calling person's own settings and returns the full set afterwards. Send only the settings you are changing — the rest are kept, so two screens can save at once without one undoing the other.
POST /v1/iam/projects/delete
Removes a project. The people and roles in your organization are unchanged; what goes is the scope itself, so move anything addressed by it first.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/projects/get
Returns one project: what it is called and how it is set up.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/projects/update
Changes a project's settings. What it is called does not change, and neither does when it was created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — | |
workspace | string | — |
GET /v1/iam/projects
Returns your organization's projects, newest first — the scope people pick between when their work is separated by product or client rather than by team.
You see your own organization's projects and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/projects
Makes a project inside your organization — the scope people pick between when their work is separated by product or client rather than by team. A name already used in the organization is refused.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — | |
workspace | string | — |
POST /v1/iam/providers/delete
Removes a provider. Sign-in through it stops for every application that used it, so give those applications another method first.
A provider that is already gone answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/providers/get
Returns one provider: what it connects to and how it is configured. Its credentials come back masked.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/providers/update
Changes a provider's settings or rotates the credentials it holds. The change takes effect on the next sign-in through it — sessions already issued are unaffected.
A provider that is not there answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
appId | string | — | |
bucket | string | — | |
category | string | — | |
cert | string | — | |
clientId | string | — | |
clientId2 | string | — | |
clientSecret | string | — | |
clientSecret2 | string | — | |
content | string | — | |
createdAt | string | — | |
createdTime | string | — | |
customAuthUrl | string | — | |
customLogo | string | — | |
customTokenUrl | string | — | |
customUserInfoUrl | string | — | |
deleted | boolean | — | |
disableSsl | boolean | — | |
displayName | string | — | |
domain | string | — | |
emailRegex | string | — | |
enablePkce | boolean | — | |
enableProxy | boolean | — | |
enableSignAuthnRequest | boolean | — | |
endpoint | string | — | |
host | string | — | |
httpHeaders | object | — | |
id | string | — | |
idP | string | — | |
intranetEndpoint | string | — | |
issuerUrl | string | — | |
metadata | string | — | |
method | string | — | |
name | string | — | |
owner | string | — | |
pathPrefix | string | — | |
port | integer | — | |
providerUrl | string | — | |
receiver | string | — | |
regionId | string | — | |
scopes | string | — | |
| … | 8 more fields in the schema |
GET /v1/iam/providers
Returns your organization's providers, newest first — the identity providers your people sign in with, and the senders and connectors your applications go through.
You see your own organization's providers and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/providers
Adds an identity provider your people can sign in with, or a service your applications send through — a social or enterprise login, an email or SMS sender, a storage or payment connector.
A provider is configured once and then switched on per application, so several applications can share one set of credentials.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
appId | string | — | |
bucket | string | — | |
category | string | — | |
cert | string | — | |
clientId | string | — | |
clientId2 | string | — | |
clientSecret | string | — | |
clientSecret2 | string | — | |
content | string | — | |
createdAt | string | — | |
createdTime | string | — | |
customAuthUrl | string | — | |
customLogo | string | — | |
customTokenUrl | string | — | |
customUserInfoUrl | string | — | |
deleted | boolean | — | |
disableSsl | boolean | — | |
displayName | string | — | |
domain | string | — | |
emailRegex | string | — | |
enablePkce | boolean | — | |
enableProxy | boolean | — | |
enableSignAuthnRequest | boolean | — | |
endpoint | string | — | |
host | string | — | |
httpHeaders | object | — | |
id | string | — | |
idP | string | — | |
intranetEndpoint | string | — | |
issuerUrl | string | — | |
metadata | string | — | |
method | string | — | |
name | string | — | |
owner | string | — | |
pathPrefix | string | — | |
port | integer | — | |
providerUrl | string | — | |
receiver | string | — | |
regionId | string | — | |
scopes | string | — | |
| … | 8 more fields in the schema |
GET /v1/iam/registry/jwks
Publishes the public key your registry uses to verify the tokens issued above — the one URL to configure so the registry trusts logins without holding any secret of its own.
If no signing key is available it refuses rather than publishing an empty set, because a registry that trusts nothing looks identical to one that trusts everything until somebody tries to push.
GET /v1/iam/registry/token
Signs a container client in to your registry. docker login, and every
build tool that pushes or pulls images, lands here: it exchanges the
credential for a short-lived token scoped to exactly the repositories that
credential may touch.
Both of the shapes container tooling uses are accepted, so the same login works whichever client your pipeline runs.
POST /v1/iam/registry/token
Signs a container client in to your registry. docker login, and every
build tool that pushes or pulls images, lands here: it exchanges the
credential for a short-lived token scoped to exactly the repositories that
credential may touch.
Both of the shapes container tooling uses are accepted, so the same login works whichever client your pipeline runs.
GET /v1/iam/resolve-key
Answers which organization a PUBLISHABLE key belongs to — what a service of yours calls to attribute a request that arrived carrying a key shipped in a browser.
It names an organization and never a person: no path through it can load or
return a user, so a key you put in client code cannot become a way to learn
who anyone is. A key that is expired, secret rather than publishable, or
simply unknown all answer with the same sentence, and with a code saying
which of those it was. Only a confidential service that already proved it may
resolve keys at all ever reads that code — there is no anonymous caller here
to probe for which keys exist — and telling it apart is what lets the holder
be told to re-mint an expired key instead of hunting a configuration error.
POST /v1/iam/revoke-user-keys
Clears the target user's key of the requested TYPE (immediate
revoke). Scoped by the same ?type field mint takes, so revoking the browser key
leaves the server key working. A secret key's stored value is the sk- in its
schema.Key row.
POST /v1/iam/roles/delete
Removes a role. Everyone in it loses the access it carried; their accounts, and any other role they hold, are untouched.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/roles/get
Returns one role: who is in it, and the roles it includes.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/roles/update
Changes who is in a role, or which roles it includes. Access changes for everyone in it as soon as the write lands. What the role is called does not change, and neither does when it was created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
groups | string[] | — | |
isEnabled | boolean | — | |
name | string | — | |
owner | string | — | |
roles | string[] | — | |
users | string[] | — |
GET /v1/iam/roles
Returns your organization's roles, newest first — each a named group of people that permissions are granted to.
You see your own organization's roles and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/roles
Makes a role — a named group of people that permissions are granted to. Granting to a role rather than to each person is what keeps access correct as your team changes: add someone to the role and they inherit everything it can do. A name already used in your organization is refused.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
groups | string[] | — | |
isEnabled | boolean | — | |
name | string | — | |
owner | string | — | |
roles | string[] | — | |
users | string[] | — |
GET /v1/iam/scim/v2/ResourceTypes/{name}
Returns one provisionable record kind in full.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes |
GET /v1/iam/scim/v2/ResourceTypes
Returns the kinds of record this directory provisions and the address of each, so your identity provider discovers them rather than having them configured by hand.
GET /v1/iam/scim/v2/Schemas/{id}
Returns one attribute definition in full.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes |
GET /v1/iam/scim/v2/Schemas
Returns the attribute definitions this directory understands, so your identity provider knows which fields it may send and what they mean before it sends any.
GET /v1/iam/scim/v2/ServiceProviderConfig
Tells your identity provider which parts of SCIM this directory supports, so it configures itself instead of you filling in a form.
Filtering and partial updates are supported. Bulk operations, sorting and entity tags are not — an IdP that reads this will not attempt them.
GET /v1/iam/scim/v2/Users/{owner}/{name}
Returns one person in the standard SCIM shape. An administrator may read anyone in the organization; everyone else may read only themselves.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | |
name | path | string | yes |
PUT /v1/iam/scim/v2/Users/{owner}/{name}
Overwrites a person's SCIM attributes with what your identity provider sends — how a change made there lands here.
Only the attributes SCIM describes are replaced. Anything the standard does not cover — their multi-factor enrolment above all — survives untouched, so a routine sync from your IdP can never quietly strip someone's second factor or bring a deleted account back.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | |
name | path | string | yes |
PATCH /v1/iam/scim/v2/Users/{owner}/{name}
Applies a partial change from your identity provider — one attribute moved, not the whole record resent.
The change is applied onto the person as they currently are, so everything you did not mention keeps its value, including the parts SCIM does not describe.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | |
name | path | string | yes |
DELETE /v1/iam/scim/v2/Users/{owner}/{name}
Deprovisions a person — how removing someone in your identity provider removes their access here. Their sessions stop working immediately. Takes an administrator.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | path | string | yes | |
name | path | string | yes |
GET /v1/iam/scim/v2/Users
Returns the people in your organization to your identity provider, in the standard SCIM shape, so an IdP can reconcile its directory against ours. Searchable by username or email address, and paged.
Reading the whole list takes an administrator; an ordinary person is refused.
POST /v1/iam/scim/v2/Users
Provisions a person from your identity provider — how a new hire gets an account here automatically when they are added over there.
Takes an administrator. Making someone an administrator takes more than that, so an IdP integration cannot escalate anyone by setting a flag.
POST /v1/iam/send-verification-code
Validates the request, mints + persists an OTP, and reports success. The request fields are read via fiber's FormValue — the escape hatch zip exposes for form bodies (multipart or urlencoded) — since the typed JSON Bind does not apply here. v1 also accepts countryCode/method/ checkUser/captchaType; iam ignores them (the captcha/forget/MFA flows those drive are not ported), and CAPTCHA verification is likewise not enforced — iam models no captcha provider — so the code is issued once the destination and application validate.
POST /v1/iam/service-accounts/{name}/keys
Serves POST /v1/iam/service-accounts/:name/keys: mint a fresh key, invalidating the prior one, and return the new raw secret exactly once.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes |
DELETE /v1/iam/service-accounts/{name}
Serves DELETE /v1/iam/service-accounts/:name.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | yes |
GET /v1/iam/service-accounts
Returns your organization's service accounts — what each is called and when it was created. Never their secrets: a key's secret half exists in a response exactly once, when it is minted. Paginated in memory over the already org-scoped slice — the set per org is small, so a dedicated count query is overkill (v1 service_account.go:296-307).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
organization | query | string | — | Organization is the organization whose service accounts to list. |
p | query | integer | — | P is the 1-indexed page to return. Paging takes both p and pageSize — leave either out, or send something that is not a… |
pageSize | query | integer | — | Size is how many accounts a page holds. |
POST /v1/iam/service-accounts
Makes a service account — an identity for a program rather than a person, for a script, a bot or a deployment that has to authenticate on its own.
It comes back with its first key, and the secret half is shown ONCE, here. There is no way to read it again; if you lose it, rotate.
POST /v1/iam/sessions/create
Records a sign-in. Signing in again from another browser adds to the session rather than replacing it, so one person can be signed in from a laptop and a phone at once.
Ask for an exclusive sign-in and the opposite holds: the new sign-in is the only one left and every other browser is signed out. That is the setting to use when one person may hold only one live session at a time.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | yes | |
exclusiveSignin | boolean | — | |
name | string | yes | |
owner | string | yes | |
sessionId | string[] | — |
POST /v1/iam/sessions/delete
Signs a person out of one application — the session ends and every browser carrying it stops being authenticated.
A session that is already gone reports that nothing was deleted rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | yes | |
name | string | yes | |
owner | string | yes |
POST /v1/iam/sessions/get
Returns one person's session in one application — when it began and which browsers or devices are still carrying it.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | yes | |
name | string | yes | |
owner | string | yes |
POST /v1/iam/sessions/list
Returns who is currently signed in to your organization, newest first, and can be narrowed to one person or one application. It is what you read before signing someone out.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | — | |
name | string | — | |
owner | string | yes |
POST /v1/iam/sessions/update
Replaces the set of browsers a session covers — signing out the ones you leave off while the session itself stays live. A session that does not exist is reported as missing rather than created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
application | string | yes | |
name | string | yes | |
owner | string | yes | |
sessionId | string[] | — |
POST /v1/iam/set-preferred-mfa
Picks which second factor an account is asked for first when it has more than one enrolled.
POST /v1/iam/signin
Completes a sign-in: it exchanges the one-time code your application was handed at the end of the login flow for a live session, and returns the signed-in account.
The code works once. This is the call that turns a finished login into something your application can act on.
POST /v1/iam/signup
Creates an account from the sign-up form and applies the application's own sign-up rules — whether self-service registration is open at all, and which fields it requires.
The password is hashed before it is stored and is never returned.
POST /v1/iam/tokens/delete
Revokes an access token. Whatever was using it stops being authorized at once.
A token that is already gone answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/tokens/get
Returns one access token: who and what it was issued to, and when it expires.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/tokens/issue
Mints an access token for the ?id=<owner>/<name> target
user (optional ?aud= resource, RFC 8707), issued by the authenticated +
allow-listed confidential client. The token's subject + owner are the TARGET
USER's, so a resource server scopes on the validated owner claim to the user's
tenant — indistinguishable from a token the user obtained directly. Response is
the camelCase {accessToken, expiresIn} body identity.ts consumes. Equivalent to
the RFC 8693 token-exchange grant, minus the subject_token proof (the console has
the user's id, not a token) — the reason this compat shim exists.
POST /v1/iam/tokens/update
Changes an access token's scope or expiry.
A token that is not there answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessToken | string | — | |
accessTokenHash | string | — | |
application | string | — | |
code | string | — | |
codeChallenge | string | — | |
codeChallengeMethod | string | — | |
codeExpireIn | integer | — | |
codeIsUsed | boolean | — | |
createdAt | string | — | |
createdTime | string | — | |
deleted | boolean | — | |
expiresIn | integer | — | |
id | string | — | |
name | string | — | |
nonce | string | — | Nonce is the OIDC authorize nonce, stored on the code and echoed into the id_token minted at the exchange (OIDC Core… |
organization | string | — | |
owner | string | — | |
publicGrant | boolean | — | PublicGrant records that this grant was established WITHOUT client authentication — a PKCE code exchange from a client… |
redirectUri | string | — | RedirectUri binds the authorization code to the exact redirect URI of the authorize request (RFC 6749 §4.1.3): the… |
refreshConsumed | boolean | — | |
refreshExpireIn | integer | — | |
refreshFamily | string | — | Refresh-token rotation state (v2). Each refresh belongs to a family (the grant); rotation mints a new row in the same… |
refreshToken | string | — | |
refreshTokenHash | string | — | |
resource | string | — | RFC 8707 resource indicator |
scope | string | — | |
tokenType | string | — | |
updatedAt | string | — | |
user | string | — | |
userCode | string | — |
GET /v1/iam/tokens
Returns the access tokens issued in your organization, newest first, and can be narrowed to one organization. Use it to see what is currently authorized before revoking anything.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — | |
organization | query | string | — |
POST /v1/iam/tokens
Records an access token — the credential an application or integration presents on a caller's behalf.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessToken | string | — | |
accessTokenHash | string | — | |
application | string | — | |
code | string | — | |
codeChallenge | string | — | |
codeChallengeMethod | string | — | |
codeExpireIn | integer | — | |
codeIsUsed | boolean | — | |
createdAt | string | — | |
createdTime | string | — | |
deleted | boolean | — | |
expiresIn | integer | — | |
id | string | — | |
name | string | — | |
nonce | string | — | Nonce is the OIDC authorize nonce, stored on the code and echoed into the id_token minted at the exchange (OIDC Core… |
organization | string | — | |
owner | string | — | |
publicGrant | boolean | — | PublicGrant records that this grant was established WITHOUT client authentication — a PKCE code exchange from a client… |
redirectUri | string | — | RedirectUri binds the authorization code to the exact redirect URI of the authorize request (RFC 6749 §4.1.3): the… |
refreshConsumed | boolean | — | |
refreshExpireIn | integer | — | |
refreshFamily | string | — | Refresh-token rotation state (v2). Each refresh belongs to a family (the grant); rotation mints a new row in the same… |
refreshToken | string | — | |
refreshTokenHash | string | — | |
resource | string | — | RFC 8707 resource indicator |
scope | string | — | |
tokenType | string | — | |
updatedAt | string | — | |
user | string | — | |
userCode | string | — |
POST /v1/iam/unlink
Disconnects one sign-in identity from an account, so that provider can no longer be used to sign in as that person. Their account and every other way they sign in are untouched. Two principals may do it, and only two: the account holder itself, and a SuperAdmin (a member of the reserved admin org, the one predicate). An ORG ADMIN deliberately may NOT — unlinking is not tenant administration, it is unpicking someone's own sign-in method, so the generic org-admin rule is the wrong answer here.
A holder unlinking itself must also be permitted by the application — the provider link's CanUnlink flag — so an organization that mandates federated sign-in cannot have its users strand themselves. A SuperAdmin is not bound by that flag; it is the platform's own recovery path. Fail-closed throughout.
POST /v1/iam/update-application
Updates one of your applications — its display, its sign-in methods and the redirect URIs it is allowed to return to. Which organization and name the application has are fixed when it is created and are not editable here.
A redirect URI you add becomes an allowed sign-in origin, so this is the call that makes login work from a new host.
The older spelling of PUT /v1/iam/application.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
affiliationUrl | string | — | |
category | string | — | |
cert | string | — | |
certObj | iam.Cert | — | |
certPublicKey | string | — | |
clientCert | string | — | |
clientId | string | — | ClientId is the OAuth2/OIDC client identifier and the GLOBAL key every confidential-client resolver authenticates… |
clientSecret | string | — | |
codeResendTimeout | integer | — | |
cookieExpireInHours | integer | — | |
createdAt | string | — | |
createdTime | string | — | |
customScopes | iam.ScopeDescription[] | — | |
defaultGroup | string | — | |
deleted | boolean | — | |
description | string | — | |
disableSamlAttributes | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
domain | string | — | |
enableAutoSignin | boolean | — | |
enableCodeSignin | boolean | — | |
enableExclusiveSignin | boolean | — | |
enableLinkWithEmail | boolean | — | |
enablePassword | boolean | — | |
enableSamlAssertionSignature | boolean | — | |
enableSamlC14n10 | boolean | — | |
enableSamlCompress | boolean | — | |
enableSamlPostBinding | boolean | — | |
enableSignUp | boolean | — | |
enableSigninSession | boolean | — | |
enableWebAuthn | boolean | — | |
environment | string | — | |
expireInHours | number | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
footerHtml | string | — | |
forcedRedirectOrigin | string | — | |
forgetUrl | string | — | |
| … | 50 more fields in the schema |
POST /v1/iam/update-organization
Updates your organization — its display, its default settings and the sign-in rules everyone in it inherits.
The older spelling of POST /v1/iam/organizations/update.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accountItems | iam.AccountItem[] | — | |
accountMenu | string | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
countryCodes | string[] | — | |
createdAt | string | — | |
createdTime | string | — | |
dcrPolicy | string | — | |
defaultApplication | string | — | |
defaultAvatar | string | — | |
defaultPassword | string | — | |
deleted | boolean | — | |
disableSignin | boolean | — | |
displayName | string | — | |
enableSoftDeletion | boolean | — | |
enableTour | boolean | — | |
failedSigninFrozenTime | integer | — | |
failedSigninLimit | integer | — | |
favicon | string | — | |
founder | string | — | |
hasPrivilegeConsent | boolean | — | |
id | string | — | |
initScore | integer | — | |
ipRestriction | string | — | |
ipWhitelist | string | — | |
isPersonal | boolean | — | |
isProfilePublic | boolean | — | |
kerberosKdcHost | string | — | |
kerberosKeytab | string | — | |
kerberosRealm | string | — | |
kerberosServiceName | string | — | |
languages | string[] | — | |
ldapAttributes | string[] | — | |
logo | string | — | |
logoDark | string | — | |
masterPassword | string | — | |
masterVerificationCode | string | — | |
mfaItems | iam.MfaItem[] | — | |
mfaRememberInHours | integer | — | |
name | string | — | |
| … | 19 more fields in the schema |
POST /v1/iam/update-preferences
Saves the calling person's own settings and returns the full set afterwards. Send only the settings you are changing — the rest are kept, so two screens can save at once without one undoing the other.
POST /v1/iam/update-provider
Updates a provider's settings or rotates the credentials it holds. The change takes effect on the next sign-in through it — sessions already issued are unaffected.
The older spelling of POST /v1/iam/providers/update.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
appId | string | — | |
bucket | string | — | |
category | string | — | |
cert | string | — | |
clientId | string | — | |
clientId2 | string | — | |
clientSecret | string | — | |
clientSecret2 | string | — | |
content | string | — | |
createdAt | string | — | |
createdTime | string | — | |
customAuthUrl | string | — | |
customLogo | string | — | |
customTokenUrl | string | — | |
customUserInfoUrl | string | — | |
deleted | boolean | — | |
disableSsl | boolean | — | |
displayName | string | — | |
domain | string | — | |
emailRegex | string | — | |
enablePkce | boolean | — | |
enableProxy | boolean | — | |
enableSignAuthnRequest | boolean | — | |
endpoint | string | — | |
host | string | — | |
httpHeaders | object | — | |
id | string | — | |
idP | string | — | |
intranetEndpoint | string | — | |
issuerUrl | string | — | |
metadata | string | — | |
method | string | — | |
name | string | — | |
owner | string | — | |
pathPrefix | string | — | |
port | integer | — | |
providerUrl | string | — | |
receiver | string | — | |
regionId | string | — | |
scopes | string | — | |
| … | 8 more fields in the schema |
POST /v1/iam/update-role
Updates a role's members or the roles it includes. Access changes for everyone in it as soon as the write lands.
The older spelling of POST /v1/iam/roles/update.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
domains | string[] | — | |
groups | string[] | — | |
isEnabled | boolean | — | |
name | string | — | |
owner | string | — | |
roles | string[] | — | |
users | string[] | — |
POST /v1/iam/update-user
Updates one of your users' profile, roles or credentials. Send a password to reset it; leave it out and the current one stands.
The older spelling of POST /v1/iam/users/update, with the user's fields at the top level rather than wrapped in {user, password}.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | — | |
accessSecret | string | — | |
accessSecretHash | string | — | |
accessToken | string | — | |
address | string[] | — | |
addresses | iam.Address[] | — | |
adfs | string | — | |
affiliation | string | — | |
alipay | string | — | |
amazon | string | — | |
apple | string | — | |
applicationScopes | iam.ConsentRecord[] | — | |
auth0 | string | — | |
avatar | string | — | |
avatarType | string | — | |
azuread | string | — | |
azureadb2c | string | — | |
baidu | string | — | |
balance | number | — | |
balanceCredit | number | — | |
balanceCurrency | string | — | |
battlenet | string | — | |
bilibili | string | — | |
bio | string | — | |
birthday | string | — | |
bitbucket | string | — | |
box | string | — | |
cart | iam.CartItem[] | — | |
cloudfoundry | string | — | |
countryCode | string | — | |
createdAt | string | — | |
createdIp | string | — | |
createdTime | string | — | |
currency | string | — | |
custom | string | — | |
custom2 | string | — | |
custom3 | string | — | |
custom4 | string | — | |
custom5 | string | — | |
custom6 | string | — | |
| … | 147 more fields in the schema |
POST /v1/iam/users/delete
Removes a person from your organization. Their sessions stop working immediately and the account is gone rather than suspended — to keep the record and only stop sign-in, update the user instead.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
GET /v1/iam/users/get
Returns one person in your organization, by the organization they belong to and their username. Passwords, API secrets and MFA material are stripped from the response.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes | |
name | query | string | yes |
POST /v1/iam/users/update
Changes a person's profile, their roles, or the credentials they sign in with. Send a password to reset it; leave it out and their current one keeps working.
Who they are does not change: their organization, username and the identifier their existing sessions are keyed on all survive the write, so an update never signs anyone out.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
password | string | — | |
user | iam.User | — |
GET /v1/iam/users
Returns a page of the people in your organization, with the total so you can page through the rest. Passwords, API secrets and MFA material are stripped from every entry.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | yes | |
limit | query | integer | — | |
offset | query | integer | — |
POST /v1/iam/users
Adds a person to your organization. Send a password and it becomes the one they sign in with; it is hashed before it is stored and never comes back in any response.
The username is checked against the same rule every account in the Hanzo Cloud is held to, whichever way it was created — this call, password signup, a social sign-in, or SCIM — so a name accepted here works everywhere.
A name already taken in your organization is refused rather than overwritten.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
password | string | — | |
user | iam.User | — |
POST /v1/iam/verification-codes
Validates the request, mints + persists an OTP, and reports success. The request fields are read via fiber's FormValue — the escape hatch zip exposes for form bodies (multipart or urlencoded) — since the typed JSON Bind does not apply here. v1 also accepts countryCode/method/ checkUser/captchaType; iam ignores them (the captcha/forget/MFA flows those drive are not ported), and CAPTCHA verification is likewise not enforced — iam models no captcha provider — so the code is issued once the destination and application validate.
GET /v1/iam/web3/nonce
Starts a wallet sign-in: it returns a one-time challenge for the wallet to sign. The challenge is good once and is tied to the site that asked for it, so a signature collected elsewhere cannot be replayed here.
POST /v1/iam/web3/verify
Completes a wallet sign-in: it verifies the signed challenge and, if it holds, signs the wallet's owner in.
This IS the login — it answers exactly as a password sign-in does, so the rest of your flow does not branch on how somebody arrived.
POST /v1/iam/webauthn-credentials/delete
Removes a passkey or security key — what you call when a device is lost. Make sure the person has another way to sign in first.
A credential that is already gone answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/webauthn-credentials/get
Returns one passkey or security key: whose it is, what device it lives on, and when it was registered.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
owner | string | yes |
POST /v1/iam/webauthn-credentials/update
Renames a registered passkey or security key, so a person can tell their devices apart.
A credential that is not there answers "nothing changed" rather than an error, so the call is safe to repeat.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
aaguid | string | — | |
attachment | string | — | |
attestationType | string | — | |
backupEligible | boolean | — | |
backupState | boolean | — | |
cloneWarning | boolean | — | |
createdAt | string | — | |
createdTime | string | — | |
credentialId | string | — | |
deleted | boolean | — | |
id | string | — | |
name | string | — | |
owner | string | — | |
publicKey | string | — | |
signCount | integer | — | |
transport | string[] | — | |
updatedAt | string | — | |
user | string | — | |
userPresent | boolean | — | |
userVerified | boolean | — |
GET /v1/iam/webauthn-credentials
Returns the passkeys and security keys registered in your organization, newest first — which device each belongs to and when it was last used.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/webauthn-credentials
Registers a passkey or security key for a person, so they can sign in with their device instead of a password.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
aaguid | string | — | |
attachment | string | — | |
attestationType | string | — | |
backupEligible | boolean | — | |
backupState | boolean | — | |
cloneWarning | boolean | — | |
createdAt | string | — | |
createdTime | string | — | |
credentialId | string | — | |
deleted | boolean | — | |
id | string | — | |
name | string | — | |
owner | string | — | |
publicKey | string | — | |
signCount | integer | — | |
transport | string[] | — | |
updatedAt | string | — | |
user | string | — | |
userPresent | boolean | — | |
userVerified | boolean | — |
GET /v1/iam/whoami
Tells you who the current caller is — the lightweight check a page makes on load to decide whether to render signed-in or signed-out.
It answers for a session cookie or a bearer token alike, and says plainly when nobody is signed in rather than failing.
POST /v1/iam/workspaces/delete
Removes a workspace. The people and roles in your organization are unchanged; what goes is the scope itself.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/workspaces/get
Returns one workspace: what it is called and how it is set up.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | |
owner | string | — |
POST /v1/iam/workspaces/update
Changes a workspace's settings. What it is called does not change, and neither does when it was created.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
bucket | string | — | |
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — |
GET /v1/iam/workspaces
Returns your organization's workspaces, newest first — the scope a team works in, alongside projects rather than instead of them.
You see your own organization's workspaces and no one else's; which organization that is comes from your credentials, not from the request.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
owner | query | string | — |
POST /v1/iam/workspaces
Makes a workspace inside your organization — the scope a team works in, alongside projects rather than instead of them. A name already used in the organization is refused.
Request body — application/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
bucket | string | — | |
createdTime | string | — | |
description | string | — | |
displayName | string | — | |
isDefault | boolean | — | |
metadata | string | — | |
name | string | — | |
organization | string | — | |
owner | string | — | |
tags | string[] | — |
How is this guide?