401unauthorized
No usable credential
The request carried no credential the API accepts: none at all, a malformed one, or one that is unknown, revoked or expired.
Every operation except GET /status needs a credential in the Authorization header, as Authorization: Bearer <credential>. The credential is either an API key (it starts cmn_sk_) or an OAuth access token (it starts cmn_at_). This error means the API could not turn what you sent into a working credential.
Every reason answers identically, down to the wording. A key that was revoked, one that expired and one that never existed produce the same response, so that a leaked string cannot be tested for whether it was once real. The response cannot tell you which case you are in; the causes below tell you how to find out.
The response carries a WWW-Authenticate header whose resource_metadata parameter points at the API's OAuth protected resource metadata. An MCP client or any OAuth client uses it to discover where to authorise. A client holding an API key can ignore it.
Why it happens, and how to fix it
No Authorization header, or the wrong scheme
The header is missing, or the credential was sent some other way: as
Token <key>,Basic ...,X-Api-Key, a query parameter, or a bare key with noBearerin front. There is no fallback to any of these. A request made from a browser page with a Commune session cookie is not authenticated either; the API ignores cookies.Fix: Send exactlyAuthorization: Bearer cmn_sk_...(orcmn_at_...for an OAuth token). Check that a proxy or HTTP library is not stripping theAuthorizationheader, which some do on redirects.A malformed or truncated credential
A credential is its prefix followed by 32 letters and digits. It fails when it was cut short on copy, carries surrounding quotes or a line break from an environment file, or was taken from the key's display prefix on the keys page (which is not the secret).
Fix: Print the length of what you send: an API key is 39 characters. The full secret is shown once, when the key is minted. If you no longer have it, mint a new key on Settings, API keys and store the secret as shown.The API key was revoked or has expired
Keys are turned off by their owner on the keys page, by a newsletter owner or admin cutting a key off from their newsletter's API access page, or by a
DELETE /api-keys/{key}call (which an integration may make on itself). A key also stops working at the expiry date chosen when it was minted.Fix: Open Settings, API keys as the key's owner and check its state. A revoked or expired key cannot be brought back: mint a new one, and choose an expiry you will notice.The OAuth access token has expired
An access token lives one hour. After that every request with it answers
401, while the refresh token issued with it keeps working for 90 days.Fix: Exchange the refresh token at the authorisation server's token endpoint (grant_type=refresh_token) for a new access token, then retry. Refresh proactively usingexpires_inrather than waiting for the401. The flow is in Build an app every creator can connect.The OAuth grant was revoked, or the token was issued for another resource
When the creator disconnects your app, every token under that grant stops working on the next request, refresh tokens included. A token also fails when the authorisation that produced it named a different
resourcethan this API, or the client registration was disabled.Fix: If refreshing also fails, send the creator through authorisation again, withresourceset to the API's origin,https://api.usecommune.com. An MCP client does this by itself when it followsresource_metadata; see Connect an assistant.
Retrying
No: the same credential fails the same way, so fix the header, refresh the token or use a new key first.
Headers
WWW-AuthenticateBearer realm="Commune API", resource_metadata="https://api.usecommune.com/.well-known/oauth-protected-resource". The metadata URL is where an OAuth or MCP client starts discovery.
Example response
{
"error": {
"code": "unauthorized",
"message": "No usable credential. Send an API key or an OAuth access token as `Authorization: Bearer <credential>`. A credential that has been revoked or has expired reports the same way as one that was never issued.",
"request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
"docs_url": "https://usecommune.dev/errors/unauthorized"
}
}Often confused with forbidden, insufficient_scope.