📘 Public beta · Endpoints are stable; OpenAPI specs and SDKs ship monthly. See changelog →
Getting started
Authentication

Authentication

Every Quantum Elixir API supports two authentication methods. You pick based on who's calling.

MethodUsed byHow
API keyYour backend, SDKs, scripts, cronAuthorization: Bearer qe_sk_...
Session cookieYour team using our dashboardSet via the dashboard login flow. Not for programmatic clients.

This page covers API keys. Session cookies are documented on each product's dashboard.

Key format

qe_sk_<env>_<32-char-secret>
  • env = sandbox or live
  • Secret is base32. Compares case-sensitively.

The product-specific dashboards may show a slightly different prefix (e.g. qedi_ for Document Intelligence, bs_ for Bank Statement, aml_ for AML). The suite is migrating to a unified qe_sk_ prefix; existing keys keep working indefinitely.

Sending the key

Put it in the Authorization header:

curl https://sandbox.quantumelixir.tech/identity/api/auth/me \
  -H "Authorization: Bearer $QE_API_KEY"

Never put keys in query strings or URLs

We will reject any request that puts a Bearer token in a query parameter. URLs are logged everywhere — proxy logs, browser history, CDN caches.

Scopes

Every key is issued with an explicit list of scopes. A key without the right scope returns HTTP 403:

{ "error": "missing scope: customers:write" }

The full scope vocabulary per product is documented on each product's overview page. The most common patterns:

ScopeGrants
readRead-only across all resources (legacy wildcard)
writeRead + write across all resources (legacy wildcard)
{resource}:viewRead a specific resource type
{resource}:writeCreate/update a specific resource
webhooks:manageRegister and rotate webhook endpoints
api:manageIssue, rotate, and revoke API keys

Least-privilege by default

Production keys should never have write (the wildcard). Issue one key per integration concern: payments-service gets evaluate:write, kyc-service gets customers:write + verifications:view, etc. If one key leaks, you rotate just that one.

Rotation

Rotate any key at any time from Dashboard → Settings → API Keys → ⋯ → Rotate. Old key is valid for a 24-hour grace window so you can deploy the new key without downtime, then auto-revokes.

You can also rotate via API:

POST/api/api-keys/{id}/rotate
Auth · API keyScope · api:manage

The response includes the new secret (shown once) and a previousValidUntil timestamp.

Acting as a user — actAsUserId

Machine accountability for four-eyes workflows. When an API key creates or transitions an artifact that is subject to four-eyes (rule approval, SAR submission, case close), AML and Anti-Fraud need to know which human is accountable for the action — an opaque key can't be the drafter or the submitter on its own.

Set actAsUserId on the API key to bind it to a real user account in your org:

POST/api/api-keys
Auth · API keyScope · api:manage
{
  "name":         "compliance-bot · MLRO",
  "scopes":       ["sar.write", "rule.read", "case.write"],
  "actAsUserId":  "usr_mlro_lead..."
}

When the bot calls POST /api/sar-filings/{id}/submit, the server resolves the effective user to usr_mlro_lead... and writes both submittedById: "usr_mlro_lead..." and the key's apiKeyId into the audit log. Four-eyes enforcement compares effective submittedById against filedById — same as if a human had clicked the button.

PropertyValue
Required for four-eyes endpointsYes — request returns HTTP 422 api_key_not_bound_to_user
Required for read endpointsNo — read keys don't need a user binding
Editable post-creationYes — PATCH /api/api-keys/{id} with { "actAsUserId": "..." }
Visible in audit logAlways — both userId (effective) and apiKeyId are written

Don't share keys across humans

Binding a key to a single human is the audit-trail contract. If two compliance officers share one bot key, four-eyes guarantees break — both become the same "user" from the system's view. Issue one key per officer + per task, or use dashboard logins.

Service principals (advanced)

When one Quantum Elixir product calls another (e.g. Orchestration calling AML on your behalf), it uses service principal keys. These are scoped to a specific calling service via callerServiceSlug. You don't issue these — Orchestration and AI Automation issue them automatically when you connect a sibling service.

Failure modes

StatusBodyWhat it means
401{ "error": "missing or invalid Bearer" }No key, malformed key, or revoked key
401{ "error": "key expired" }Key passed its expiresAt
403{ "error": "missing scope: ..." }Key is valid but lacks the scope this endpoint needs
403{ "error": "key is sandbox; endpoint is live" }Cross-environment call (sandbox key against live URL)
429{ "error": "rate limit exceeded" }Per-key rate limit — see Rate limits

Webhook signatures

Webhooks use a different auth model — HMAC-SHA256 over the raw body. See Webhooks.