Skip to main content

Documentation Index

Fetch the complete documentation index at: https://orchestrator-docs.hexoforge.dev/llms.txt

Use this file to discover all available pages before exploring further.

Token management

  1. Validate JWTs locally. Fetch JWKS from /.well-known/jwks.json, cache it, and verify tokens in your backend to avoid a round trip on every request.
  2. Refresh before expiry. Access tokens default to 15 minutes. Refresh about 30–60 seconds before expiry to avoid transient 401s.
  3. Treat refresh tokens as single-use. Each /refresh call invalidates the previous refresh token. Always persist the latest pair.
  4. Handle revocation. A 401 on a formerly valid token can mean password reset or admin revocation. Send the user back through login.

Security

  1. Never ship API keys in client code. Proxy requests through your backend or serverless layer so only your servers add X-API-Key.
  2. Protect refresh tokens. Prefer httpOnly cookies on the-web; use platform secure storage on mobile. Do not store refresh tokens in localStorage in the browser.
  3. Model the TOTP two-step flow. When /login returns requires_totp: true, collect a TOTP code and call /login/totp before you have tokens. Login tickets expire in 5 minutes.

Performance

  1. Cache JWKS with rotation in mind. Cache for 1–24 hours. On verification failure with an unknown kid, refresh JWKS.
  2. Do not call /me on every request. It hits the database. Prefer reading sub, roles, permissions, and email_verified from the JWT.
  3. Use last_login_method from login responses. You can persist it on the client for UX hints without calling /me.

Error handling

  1. Treat 401 and 403 differently. 401 means bad or missing credentials; 403 means good credentials but policy or state blocks access.
  2. Backoff on 429. Use the RateLimit header’s reset value to wait until the window resets.
  3. Avoid email enumeration. /forgot-password always returns 204. Login uses the same error for wrong email and wrong password.

Integration flows

Registration with email verification

POST /register → requires_email_verification: true
(user receives OTP)
POST /verify-email { email, otp }
POST /login { email, password } → tokens

Login with TOTP

POST /login → requires_totp: true, login_ticket
POST /login/totp { login_ticket, totp_code } → tokens

Token lifecycle

POST /login → access_token + refresh_token
(access token expires, default 15 minutes)
POST /refresh { refresh_token } → new pair
POST /logout { refresh_token }

Last login method hint (browser example)

// After successful login
const { access_token, refresh_token, last_login_method } = response;
if (last_login_method) {
  localStorage.setItem('last_login_method', last_login_method);
}

// On login page load
const lastMethod = localStorage.getItem('last_login_method');

JWT claims reference

Access tokens are RS256-signed. Typical claims and header fields:
Claim / fieldDescription
subUser ID (UUID)
pidProject ID (UUID)
rolesRole slugs
permissionsPermission slugs
email_verifiedBoolean
kid (header)Key ID for JWKS lookup
expExpiry (unix time)
iatIssued-at (unix time)