Skip to main content

Authentication

Orbit authenticates API requests two ways: an API key for server-to-server calls, and a session Bearer token for dashboard users. Enterprise organizations can additionally sign users in through SAML single sign-on and provision them through SCIM. Pick the method that matches how the request is made.

API Key (Server-to-Server)

Include your API key in the X-API-Key header:
The same call through an official SDK keeps the key in one place — the client you init once on your backend:
Set ORBIT_API_KEY on your server, never in client-side code. Full install and usage for every language is under SDKs.

Bearer Token (Dashboard Users)

For dashboard users, use JWT Bearer tokens:
You may also pass an API key via Authorization: Bearer dv_live_pk_... (any dv_ key — dv_live_sk_, dv_test_sk_, dv_live_pk_, dv_test_pk_) for environments where the X-API-Key custom header is blocked by CORS. The server accepts either form: it reads X-API-Key first, then falls back to a Bearer token that carries a dv_ prefix. A JWT (which starts with eyJ) is still treated as a dashboard session token, so the two never collide.

API Key Format

A public key (dv_live_pk_ / dv_test_pk_) is meant to be embedded in client-side code, so it is restricted to read-only scopes at creation. Write and administrative scopes — messages:write, contacts:write, admin, the * wildcard, and the sensitive account reads billing:read / settings:read — are rejected for a public key with a 422. Use a secret key (dv_live_sk_) for any operation that sends or modifies data.A scoped public key works — this one carries only messages:read:
Ask to mint that same key with a write scope and the create call is rejected:
Still treat any key you ship to a browser or mobile bundle as publicly visible and scope it to the minimum reads it needs.

Create your first key in the dashboard

The Settings → API Keys page in the dashboard is the same key surface the create endpoint above drives. Click Create key and set three things:
  1. Type — the same four classes as the format table: live secret (dv_live_sk_), test secret (dv_test_sk_), live public (dv_live_pk_), or test public (dv_test_pk_). Pick a test secret for a first integration: it can never deliver real traffic or bill your wallet, so your first run is free of side effects.
  2. Scopes — grant the minimum the integration needs. Public keys accept read-only scopes only; write and administrative scopes are rejected at creation, as the example above shows.
  3. Expiry — optionally give the key an expires_at. A key with no expiry stays valid until you rotate or revoke it; a short expiry suits trials and CI runners.
The dashboard shows the new key’s plaintext once — copy it into your secret manager in the same sitting. Later views show only the masked prefix and the last four characters. Prefer automation over clicks: the POST /api/v1/settings/api-keys call above creates the same key with type and scopes in the body. For a full first-key-to-production recipe — sandbox key first, then a scoped production key, then the controls below — follow the API keys end-to-end guide.

Manage the key after creation

Minting the key is step one. Orbit then gives each key a lifecycle and a set of per-key controls, all reachable from the same Settings → API Keys surface and the settings/api-keys API. Rotate on a schedule, not on a rumor. Rotation (POST /api/v1/settings/api-keys/:id/rotate) mints a replacement and retires the old key in one of two modes:
  • Grace (default). The old key stays valid for grace_period_hours (default 24, clamped to 1–168 hours) so both keys authenticate while you migrate. The response’s old_key_expires_at tells you the exact cutoff — it is the earlier of the old key’s original expires_at and the end of the grace window.
  • Immediate. The old key is revoked in the same transaction. Reserve this for a leaked key; routine rotations should always overlap.
The full lifecycle — dual-valid window, cutoff math, audit entries, and the guided cutover — is in API key lifecycle and rotation. Bind the key to your network. A per-key IP allowlist makes the key authenticate only from your source IPs or CIDR ranges; requests from anywhere else fail before they touch your data. A leaked key is then useless outside your infrastructure. Bound the key’s blast radius. Four independent controls cap what one key can do before you notice:
  • Usage limits — a requests-per-minute rate limit and a monthly request quota per key (or as an org-wide default), so a noisy or compromised key trips its own 429 instead of consuming the throughput your other keys share.
  • Usage budget alerts — a lightweight per-operator threshold on a key’s analytics drawer that badges the key as usage crosses 80% and 100% of the ceiling.
  • Spend budgets — a persisted monthly money ceiling per key (minor currency units plus ISO-4217 currency) with one alert per threshold, shared with your whole team.
