# auth.md: how an agent gets access to the SpecStream API

Every call to `https://api.specstream.ai` carries a credential of one SpecStream account as a Bearer token: an API key, or an OAuth 2.1 access token. An agent acts for a person who has an account; there is no anonymous access and no agent-only account.

## Discover

- Protected resource metadata (RFC 9728): https://api.specstream.ai/.well-known/oauth-protected-resource
- Authorization server metadata (RFC 8414): https://specstream.ai/.well-known/oauth-authorization-server
- The issuer is `https://specstream.ai`. Its metadata has an `agent_auth` block that names this file and the two addresses of Register and Claim below.
- A call with no credential, or a refused one, answers `401` with a `WWW-Authenticate` header that names the metadata address.

## Pick a method

- OAuth 2.1 with PKCE (S256): for a client that signs a person in, such as an MCP client. Use it when the person is present.
- API key: for a server or a script. The person makes the key and gives it to the agent.

The `agent_auth` block names one identity type, `anonymous`: an agent registers its client with no identity of its own (`register_uri`), and gets an `access_token` only after a person approves it (`claim_uri`). Before that approval the agent has no credential and no access. SpecStream takes no `identity_assertion` or `id-jag` token and has no `service_auth` grant.

## Register

An OAuth client registers itself at `https://specstream.ai/oauth/register` (dynamic client registration), or names a client ID metadata document. No registration is needed for an API key.

## Claim

The person signs in at `https://specstream.ai/oauth/authorize` and approves the scopes the client asked for: `specs:read`, `specs:write`, `finds:read`, `finds:write`, `finds:spend`, `projects:read`, `account:read`. A new person signs up at `https://specstream.ai/signup` and starts with $10 of credit, no card.

For an API key, the account owner makes it under Agents & API in the workspace, with its scopes and a spending limit. A key that searches or reads pages needs `finds:spend` and a limit above 0.

## Exchange

The client exchanges the authorization code at `https://specstream.ai/oauth/token` (grant types `authorization_code` and `refresh_token`, code challenge method S256).

## Use the access_token

```bash
curl "https://api.specstream.ai/v1/web-search?q=<the question>" -H "Authorization: Bearer <access_token or API key>"
```

The MCP server at `https://api.specstream.ai/mcp` takes the same Bearer token.

## Errors

- `401`: no credential, or one that is unknown, expired or revoked. Read `WWW-Authenticate` and start again from Discover.
- `403`: the credential lacks the scope the call needs, or its spending limit is 0.
- `503` with `Retry-After`: the account used its calls for the minute, or search is busy. Wait that many seconds and send the call again. Nothing is charged.

## Revocation

An OAuth token is revoked at `https://specstream.ai/oauth/revoke`. The account owner revokes an API key under Agents & API in the workspace.

More: [API docs](https://specstream.ai/docs/api), [guide for agents](https://specstream.ai/agents.md).
