APEX Developers

Authentication

APEX uses two credential families. Which one you use depends on whether you are making runtime product calls (queries, sends, renders) or control-plane calls (provisioning tenants).

Both are issued by your Reisiger platform operator during onboarding — there is no self-service sign-up. Credentials are delivered as a secure bundle; never commit them to source control.

1. Tenant API key — runtime product calls

A platform API key issued per tenant through Forge:

2. Machine-to-machine token — OAuth2 client-credentials

For services that authenticate with the platform identity provider, and for control-plane operations (tenant provisioning, configuration integrations):

``` POST {token_url} Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id={client_id}&client_secret={client_secret}&scope={scopes} ```

Minting a token

PowerShell:

$body = @{
  grant_type    = 'client_credentials'
  client_id     = $env:APEX_CLIENT_ID
  client_secret = $env:APEX_CLIENT_SECRET
  scope         = 'apex/your-tenant.read apex/your-tenant.write'
}
$token = (Invoke-RestMethod -Method Post -Uri $env:APEX_TOKEN_URL -Body $body).access_token

curl:

curl -s -X POST "$APEX_TOKEN_URL" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=$APEX_CLIENT_ID&client_secret=$APEX_CLIENT_SECRET&scope=apex/your-tenant.read"

Python:

import os, requests

resp = requests.post(os.environ["APEX_TOKEN_URL"], data={
    "grant_type": "client_credentials",
    "client_id": os.environ["APEX_CLIENT_ID"],
    "client_secret": os.environ["APEX_CLIENT_SECRET"],
    "scope": "apex/your-tenant.read apex/your-tenant.query",
})
resp.raise_for_status()
token = resp.json()["access_token"]  # cache; refresh before the 60-minute expiry

Which products accept which credential

Product Machine-to-machine token Tenant API key Notes
Zenith Yes Operator-enabled Tenant in the URL path must match the credential's tenant
Echo Yes Operator-enabled Per-tenant authentication strategy is configurable (token-only, key-only, or either)
Prism Yes Operator-enabled Tenant from request body or inferred from the credential
Vector No Yes (primary) Bearer value is the tenant API key itself, centrally verified; tenant carried as tenant_id query parameter
Document Operations Yes Yes Tenant via X-Tenant-ID header
Forge portal Provisioning only (forge/… scopes) Issued here, used at other products Portal browsing uses operator sign-in sessions
Forge support service No No Separate support-service token issued by your operator (Preview)
Forge LLM gateway Yes (scope llm:invoke) Planned — contract pinned, not yet served
Pulse Preview Preview Bearer required; credential verification is hardening — server-side, trusted callers only
Quantum Preview Preview Authentication hardening in progress; local/preview use only

Handling rules

  1. Server-side only. APEX credentials live in your backend environment (the backend-for-frontend pattern). They must never reach a browser, mobile client, or client-side bundle.
  2. One credential set per environment. Test-class keys against development; production-class keys against production. Never share credentials across environments.
  3. Your users are not APEX principals. End users authenticate with your platform (your identity provider). Their identity terminates at your backend; APEX sees your tenant credential. An audit header for acting-user attribution (X-On-Behalf-Of) is Planned.
  4. Expect 401 vs 403 to mean different things. 401 — credential missing, malformed, or expired (mint a fresh token / check the key). 403 — credential valid but not permitted (tenant mismatch, entitlement, or tenant not configured). Do not retry a 403 unchanged.
  5. Rotate without downtime. Create the replacement key, deploy it, then revoke the old one.