Authorization header, and — for any organization-scoped endpoint — scoped to one organization with the X-Organization-ID header. The two SDKs send exactly these headers for you.
The API does not read a header named
X-Authorization. There is no such header anywhere in the backend or in either SDK. Use Authorization: Bearer (preferred) or the X-API-KEY fallback, both described below.The two headers you send
A minimal authenticated request looks like this:
Authenticated request
https://api.modulex.dev and there is no /v1 path segment — routers are mounted at the root. See Base URLs & versioning for environments and the versioning policy, and the API overview for the full request lifecycle.
API keys
A ModuleX API key is a per-user secret used by SDKs and any programmatic caller. It is distinct from the Clerk session token (JWT) that the web app uses — see Auth model: JWT vs API key for how the two paths differ.Key format
The backend distinguishes credentials by prefix: a token starting with
mx_live_ is treated as an API key; anything else presented as a bearer token is treated as a Clerk JWT.
Create a key
Create keys in the app (Settings → API keys) or via the API. Creating a key requires an authenticated, already-provisioned user — you can present either a Clerk JWT or an existingmx_live_ API key, so one key can create another. Only the very first key needs a JWT-provisioned account to bootstrap from.
string
required
A label for the key. 1–255 characters.
string
Scope the key to a single organization. The caller must be an active member of that organization. When omitted (the default), the key works across all of your organizations and you choose the organization per request with
X-Organization-ID.string
An ISO 8601 timestamp. When omitted (the default), the key never expires.
integer
default:"60"
Per-key request budget, 1–1000.
201) is the only response that includes the full key:
string
UUID of the key record.
string
The label you set.
string
The full
mx_live_… key. Returned only here.string
The first 8 characters of the random part, for display.
string
mx_live_{hint}******** — what list/detail endpoints return.string | null
The org the key is scoped to, or
null for all orgs.string | null
Expiry timestamp, or
null for never.boolean
Whether the key is past its expiry.
boolean
Whether the key is active (not revoked).
integer
The per-key budget.
string | null
When the key was last used, or
null.string
Creation timestamp.
string | null
When the key was revoked, or
null.Key limits
Revoke a key
Revoking is permanent and immediate; the record is kept for audit. A revoked key returns401 on its next use.
Revoke a key
Sending the key
You can present the key two ways. Both are accepted by the backend.- X-API-KEY (fallback)
1
Authorization: Bearer
If present and the token starts with
mx_live_, it is used as an API key. Otherwise it is verified as a Clerk JWT.2
X-API-KEY
Consulted only if no bearer credential resolved, and only if the value starts with
mx_live_.3
Neither
A
401 is returned: Authentication required. Provide Authorization: Bearer token or X-API-KEY header.Organization scope
ModuleX is multi-tenant. Identity (your key) and organization (the tenant you act in) are two separate axes: the key says who you are;X-Organization-ID says which organization the request runs against. Most resources — workflows, runs, knowledge bases, credentials, integrations, the composer, the assistant, and schedules — are organization-scoped and require the header. Identity-only endpoints such as GET /auth/me and GET /auth/invitations/my do not.
Org-scoped request
1
Header present
Missing
X-Organization-ID on an org-scoped route returns 400: X-Organization-ID header is required.2
Key scope matches
If the key is scoped to a specific organization (you set
organization_id when creating it), the header must name that same organization, or you get 403: API key is scoped to a different organization.3
Membership
You must be a member of the named organization, or you get
403: User is not a member of organization {id}.4
Role
Some surfaces require a privileged role (see below).
GET /auth/me/organizations. The header value is the organization’s id. For the full org-context model see Org context & X-Organization-ID and the concept page on organizations, roles & membership.
A few request bodies also carry an
organization_id field (for example, when creating an org-scoped API key). That field sets which organization owns the new resource. It is independent of the X-Organization-ID header, which sets which organization you are acting in. Do not conflate the two.Roles
The live organization roles areowner and admin. The member role is retired and is not a current role — document and design against owner/admin only. A handful of surfaces require owner or admin rather than plain membership: the composer, the assistant, and the organization-settings and member-management endpoints. A membership-only call to one of these returns 403. See Roles & permissions for the per-endpoint matrix.
Authenticating with the SDKs
Both official SDKs sendAuthorization: Bearer <key> and add X-Organization-ID whenever an organization is resolved. The default base URL is https://api.modulex.dev; pass baseUrl / base_url to target another environment.
Error responses
Authentication and organization-scope failures use the standard FastAPI envelope,{"detail": "<message>"}.
401 example
Rate-limit responses
When you exceed a key’s per-minute budget or the across-keys per-user budget, the per-key limiter returns429 with a string detail and rate-limit headers:
429 (per-key / per-user limiter)
The organization-level
api-class limiter can also return 429, but with a dict-valued detail:
429 (org api-class limiter)
429 shape — the flat billing-gate DenialEnvelope — appears only on run and managed-usage surfaces (workflow runs, composer, assistant, managed knowledge), never on a CRUD or settings route. The same surfaces can also return 402 and 403 billing denials. See Usage gating & limits for the gate, Rate limiting for all three 429 shapes, and Errors & status codes for the complete envelope reference.
Security notes
- Treat the key like a password. Send it only over HTTPS; never embed it in client-side code, a public repository, or a URL query string.
- Use
X-API-KEYonly if you cannot setAuthorization—Authorization: Beareris the supported path. - Scope keys to one organization and set a tight
rate_limit_per_minutefor automation, so a leaked key has limited blast radius. - Rotate by creating a new key, switching traffic, then revoking the old one. Revocation is immediate.
- The Clerk JWT used by the web app and the
mx_live_API key used by code are different credentials with different lifecycles. See Auth model: JWT vs API key for which path to use where.
Next steps
Quickstart
Get a key and make your first authenticated call.
Org context & X-Organization-ID
How organization scope is resolved and enforced.
Errors & status codes
Every error envelope and what produces it.
Glossary
Canonical terms: API key, Clerk JWT, organization, role.