# Authenticating with Pascal

You are an agent that wants to read or change Pascal projects. Pascal accepts three credentials. Pick the one that matches who you act for, and never fall back from a credential that failed to a different identity.

## Discover

Call the resource you want. Without a valid credential, https://editor.pascal.app/api/mcp and the Scene API answer `401` with:

```http
WWW-Authenticate: Bearer realm="Pascal", resource_metadata="https://editor.pascal.app/.well-known/oauth-protected-resource", scope="offline_access scene:read scene:write"
```

Fetch the protected resource metadata (RFC 9728) named there. Its `authorization_servers` entry is `https://editor.pascal.app/api/auth`; that server's metadata (RFC 8414) is at https://editor.pascal.app/.well-known/oauth-authorization-server/api/auth, with the OpenID configuration at https://editor.pascal.app/api/auth/.well-known/openid-configuration.

## Pick a method

1. **Browser OAuth** — for Claude (web, Desktop and Claude Code) and Pascal's official Cursor connector, acting for the signed-in person in the workspace they approve.
2. **API key** — for any other client acting for a person: the person creates the key in Settings (https://editor.pascal.app/settings) and gives it to you.
3. **Agent account** — only when the task explicitly calls for separate private work: you register your own account and key, and a person may claim it later.

Pascal does not implement the WorkOS agent_auth profile: there is no identity_endpoint, and identity_assertion (ID-JAG) and service_auth registrations are not accepted. Use one of the three methods above.

## Register

OAuth clients are registered by Pascal: Claude identifies itself with its published client ID metadata document (CIMD) and Cursor with its pinned client. Dynamic client registration is off, so an unknown client_id is refused.

To create an agent account, `POST https://editor.pascal.app/api/auth/agent/register` with JSON `{ "name": "...", "purpose": "...", "agentClient": "claude-code" }` (`purpose` and `agentClient` are optional). The response carries `agentId`, `apiKey`, `starterProjectId` and the MCP, Scene API and OpenAPI URLs. The key is shown once. Registration is limited to 10 per address per hour. An unclaimed agent account is sandboxed to its own private projects and public reads, and cannot spend credits.

## Claim

A person can take responsibility for an agent account. `POST https://editor.pascal.app/api/auth/agent/claim/start` with `Authorization: Bearer <the agent's key>` returns a `claimCode` and a `claimUrl` that expire in 15 minutes. Give the person the URL; they open it signed in to Pascal and confirm. Poll `GET https://editor.pascal.app/api/auth/agent/status` with the same key until `claimed` is true. Claiming does not transfer project ownership or grant access to the person's private projects.

## Exchange

OAuth uses the authorization code grant with PKCE (S256 only) at `https://editor.pascal.app/api/auth/oauth2/authorize`, then `POST https://editor.pascal.app/api/auth/oauth2/token` with the code, your `code_verifier` and `resource=https://editor.pascal.app/api/mcp`. Access tokens last 600 seconds and are bound to that resource (RFC 8707); request `offline_access` for a refresh token, which rotates on every use. The authorization response carries `iss` (RFC 9207); check it. API keys need no exchange.

## Use the access_token

Send `Authorization: Bearer <token or API key>` to https://editor.pascal.app/api/mcp or the Scene API. OAuth scopes are `scene:read` for read-only tools and `scene:write` for tools that change a project. An API key carries its owner's access. Read the pascal://agent-guide MCP resource before your first edit.

## Errors

- `401` with `error="invalid_token"`: the credential is expired, revoked or unknown. Reconnect or ask for a new key; do not retry the same credential.
- `403` with `error="insufficient_scope"`: the connection lacks the scope named in `WWW-Authenticate`. Ask the person to reconnect and approve it.
- `429`: wait the `Retry-After` seconds. `RateLimit` and `RateLimit-Policy` report the budget on every response.
- Every error body is JSON with a machine-readable code and a message. See https://editor.pascal.app/docs/developers/errors.

## Revocation

Revoke an OAuth token with `POST https://editor.pascal.app/api/auth/oauth2/revoke` (RFC 7009, form-encoded `token` and `token_type_hint`). Replaying a spent refresh token revokes the whole grant. People revoke API keys and connected apps in Settings, and the next request with that credential gets `401`. A revoked agent account loses access at once.
