Skip to main content
Every operation needs a credential, sent as a bearer token:
Three kinds of credential exist. They do not all open the same doors. The app session is what the Doers app itself uses. For your own scripts and agents, use a personal token (anything) or OAuth (an MCP client that supports it).

Personal API tokens

  • Create one in Settings > API & MCP, or with POST /v2/tokens. The value is shown once. The server keeps only its SHA-256 hash, so a lost token cannot be shown again: create another.
  • One per integration. Name each after what uses it, so you can revoke one without breaking the others. Settings > API & MCP shows when each was last used.
  • Revoke it from the same page. The next request with it gets 401.
  • No scope, no expiry. A token can call every operation your account can, including creating more tokens and revoking connected applications. Treat it as a password.

OAuth, for MCP clients

An MCP client that supports OAuth 2.1 signs you in through your browser instead of asking for a token. Doers is its own authorization server:
  • discovery through /.well-known/oauth-protected-resource (RFC 9728) and /.well-known/oauth-authorization-server (RFC 8414);
  • dynamic client registration at POST /oauth/register (RFC 7591), so there is nothing to set up beforehand;
  • the authorization code flow with PKCE S256, mandatory; public clients only;
  • one scope, mcp;
  • an access token valid for one hour and a refresh token valid for 60 days, rotated on every use. Presenting a refresh token that was already used revokes the whole connection: the client has to sign in again.
The consent screen is a page of the Doers app, so you approve with the session you already have. Approved applications are listed in Settings > API & MCP > Connected apps, with a button to disconnect each one, effective immediately.
OAuth access tokens are accepted by the MCP server only. Sent to a REST route, a pcat_ token is refused with 401. For REST, use a personal token.
An OAuth token is bound to the MCP server it was issued for. The authorization server issues tokens for https://app.doers.sh/mcp, so an OAuth client must be configured with that address: see Connecting a client.
Like a personal token, an OAuth connection carries no scope beyond mcp: it reaches every MCP tool your account can use.

When authentication fails

On REST, a missing, unknown, expired or revoked credential gets the same answer, so a caller cannot tell a revoked token from one that never existed:
The MCP server answers 401 with a challenge that tells an OAuth client where to start:
When a credential was sent but refused, the challenge also carries error="invalid_token". See MCP troubleshooting. Failed authentications are counted per address: after 30 in a minute, the next attempts get 429 with Retry-After.

From a browser

The REST API answers cross-origin requests only from the origins it is configured to trust, and never with Access-Control-Allow-Origin: *. A web page on another origin cannot call it. Call it from your server instead, where the token stays secret. The MCP server accepts a request with an Origin header only from a fixed list of known clients (claude.ai, claude.com, chatgpt.com, chat.openai.com, platform.openai.com, doers.sh and the loopback address). Native clients send no Origin and are not affected.