Skip to main content

Auth And Header Matrix

AxonFlow exposes several API surfaces, and they do not all authenticate the same way. This page is the reference for which credential or header model belongs to which surface.

That matters because many integration failures are not business-logic bugs. They are simply the wrong auth model applied to the wrong endpoint family.

Identity Primer (read this first)

AxonFlow uses three distinct identifiers. They appear in similar places and used to be conflated pre-v9. Keeping them straight removes most of the confusion around auth, headers, and audit rows.

IdentifierWhat it isWhere you see it
org_idThe customer organization that owns the data. This is the tenant-isolation boundary that Row-Level Security enforces under the v8.0.0 default of AXONFLOW_DB_USE_APP_ROLE=true.DB rows, Basic-auth-derived request context, the X-Org-ID header when forwarded by the SDK
client_idThe API credential / app identity that authenticated this request. One org can have many clients (prod, staging, per-service).Basic Auth username, the X-Client-ID header (introduced in PR #2233, Phase 4), audit-log credential column
deployment license identityThe AxonFlow installation that booted this agent. Validated against the license at startup. Not written to customer rows.License payload (V3 deployment_id field, shipped 2026-05-19 in PR #2257; V2 org_id field still accepted) + the ORG_ID env var on the agent

A few practical examples:

  • In-VPC Enterprise: org_id = acme-corp (the customer), client_id = acme-prod-api (their production app credential), deployment identity = whatever the operator set at deployment time (commonly the same as org_id).
  • Community SaaS: org_id = cs_abc123 and client_id = cs_abc123 — one credential per customer is the common case, so they share the same value. Deployment identity = axonflow-community-saas (AxonFlow's installation).
  • Self-hosted Community: org_id = local-dev-org (the default; never changes unless you set ORG_ID), client_id = your Basic Auth username, no license.

Why "tenant" terminology is being phased out: pre-v8 docs used tenant_id for both customer org and API credential because the codebase didn't separate them. v8.0.0 makes the distinction explicit. The on-wire tenant_id field in JSON responses and the X-Tenant-ID header still work — they're accepted as deprecated aliases for client_id through v8 and planned for removal in a future v10 cut. The full design lives in the v7 → v8 Migration Guide.

Quick Matrix

SurfacePrimary auth modelImportant headers or fieldsNotes
Agent request path (/api/request)SDK client credentials or direct request fieldsclient_id, user_token, optional Basic auth in SDK-driven flowsmost application traffic starts here
Gateway and proxy SDK flowsBasic auth with clientId:clientSecretAuthorization: Basic ...client secret is optional in community mode, required in enterprise-style deployments
Community SaaS plugin / SDK requestsBasic auth + optional X-License-TokenAuthorization: Basic ..., X-License-Token: AXON-..., X-Axonflow-Client: <id>/<v>per-credential tier resolution + scope check; see License Matrix Headers below
Orchestrator protected workflow APIsBasic auth (org_id + client_id derived from credentials)Authorization: Basic ..., X-Org-ID, X-Client-ID (forwarded)identity derived server-side; X-Tenant-ID accepted as deprecated alias
MCP standalone policy checkssame application auth context as the calling runtimerequest body plus normal client contextused when external orchestrators want policy-only checks
Customer portal APIssession authaxonflow_session cookieused for most protected portal workflows
SCIM provisioningbearer tokenAuthorization: Bearer ...separate from portal session auth
Admin organization APIsadmin API keyX-Admin-API-Keyrequired in SaaS production, optional in some other deployments

Public Runtime Patterns

SDK and application traffic

The public SDK guidance is centered on client credentials:

  • AXONFLOW_CLIENT_ID
  • AXONFLOW_CLIENT_SECRET

The SDKs use Basic auth with:

Authorization: Basic base64(clientId:clientSecret)

At the request level, the runtime also uses fields such as:

  • client_id
  • user_token

This is why the public docs often talk about both SDK credentials and request identity fields. They are related, but not identical.

License Matrix Headers (X-License-Token + X-Axonflow-Client)

On Community SaaS endpoints (try.getaxonflow.com and self-hosted community-saas overlays), every governed plugin or SDK request can carry two additional headers that drive per-tenant tier resolution and scope validation per ADR-050:

X-Axonflow-Client: <client-id>/<version>

Identifies which plugin or SDK is making the request. Set on every governed request automatically by the AxonFlow plugins (Claude Code, Cursor, Codex, OpenClaw) and SDKs (TypeScript, Python, Go, Java) — you don't set it manually.

Examples that the agent recognises:

Header valueMaps to scope
openclaw/2.1.0plugin
claude-code-plugin/1.1.0plugin
cursor-plugin/1.1.0plugin
codex-plugin/1.1.0plugin
sdk-typescript/7.8.0sdk
sdk-python/7.8.0sdk
sdk-go/7.8.0sdk
sdk-java/7.8.0sdk
(header absent)full (default)

The agent uses the derived scope to validate that any presented X-License-Token is authorised for that scope — a token issued for the SaaS Plugin path can't be used as SaaS SDK auth, and vice versa.

The agent also captures the value into the Community SaaS telemetry table under the client column so operators can see per-plugin / per-SDK request distribution.

X-License-Token: AXON-<base64url-payload>.<base64url-signature>

A Pro-tier license token issued by Stripe Checkout. Optional — absent means Free-tier baseline (3-day audit retention, 200 events/day). When present, the agent validates the signature, the aud claim against the SaaS Plugin path's accept list, the scope against X-Axonflow-Client via HasScope(), and the tenant binding against the Basic-auth-derived tenant.

Validation outcomes:

  • Valid token + matching plugin_user_licenses row → Pro tier (30-day retention, 1000 events/day) for the duration of the token (90 days from purchase).
  • Token signature invalid → 401 with invalid_license_token reason.
  • Token aud not in SaaS Plugin path accept list (e.g. a self-hosted token sent here) → 401 with cross_quadrant_token reason.
  • Token aud accepted but scope mismatch (e.g. plugin-aud token + SDK client header) → 401 with scope_mismatch reason.
  • Token tenant_id mismatches Basic-auth-derived client_id → 403 with tenant_mismatch reason. (The tenant_id claim on the token is the legacy field name; in v9 terminology it carries the client_id. The wire field is unchanged; only the conceptual mapping changes.)
  • DB-level revocation (chargeback, dispute) → 401 within ~60 seconds (no caching).

For the full license matrix concept including all six canonical aud values, see License Matrix.

Orchestrator headers

Orchestrator surfaces use identity headers derived from Basic auth credentials. After v9, the canonical headers are:

  • X-Org-ID — the customer organization (RLS-enforced boundary).
  • X-Client-ID — the authenticated API credential / app identity.
  • X-User-ID — the human user, when applicable.

Compatibility through v9:

  • X-Tenant-ID is accepted as a deprecated alias for X-Client-ID. The agent and orchestrator both honour it on inbound requests; the agent's outbound proxy emits both X-Client-ID and X-Tenant-ID until v10 removes the alias.
  • Inbound X-Org-ID headers are overwritten by auth-derived values to prevent client-side spoofing — only the values resolved by the auth middleware reach orchestrator handlers and audit writes.

See the Identity Primer above for the meaning of each identifier and how they differ from the license deployment identity.

Protected Portal Patterns

Session-backed portal APIs

The customer portal uses login and session flows under /api/v1/auth/..., and successful login establishes the axonflow_session cookie. That cookie-backed session is then used for:

  • usage and analytics
  • API keys
  • connectors and providers
  • approvals
  • exports
  • SSO settings

SCIM

SCIM is its own auth model. The portal manages SCIM tokens, but actual provisioning requests use bearer-token auth against /scim/v2/....

Admin APIs

The admin organization surface uses:

  • header: X-Admin-API-Key
  • env var on the service side: ADMIN_API_KEY

In the current middleware, SaaS production requires it. Other deployment modes are looser, but that should be treated as an operational choice, not as a reason to blur the auth model in client code.

Practical Advice

When an AxonFlow call fails, identify the endpoint family before changing credentials. A good debugging sequence is:

  1. Is this a public runtime call, a portal call, a SCIM call, or an admin call?
  2. Does this surface expect Basic auth, bearer token, session cookie, or admin key?
  3. Does the request also need tenant or org routing headers?

That sequence is faster than guessing between Authorization, tenant derived from Basic auth, and portal cookies after the fact.

Operational Readiness Checklist

Before relying on this page in a production rollout, pair it with the core operations docs: