Authentication and session model
Orbit recognizes three credential classes:dv_-prefixed API keys, dashboard
session tokens, and the SCIM provisioning token. Each request carries one of
them, and a single resolution rule decides the class from the headers you
send. This page defines the vocabulary, states the rule, and tells you which
credential each audience (server, dashboard, identity provider) should send.
For route-by-route rejection codes, see the
authentication troubleshooting page.
Section 1 — The credential vocabulary
Three credential classes authenticate to Orbit. They look different on the wire, authorize different surfaces, and get managed in different places. API keys (dv_ prefix). Long-lived credentials you create in the
dashboard under Settings → API Keys and use for programmatic calls. Four
forms exist:
A public key (
pk) is meant for browser or mobile bundles, so the platform
rejects write and administrative scopes on it at creation with a 422. For
anything that sends or modifies data — messages:write, contacts:write,
admin, the * wildcard — use a secret key (sk).
Dashboard session token (JWT). A signed JSON Web Token issued when a
dashboard user signs in — email/password, or SAML single sign-on where
enabled. Session tokens carry a user’s identity and the org memberships they
belong to; they authenticate the person, not an application. You recognize
one by the eyJ prefix that every JWT starts with.
SCIM provisioning token. A dedicated Bearer credential that
authenticates exactly one surface: the /scim/v2/{orgSlug} endpoints your
identity provider calls to create and remove dashboard users. It is neither
an API key nor a session token, and it is valid on no other route.
Section 2 — How resolution is decided
The server determines which credential class a request carries with one precedence rule:- A non-empty
X-API-Keyheader is checked first. - Only if
X-API-Keyis absent does the server look atAuthorization: Bearer, and only when the token carries adv_prefix is it treated as an API key. - Any other Bearer token — the
eyJ…JWT shape — is treated as a dashboard session token.
eyJ and every API key starts with dv_,
the two forms never collide on the Authorization header. This is the
fallback rule stated on the authentication page, and it
exists so browser environments where the X-API-Key custom header is blocked
by CORS can still send an API key as a Bearer token.
The practical consequence: sending both an X-API-Key header and a session
Bearer is unambiguous — the API key wins. A malformed request mixes the two
only when the client generated it wrong; the resolution rule still makes the
outcome deterministic.
Section 3 — Session token lifecycle
A dashboard session token moves through four states:- Issued at login. Email/password sign-in, or the SAML callback from your identity provider when SSO is configured, both mint a signed JWT.
- Used until expiry. The dashboard sends it on every API request as an
Authorization: Bearer eyJ…header. Session tokens have bounded lifetimes; an expired token gets a401. - Rotated. Re-authentication or a token refresh issues a replacement JWT; the old one expires on its own schedule.
- Terminated on sign-out. Signing out invalidates the token; the next request with it fails.
dv_ keys while users come and go through the IdP.
Section 4 — The SCIM provisioning token
Generate the token under Settings → SCIM in the dashboard, or withPOST /api/v1/settings/scim/generate-token. The full value is shown once
at creation — copy it into your IdP immediately; if you lose it, generate a
new one. The endpoint is a dashboard-session-authorized call, so minting or
rotating the token requires a signed-in administrator.
Your IdP then sends the token as a Bearer credential against the SCIM
resource endpoints (/scim/v2/{orgSlug}/Users, /Groups), which return
application/scim+json. The step-by-step IdP walkthroughs for Okta, Entra
ID, and generic clients are in the SCIM 2.0 provisioning guide
(and the tenant-owned posture view in compliance).
Because the value is shown once, treat rotation as “generate a new token,
update the IdP, discard the old” — a one-step operation, but one you must
plan for when you do not retain the original.
Section 5 — Where tenant identity comes from
The credential is also how the platform learns which tenant a request belongs to. Every org is a row in the sharedorganizations catalog; each API key is
issued against exactly one org, and the server resolves the key back to that
org on every request. A dashboard session token likewise carries its org
bound at login and selected from the user’s memberships. Client-supplied
claims of tenant identity (tenant_id fields in a request body) are never
trusted. The full resolution chain — catalog lookup, tenant_<tenant_id>
schema routing, and the subaccount sharing rules — is covered in
Tenant isolation.
Section 6 — What to branch on
Send the credential class that matches the caller’s relationship to the platform:
When you build on an SDK, set the same choice: the SDK sends either an API
key or a session token; the resolution rule above applies untouched.
Two rules of thumb close out most mistakes:
- A 401 means the credential did not resolve. A truncated key, a
dv_value sent asAuthorization: Bearerwithout the full prefix, or a session token whose expiry has passed all fail here. - A 422 from SSO or SCIM usually means you sent a session surface an API
key (or vice versa). Match the credential class to the table above, then
re-check the scopes page for
skvspkif the route still rejects.