REST API
API: Auth
Sign in and manage tokens. All endpoints require authentication unless noted. 58 endpoints.
POST /api/auth/forgot-password
Section titled “POST /api/auth/forgot-password”Request a password reset email
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/auth/google
Section titled “POST /api/auth/google”Sign in with a Google ID token — links only where Google owns the address, never creates accounts (EZS-4)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
idToken |
string | yes | |
deviceId |
string | no | |
trustedDeviceToken |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/handoff
Section titled “POST /api/auth/handoff”Start signing this browser in from the phone app (EZS-9)
Responses: 201 · 400 · 401 · 409
GET /api/auth/handoff/{id}
Section titled “GET /api/auth/handoff/{id}”Which browser is asking to be signed in (for the approving app; the number is read off that screen)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/auth/handoff/{id}/approve
Section titled “POST /api/auth/handoff/{id}/approve”Approve (with the number the browser shows) or decline a browser’s sign-in, as the app’s user (EZS-9)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
approve |
boolean | yes | |
matchCode |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/handoff/{id}/redeem
Section titled “POST /api/auth/handoff/{id}/redeem”The browser’s poll: its status, then its session once approved (EZS-9; 60 s)
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
secret |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/auth/identities
Section titled “GET /api/auth/identities”Linked sign-in accounts (EZS-7)
Responses: 200 · 400 · 401
DELETE /api/auth/identities/{id}
Section titled “DELETE /api/auth/identities/{id}”Unlink a sign-in account
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/auth/identities/google
Section titled “POST /api/auth/identities/google”Link a Google account to the signed-in user — needs a recent sign-in, or the password / an authenticator code (EZS-4)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
idToken |
string | yes | |
currentPassword |
string | no | |
code |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/identities/microsoft
Section titled “POST /api/auth/identities/microsoft”Finish linking a Microsoft account to the signed-in user: redeem the one-time grant (UXR-SSO-SIGNUP)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
grant |
string | yes | |
codeVerifier |
string | yes |
Responses: 200 · 400 · 401 · 403 · 404 · 409
POST /api/auth/identities/microsoft/start
Section titled “POST /api/auth/identities/microsoft/start”Start linking a Microsoft account to the signed-in user — needs a recent sign-in, or the password / an authenticator code (UXR-SSO-SIGNUP)
Answers the Microsoft address to open; the callback returns to Settings → Security with a grant for POST /api/auth/identities/microsoft.
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
codeChallenge |
string | yes | |
currentPassword |
string | no | |
code |
string | no |
Responses: 200 · 400 · 401 · 403 · 404
POST /api/auth/login
Section titled “POST /api/auth/login”User login
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes | |
password |
string | yes | |
deviceId |
string | no | |
trustedDeviceToken |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/logout
Section titled “POST /api/auth/logout”Logout (revoke refresh token)
Ends the session the access token belongs to and revokes the presented refresh token (cookie, or body for native apps). An access token that has expired is no obstacle: the refresh token then says whose session ends. The refresh cookie is cleared on every answer.
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
refreshToken |
string | no |
Responses: 204 — No content · 401 · 404
POST /api/auth/magic/request
Section titled “POST /api/auth/magic/request”Email a sign-in link and code — always answers the same, at once (EZS-3)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/auth/magic/verify
Section titled “POST /api/auth/magic/verify”Sign in with the emailed link’s token, or the address and its code (EZS-3)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | no | |
email |
string | no | |
code |
string | no | |
deviceId |
string | no | |
trustedDeviceToken |
string | no |
Responses: 200 · 400 · 401 · 404
GET /api/auth/me
Section titled “GET /api/auth/me”Get current user profile
Responses: 200 · 400 · 401 · 404
PUT /api/auth/me
Section titled “PUT /api/auth/me”Update the signed-in user’s profile
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes |
Responses: 200 · 400 · 401 · 404
POST /api/auth/mfa/challenge
Section titled “POST /api/auth/mfa/challenge”Complete an MFA-gated login with a TOTP code
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
mfaToken |
string | yes | |
code |
string | yes | |
deviceId |
string | no | |
rememberDevice |
boolean | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/mfa/disable
Section titled “POST /api/auth/mfa/disable”Disable MFA (requires a valid current code)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | yes |
Responses: 200 · 400 · 401 · 403 · 404
POST /api/auth/mfa/enable
Section titled “POST /api/auth/mfa/enable”Enable MFA after verifying a TOTP code
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | yes |
Responses: 200 · 400 · 401 · 403 · 404
POST /api/auth/mfa/recovery-codes
Section titled “POST /api/auth/mfa/recovery-codes”Regenerate MFA recovery codes (invalidates the previous set)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | yes |
Responses: 200 · 400 · 401 · 403 · 404
POST /api/auth/mfa/setup
Section titled “POST /api/auth/mfa/setup”Begin TOTP enrollment (returns secret + otpauth URI)
Responses: 200 · 400 · 401 · 404
GET /api/auth/mfa/status
Section titled “GET /api/auth/mfa/status”Whether TOTP MFA is enabled for the caller
Responses: 200 · 400 · 401 · 404
POST /api/auth/microsoft
Section titled “POST /api/auth/microsoft”Finish signing in with Microsoft: redeem the one-time grant; links only where the tenant verified the address’s domain, never creates accounts (UXR-SSO-SIGNUP)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
grant |
string | yes | |
codeVerifier |
string | yes | |
deviceId |
string | no | |
trustedDeviceToken |
string | no |
Responses: 200 · 400 · 401 · 403 · 404
POST /api/auth/microsoft/callback
Section titled “POST /api/auth/microsoft/callback”Microsoft’s form post after sign-in: verifies the ID token and sends the browser back to the app (UXR-SSO-SIGNUP)
Spends the flow’s state once, verifies the ID token (Microsoft’s keys, this app as the audience, the issuer of the token’s own tenant, unexpired, the flow’s nonce) and redirects to the app: /login, /signup or Settings with a one-time grant in the fragment, or with ?sso_error=<code>. Never a session: the app redeems the grant.
Responses: 303 — To the app’s page for this flow, with a grant or an sso_error code
POST /api/auth/microsoft/start
Section titled “POST /api/auth/microsoft/start”Start signing in or signing up with Microsoft: answers the Microsoft address to open (UXR-SSO-SIGNUP)
Body: the intent and the S256 challenge of a verifier the app keeps. Microsoft posts the ID token to POST /api/auth/microsoft/callback, which sends the browser back to the app with a one-time grant in the URL fragment; the app redeems it with the verifier at POST /api/auth/microsoft (sign-in) or POST /api/signup/sso/microsoft (signup). Work and school accounts only.
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
intent |
"signin" | "signup" |
yes | |
codeChallenge |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/auth/passkeys
Section titled “GET /api/auth/passkeys”Your passkeys (EZS-7)
Responses: 200 · 400 · 401
PATCH /api/auth/passkeys/{id}
Section titled “PATCH /api/auth/passkeys/{id}”Rename a passkey
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes |
Responses: 200 · 400 · 401 · 404
DELETE /api/auth/passkeys/{id}
Section titled “DELETE /api/auth/passkeys/{id}”Remove a passkey
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/auth/passkeys/login/options
Section titled “POST /api/auth/passkeys/login/options”Start signing in with a passkey (EZS-2)
Responses: 200 · 400 · 401 · 404
POST /api/auth/passkeys/login/verify
Section titled “POST /api/auth/passkeys/login/verify”Finish signing in with a passkey — a user-verified passkey is two factors (EZS-2)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
challengeId |
string | yes | |
response |
object | yes | |
deviceId |
string | no | |
trustedDeviceToken |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/passkeys/register/options
Section titled “POST /api/auth/passkeys/register/options”Start adding a passkey — needs a recent sign-in, or the password / an authenticator code (EZS-2)
Body (optional, only when the session is not recent): { currentPassword } or { code }. An empty POST is fine otherwise.
Responses: 200 · 400 · 401 · 404
POST /api/auth/passkeys/register/verify
Section titled “POST /api/auth/passkeys/register/verify”Finish adding a passkey (EZS-2)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
challengeId |
string | yes | |
response |
object | yes | |
name |
string | no |
Responses: 201 · 400 · 401 · 409
POST /api/auth/password
Section titled “POST /api/auth/password”Change the signed-in user’s local password
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
currentPassword |
string | yes | |
newPassword |
string | yes |
Responses: 200 · 400 · 401 · 403 · 404 · 409
POST /api/auth/refresh
Section titled “POST /api/auth/refresh”Refresh access token
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
refreshToken |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/register
Section titled “POST /api/auth/register”Register a new user (requires authentication)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes | |
name |
string | yes | |
password |
string | yes | |
companyId |
string | yes |
Responses: 201 · 400 · 401 · 409
POST /api/auth/reset-password
Section titled “POST /api/auth/reset-password”Reset password using a reset token
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
token |
string | yes | |
password |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/auth/saml/{slug}/metadata
Section titled “GET /api/auth/saml/{slug}/metadata”SAML service-provider metadata for an organization
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug |
string | yes |
Responses: 200
POST /api/auth/saml/acs
Section titled “POST /api/auth/saml/acs”SAML assertion consumer service — completes a SAML sign-in
Responses: 200
GET /api/auth/security-events
Section titled “GET /api/auth/security-events”The caller’s recent sign-in, password, two-factor and session events
A self-only projection of the audit trail: an allowlist of account-security actions, with time, address, client and platform. Not the administrator audit route.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit |
integer | no | |
before |
string | no | Opaque cursor from a previous page. |
Responses: 200 · 400 · 401 · 404
GET /api/auth/sessions
Section titled “GET /api/auth/sessions”The caller’s active sessions (browser families and native installations)
Newest activity first. current marks the session this request was made with; a session revoked elsewhere disappears within the guard’s 30-second check window.
Responses: 200 · 400 · 401 · 404
DELETE /api/auth/sessions/{id}
Section titled “DELETE /api/auth/sessions/{id}”End one of the caller’s sessions
Only the caller’s own sessions can be ended; anything else answers 404. Ending the current session signs this client out on its next request.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
POST /api/auth/sessions/revoke-others
Section titled “POST /api/auth/sessions/revoke-others”End every session except the current one
Responses: 200 · 400 · 401 · 404
GET /api/auth/signin-methods
Section titled “GET /api/auth/signin-methods”Which easy sign-in methods this deployment offers (EZS)
Responses: 200 · 400 · 401 · 404
GET /api/auth/signin-options
Section titled “GET /api/auth/signin-options”Which easy sign-in methods the signed-in user may use — company policy, and nothing around SSO (EZS-7)
Responses: 200 · 400 · 401 · 404
GET /api/auth/sso/{slug}/login
Section titled “GET /api/auth/sso/{slug}/login”Redirect to the organization’s identity provider
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug |
string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
client |
"android" | "ios" | "macos" | "windows" |
no | |
code_challenge |
string | no | |
device_id |
string | no |
Responses: 200
GET /api/auth/sso/callback
Section titled “GET /api/auth/sso/callback”OIDC callback — completes the SSO login
Responses: 200
GET /api/auth/sso/config
Section titled “GET /api/auth/sso/config”The company’s SSO configuration (secret redacted)
Responses: 200
PUT /api/auth/sso/config
Section titled “PUT /api/auth/sso/config”Create or update the company’s SSO configuration (OIDC or SAML)
Setting up, changing or switching on single sign-on is part of the Enterprise plan (403 PLAN_TIER_REQUIRED below it, details.feature “sso”). A workspace whose paid Business period was running when it moved keeps it until that period’s renewal. On every plan an existing connection can be switched off and a SAML connection can take its identity provider’s rotated signing certificate (same entity and sign-in address); signing in through a connection that exists, reading it and removing it work on every plan too.
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
protocol |
"oidc" | "saml" |
no | |
issuerUrl |
string | no | |
clientId |
string | no | |
clientSecret |
string | no | |
idpEntityId |
string | null | no | |
idpSsoUrl |
string | no | |
idpCertificates |
array of string | no | PEM certificates the IdP signs with (any one may sign — list two during a rotation) |
emailAttribute |
string | null | no | |
nameAttribute |
string | null | no | |
allowedDomains |
array of string | no | |
autoProvision |
boolean | no | |
isEnabled |
boolean | no |
Responses: 200
DELETE /api/auth/sso/config
Section titled “DELETE /api/auth/sso/config”Remove the company’s SSO configuration
Responses: 200
POST /api/auth/sso/exchange
Section titled “POST /api/auth/sso/exchange”Exchange a mobile SSO one-time code for tokens (PKCE)
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | yes | |
codeVerifier |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/auth/sso/lookup
Section titled “GET /api/auth/sso/lookup”Whether an email signs in with SSO, and an opaque handle that starts it
startHandle is an opaque handle for GET /api/auth/sso/{handle}/login, valid for an hour and different on every call. The answer names no organization or domain; the sign-in the handle starts does (a SAML request’s Issuer, an OIDC redirect’s identity provider and client ID).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
email |
string | yes |
Responses: 200 · 400 · 401 · 404
GET /api/auth/trusted-devices
Section titled “GET /api/auth/trusted-devices”Devices that skip the authenticator code (EZS-5)
Responses: 200 · 400 · 401
DELETE /api/auth/trusted-devices
Section titled “DELETE /api/auth/trusted-devices”Forget every remembered device
Responses: 200 · 400 · 401 · 404
DELETE /api/auth/trusted-devices/{id}
Section titled “DELETE /api/auth/trusted-devices/{id}”Forget a remembered device
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id |
string | yes |
Responses: 204 — No content · 401 · 404
GET /api/auth/web-session
Section titled “GET /api/auth/web-session”Redeem a WebView session code (sets cookie, redirects to the viewer)
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
code |
string | yes |
Responses: 200
POST /api/auth/web-session-code
Section titled “POST /api/auth/web-session-code”Mint a one-time code to open an authenticated WebView session
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
dashboardId |
string | no | |
cardId |
string | no |
Responses: 200 · 400 · 401 · 404
POST /api/auth/workspace
Section titled “POST /api/auth/workspace”Switch the authenticated session to another workspace
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
workspaceId |
string | yes | |
refreshToken |
string | no |
Responses: 200 · 400 · 401 · 404