API key
Send it in theX-API-Key header:
smx_ and created in the dashboard. This is the credential for scripts, integrations, and CI.
Keys authenticate the REST API only. The MCP server uses OAuth and refuses API keys with an explicit 401.
JWT
The dashboard authenticates with a Supabase-issued JWT in anAuthorization: Bearer header. It’s short-lived and tied to a browser session, so it isn’t a practical credential for your own integrations.
Endpoints accept either. Where the docs say “authenticated”, both work.
How the organization is resolved
This is the part worth understanding, because the two credentials behave differently. With an API key, the organization is read from the key itself. The key is bound to one organization at creation, and that binding decides what the request can reach. With a JWT, the token identifies a person, who may belong to several organizations — so the credential alone doesn’t answer the question. Passorg_id explicitly in the path wherever the endpoint offers it. Nearly every endpoint is nested under an organization for exactly this reason, and relying on an implicit resolution for a user with several memberships is how lookups end up billed to the wrong organization.
The MCP server makes this explicit rather than implicit: org-scoped tools take an optional
organization argument, and a caller with several memberships who names none gets a refusal listing them, not a guess.What a key can reach
A key carries owner-level access to its organization. It isn’t restricted by the role of whoever created it, and any member can create one. Verification is a bcrypt comparison, so a resolved key is cached briefly rather than re-hashed on every request. A revoked key stops working immediately — revocation writes a tombstone the cache checks, rather than waiting for the entry to expire.Errors
Note the split. Not being a member answers 404, never 403 — a 403 would confirm the organization exists.
FORBIDDEN is reserved for a member whose role is insufficient, and its message names the role required.
A 401 never says why. “Expired”, “malformed”, and “wrong signature” are all information the caller can’t act on differently.
See Roles and permissions for the full role table.