Authentication
Authenticate every HTTP and MCP call with a bearer token, and identify the caller.
Every call to the HTTP API (/api/v1) and to the MCP endpoint (/mcp) carries a
bearer token in the Authorization header. The token identifies you — the
operator — and the space roles you hold decide what each call may do.
Replace https://cadence.example.com in the examples below with the address of
your own Cadence instance.
Bearer tokens
Send your token on every request:
Authorization: Bearer smc_your_token_hereTwo kinds of token resolve to your operator account:
| Prefix | Token kind | How you get it |
|---|---|---|
smc_ | An API token you mint for yourself | API tokens in your account settings |
mcoa_ | An OAuth access token issued to a connected client | The OAuth flow |
Both resolve to the same user. An mcoa_ token also stops working the moment its
grant is revoked, even before it would otherwise expire.
The same header and the same two token kinds work for both /api/v1 and /mcp.
What your role decides
Your access is set per space by a role, in a strict ladder: viewer, then member, then admin. Each action needs one of three levels:
- read — a viewer, member, or admin may call it.
- write — a member or admin may call it.
- admin — only an admin may call it.
A separate instance-admin flag exists for whoever runs the Cadence instance itself. It grants no access to any space: reaching a space's tasks, workflows, or settings always requires a role in that space.
Each reference page states the level a call needs where it is not read.
When a token is missing or wrong
A request with no token, or a token that does not resolve, is refused with
401. The response names the reason — missing_token when the header is absent
or empty, invalid_token when it does not resolve — and carries a
WWW-Authenticate header pointing at the OAuth discovery document:
WWW-Authenticate: Bearer resource_metadata="https://cadence.example.com/.well-known/oauth-protected-resource"On /api/v1 the body is:
{ "error": { "code": "invalid_token", "message": "Authentication required" } }On /mcp the same refusal comes back as a JSON-RPC error with code -32001 and
message Authentication required.
API tokens
Create an smc_ API token in the web interface at /settings/api_tokens/new.
Creating a token shows the full smc_… value once, at creation — it is not
shown again, so copy it then. Your account page at /settings/account lists your
tokens and revokes any of them.
Any signed-in user manages their own tokens; no admin role is needed to hold one.
Connected applications
To review the OAuth clients you have authorised — the applications holding
mcoa_ tokens on your behalf — open /settings/account/connected_applications.
Disconnecting a client there revokes its grant, and every access and refresh
token on that grant stops working at once.
Identify the caller
whoami
GET /api/v1/whoami returns your user:
{ "user": { "id": 4021, "email": "you@example.com" } }Over MCP, the whoami tool returns your identity and the spaces you belong to,
each with the role you hold there:
{
"principal": { "type": "user", "id": 4021, "email": "you@example.com", "name": "Your Name" },
"memberships": [
{ "space_key": "OPS", "role": "admin" },
{ "space_key": "SUP", "role": "member" }
]
}Called under a lease token — by a worker reading its own identity — whoami
returns the lease's scope instead: the space it runs in, and the workflow and task it
is pinned to. scope.workflow and scope.task appear only for the subject the lease
answers for, so a worker can tell what its lease is scoped to:
{
"principal": { "type": "lease", "id": 88213 },
"scope": {
"space": { "key": "OPS" },
"workflow": { "slug": "delivery" },
"task": { "key": "OPS-42" }
}
}A task-subject lease carries all three. A workflow-subject lease omits task; a
space-subject lease omits both workflow and task, carrying only the space. (On
a lease that answers for a workflow or a whole space — see
Leases — there is no single task to name.)
users_resolve
The MCP users_resolve tool turns a name or email into a user reference you can
use when assigning a task or adding a participant. Pass a query:
{ "status": "matched", "user_id": 4088, "ref": "user:4088", "matched_field": "email" }{ "status": "not_found" }{ "status": "ambiguous" }when more than one operator matches.
It only resolves operators who share a space with you, and never returns another person's name or email — only the reference.
operators_update_self
The MCP operators_update_self tool edits your own operator profile. Pass any of
first_name, last_name, language, timezone, bio — at least one. A field
you omit is left unchanged; a field set to null is cleared. It returns your
updated profile. This tool acts only on your own account.