Account and auth
Sign in, sessions, two-factor authentication and your own user account.
These endpoints act on the signed-in user, not a workspace, so they do not take OD-Workspace. They are for user sessions; API keys cannot use them.
Sign-in
Section titled “Sign-in”| Method | Path | Description |
|---|---|---|
GET |
/v1/auth/config |
Providers, password login, sign-up and challenge settings |
POST |
/v1/auth/register |
{email, password, name, turnstile_token?} |
POST |
/v1/auth/login |
{email, password, turnstile_token?} |
POST |
/v1/auth/mfa |
{mfa_token, code} |
POST |
/v1/auth/refresh |
{user_id?} + the account’s refresh cookie → new access token, rotates that account’s refresh token |
POST |
/v1/auth/accounts |
The accounts this browser is signed in to, with their workspaces. Rotates nothing |
POST |
/v1/auth/logout |
Revokes this account’s session in the browser and closes its sockets; {all: true} for every account |
POST |
/v1/auth/password/forgot |
{email}, always 204 |
POST |
/v1/auth/password/reset |
{token, password} |
POST |
/v1/auth/email/verify |
{token} |
POST |
/v1/auth/email/resend |
|
GET |
/v1/auth/oauth/{provider}/start?redirect_to= |
Redirects to Google, Microsoft, GitHub or OIDC |
GET |
/v1/auth/oauth/{provider}/callback |
Redirects to APP_URL/auth/callback?code= |
POST |
/v1/auth/oauth/exchange |
{code, code_verifier?} → access token, or mfa_required. The verifier is required for a code from a native sign-in |
POST |
/v1/auth/app-attest/challenge |
{} → {challenge}, single use, five minutes. For the iPhone app’s App Attest |
POST |
/v1/auth/app-attest/keys |
{key_id, attestation, challenge} → 204. Registers an attested key |
curl https://api.opendesk.sh/v1/auth/config{ "providers": [{ "id": "google", "name": "Google" }], "password_login": true, "signup_enabled": true, "turnstile_site_key": "0x4AAA..." }/v1/auth/config also has native: { app_attest, push, relay_url } for the native apps: whether App Attest is accepted, and the push mode (direct, relay or off).
Login, registration and password reset are rate limited and protected by a Turnstile challenge when one is configured; a native iPhone client may send an App Attest proof instead. Native clients receive the refresh token in the body rather than a cookie: see Native apps. Login gives the same answer, in the same time, for an unknown email and a wrong password.
Two-factor authentication
Section titled “Two-factor authentication”| Method | Path | Description |
|---|---|---|
POST |
/v1/auth/totp/setup |
→ {secret, otpauth_url} |
POST |
/v1/auth/totp/enable |
{code} → {recovery_codes} |
POST |
/v1/auth/totp/disable |
{code} |
A code can be used only once. Recovery codes are single use.
Your account
Section titled “Your account”| Method | Path | Description |
|---|---|---|
GET |
/v1/me |
{ user, memberships } |
PATCH |
/v1/me |
{name?, avatar_url?} |
POST |
/v1/me/password |
{current_password, new_password} |
GET |
/v1/me/sessions |
Your sessions, with current marking this one and client (web, desktop or ios) |
DELETE |
/v1/me/sessions/{id} |
Revoke a session |
GET |
/v1/me/devices |
Phones registered for push notifications |
POST |
/v1/me/devices |
{platform: "ios", token? or relay_token?, environment, app_version, name}: register this phone, bound to the calling session |
PATCH |
/v1/me/devices/{id} |
{muted_types?}: notification types this phone does not get, on top of your notification preferences |
DELETE |
/v1/me/devices/{id} |
Remove a phone |
DELETE |
/v1/me |
{password?, code?}: delete your account |
type User = { id: string; email: string; name: string; avatar_url: string; email_verified: boolean; totp_enabled: boolean; created_at: string };type Membership = { workspace: Workspace; role: Role };A device belongs to the session that registered it: signing out or revoking that session removes it. See Push notifications.
Notification preferences
Section titled “Notification preferences”| Method | Path | Description |
|---|---|---|
GET |
/v1/me/notification-preferences |
Your preferences in the workspace named by OD-Workspace |
PATCH |
/v1/me/notification-preferences |
{email_cadence?, digest_hour?, timezone?, paused_until?, types?: [{type, email?, push?, desktop?}]} |
POST |
/v1/me/notification-preferences/test |
Send yourself a sample notification email (5 an hour) |
POST |
/v1/notifications/unsubscribe |
Public. {token} from a notification email: turns off that workspace’s notification emails |
type NotificationPreferences = { email_cadence: "instant" | "hourly" | "daily" | "off"; digest_hour: number; timezone: string; paused_until: string | null; email: string; email_verified: boolean; delay_minutes: number; types: { type: string; group: "tickets" | "team" | "ai_billing"; email: boolean; push: boolean; desktop: boolean; defaults: { email: boolean; push: boolean; desktop: boolean } }[];};Channels (email, push for your phones, desktop for the desktop app) are chosen per type and per workspace. The email schedule and the pause apply to your whole account. With instant, an unread notification is emailed after delay_minutes, together with anything else waiting for you in that workspace; a notification you read first is never emailed. Notification emails carry a one-click unsubscribe (RFC 8058).
Passwords are 12 to 128 characters and are refused if they appear in a list of breached passwords. Deleting your account is refused while you are the only owner of a workspace that has other members.