Skip to content
Charming Docs
Esc
navigateopen⌘Jpreview
On this page

Authentication

Agent reference for token scopes, pairing, claims, recovery, and revocation.

Charming’s HTTP API uses Bearer tokens. An MCP client with a browser should complete OAuth when it connects, which is the smoothest path and needs no token handling. A client without one can send a chrm_user_* token as its Bearer to an MCP surface instead, which is what pairing exists for. For HTTP request and response schemas, use the REST API reference.

Choose a credential

Use the smallest scope that fits the task.

Token Scope Use
chrm_app_* One app Returned when an agent creates an anonymous app. It can read, update, and run that app.
chrm_user_* One account Used by agents that need the user’s apps, sharing, secrets, or account settings. Works on the HTTP API and on the MCP surfaces.
chrm_render_* One app at runtime Minted by Charming for window.charming. Agents do not mint or manage it.

See Pricing and limits for token lifetimes.

Discovery

Do not hardcode auth metadata. Use these machine-readable sources:

  • OpenAPI contract for routes, schemas, security rules, and errors.
  • OAuth authorization server for sign-in and pairing endpoints. Its agent_auth.anonymous.credential_types_supported value is ["api_key"], because pairing returns a personal access token after approval.
  • OAuth protected resource for the API’s authorization server.
  • Path-scoped protected-resource metadata for one MCP surface, at /.well-known/oauth-protected-resource followed by the surface path — /mcp, /mcp/chatgpt, /mcp/inline. Each surface names its own document in the WWW-Authenticate header it returns on a 401, and the document’s resource is that surface rather than the origin.
  • Read authorization_servers from the surface document rather than assuming the origin. A surface may name itself, in which case its authorization-server metadata lives at the RFC 8414 path-inserted URL for that issuer — for /mcp/chatgpt that is /.well-known/oauth-authorization-server/mcp/chatgpt. That document may carry a different authorization_endpoint from the origin-wide one, on a host reachable to readers who cannot resolve this one. Everything else, including the token endpoint, stays on this origin. A client that hard-codes the root authorization-server document still works; it just signs in on this host.

Anonymous app token

Create an app without an Authorization header to receive a chrm_app_* token. Keep it secret. It works only for the returned app and cannot list other apps.

An anonymous app expires unless a user claims it. Claiming the app revokes its chrm_app_* token. If an agent later uses that token, the 401 response includes a recovery block. Follow that block instead of creating a replacement app.

User token

A signed-in user can mint a chrm_user_* token with Create token. Charming returns the plaintext once. Use List tokens to inspect active tokens and Revoke token to revoke one.

An agent without a browser session should pair:

  1. Call Start pairing.
  2. Show the returned user_code and verification_url to the user.
  3. Poll with Poll pairing at the returned interval.
  4. Store the chrm_user_* token returned after approval. Charming returns it once.

Send that token as the Bearer on either transport: the HTTP API, or an MCP surface such as /mcp.

The device_code is private to the agent. The user_code is safe to show to the user.

Claim an anonymous app

There are two supported flows:

  • Set pair: true when you create an anonymous app. Approval pairs the agent and claims the app in one flow.
  • If you already have a chrm_user_* token, call Claim app with the app’s chrm_app_* token as proof.

Both flows revoke the app token after claim. Use the user token for later work.

Send a token

HTTP agents send Authorization: Bearer <token>. Do not put a user or app token in a URL. Follow build-http.md for request examples.

Rendered apps use window.charming.api() instead of managing credentials. Charming attaches the render token.

Recover from auth errors

  • 401 means the request has no valid credential. Follow error.recovery when present.
  • 403 means the credential is valid but lacks access to the app or action. Do not retry with the same scope.
  • token_revoked_post_claim means an app was claimed. Pair for a user token, then retry.
  • token_expired includes the next auth step in error.recovery.
  • sign_in_required (401) means a claimed app refused a gated call from a caller it cannot name. Inside a rendered app, window.charming.withUser(action) signs the visitor in and re-runs the action; an HTTP agent sends a user token instead. Signing in fixes this one, unlike unauthorized.

The OpenAPI contract defines every error field and reason.

Revoke access

Users can review and revoke agent tokens from the account menu: choose Account settings, then Connections. HTTP agents can use List tokens and Revoke token.

Claiming an anonymous app revokes its app token. Render tokens rotate when Charming renders the app again.

Was this page helpful?