Encryption keys are a separate lane. If you also manage customer-managed encryption keys (BYOK), those protect stored data; the API keys on this page are the authentication credentials that call the API. The two surfaces are independent.

What to do when a key leaks

A key committed to a repo, pasted into a chat, or found in someone else’s logs is an incident, not a hygiene task. Act in this order:
  1. Revoke first. Send POST /api/v1/settings/api-keys/:id/revoke before anything else. Revoking a leaked key stops the meter at the revoke timestamp — usage billed into your account ends there regardless of what the leaked key does afterward — so revocation is always the right first move, even before you investigate.
  2. Mint a replacement. If the integration must keep working, rotate with mode: "immediate" instead of a bare revoke: the replacement is minted and the old key is killed in one transaction. Copy the new plaintext from the rotation response — it is the only place it ever appears.
  3. Review the damage path. Check the key’s usage in its analytics drawer (usage limits) and its audit log entries — grace rotations write api_key.rotated, panic-revokes write api_key.revoked_immediate, so a compliance review can tell them apart.
  4. Prevent the repeat. Scope the replacement minimally, add an IP allowlist so the key only works from your network, and consider an expiry so forgetful cleanup stops being a risk.

Troubleshooting

Most authentication failures resolve in seconds once the rejection code is decoded — INVALID_API_KEY, EXPIRED_TOKEN, WRONG_KEY_MODE, and the distinguishing messages all map to a specific gate. See Troubleshooting: authentication, key mode, and IP allowlist failures. For rate and quota rejections (429), see Troubleshooting: rate limits. Dashboard login lockouts (ACCOUNT_LOCKED on users, not API keys) are covered in Troubleshooting: ACCOUNT_LOCKED at dashboard sign-in.

Single sign-on (SAML)

Enterprise organizations can log dashboard users in through a SAML 2.0 identity provider — Okta, Microsoft Entra ID (formerly Azure AD), OneLogin, Google Workspace, or PingFederate. SSO authenticates people into the dashboard; it does not mint API keys, so server-to-server calls still use the methods above. An owner configures the connection under Settings → Single sign-on in the dashboard (or via PATCH /api/v1/settings/saml): set your IdP’s SSO URL, entity ID, and signing certificate, then use Test connection before enabling it. Each organization gets its own set of endpoints, keyed by your organization slug (orgSlug). They live at the API root, not under /api/v1: Point your IdP at the metadata endpoint, for example https://api.orbit.devotel.io/auth/saml/acme/metadata for the acme organization. The response — served as application/xml — is the service-provider descriptor your IdP admin imports:
The metadata is public and safe to paste into your IdP directly — it carries our ACS and logout URLs and the email NameIDFormat, no secrets.

Directory provisioning (SCIM)

Provision and deprovision dashboard users automatically from your identity provider over SCIM 2.0. Generate a provisioning token under Settings → SCIM (or via POST /api/v1/settings/scim/generate-token) — the token is shown once, so copy it into your IdP immediately. Your IdP sends the token as a Bearer credential on every request:
Endpoints follow the SCIM 2.0 spec and return application/scim+json. They are keyed by your organization slug and live at the API root, not under /api/v1: A worked user create — the exact shape your IdP (or a direct client) sends and gets back for POST /scim/v2/{orgSlug}/Users:
The 201 response is the created User resource, application/scim+json:
SAML and SCIM are independent: SSO controls how users sign in, SCIM controls which users exist. You can enable either on its own, though most IdPs configure both together.
For the full provisioning walkthrough — base URL construction, role mapping, IdP health checks, and Okta / Entra / generic-client steps — see the SCIM 2.0 provisioning guide.