# Agent authentication on outserp.ai

Not an agent? You are probably looking for the [API documentation](https://outserp.ai/api-docs) or the [MCP setup guide](https://outserp.ai/docs/mcp).

You are an agent. This document tells you how to get a credential for **Outserp** and use it against the REST API (`https://outserp.ai/api/v1`) and the MCP server (`https://mcp.outserp.ai/mcp`). Both accept the same bearer credentials. Follow the steps in order.

## Discover

- **Protected-resource metadata (RFC 9728):** `GET https://outserp.ai/.well-known/oauth-protected-resource` — names the MCP resource, the authorization server and the supported scopes (read, write, generate, publish).
- **Authorization-server metadata (RFC 8414):** `GET https://outserp.ai/.well-known/oauth-authorization-server` — `authorization_endpoint`, `token_endpoint`, `registration_endpoint` (dynamic client registration), PKCE `S256`, and an `agent_auth` block that links back to this file.
- **OpenAPI 3.1:** `GET https://outserp.ai/openapi.json` — every REST operation with its required scope under `security`.
- **API catalog (RFC 9727):** `GET https://outserp.ai/.well-known/api-catalog`.
- **MCP server card:** `GET https://outserp.ai/.well-known/mcp/server-card.json` — tool list, annotations, and which JSON-RPC methods are public.
- An unauthenticated request to `https://outserp.ai/api/v1/*` or a `tools/call` on the MCP server answers `401` with `WWW-Authenticate: Bearer resource_metadata="https://outserp.ai/.well-known/oauth-protected-resource"`. That header is the signal to come here.

## Pick a method

| Context | Method | Credential prefix | When to use |
| --- | --- | --- | --- |
| Long-running agent or script acting for one Outserp account | **API key** | `osk_live_` | Default. Scoped (read / write / generate / publish), rate-limited per key. |
| Coding agent connected to the MCP server (Claude Code, Cursor, Windsurf) | **Personal access token** | `osk_pat_` | Same header as an API key, minted from the same settings page. |
| Multi-user agent platform acting on behalf of an end user | **OAuth 2.0 authorization code + PKCE** | Bearer access token | The MCP server advertises this flow via the RFC 9728 / 8414 metadata above. Public clients, `S256`, dynamic client registration supported. |

There is no anonymous tier: every read and write requires a credential tied to an Outserp account.

## Register

Outserp does not implement agentic self-registration (no `identity_endpoint`, no ID-JAG exchange). A human creates the account once:

1. Sign up at https://outserp.ai/signup (7-day free trial, no card required). The REST API is available on Growth plans and above; the MCP server on Scale and Enterprise.
2. Open **Settings → API access** at https://outserp.ai/agent-settings and create an **API key** (choose scopes) or a **personal access token** (for MCP clients).
3. Store the credential in your agent's secret store. Keys are shown once.

OAuth clients register dynamically: `POST` the `registration_endpoint` from the AS metadata with `redirect_uris`, `client_name` and `token_endpoint_auth_method: "none"`.

## Claim

Not applicable — there is no device-code claim ceremony. A key issued in the dashboard is immediately valid. For OAuth, the end user approves the consent screen at `https://outserp.ai/oauth/authorize`; the agent then exchanges the code below.

## Exchange

- **API key / PAT:** nothing to exchange. Use it directly.
- **OAuth:** `POST https://outserp.ai/api/oauth/token` with `grant_type=authorization_code`, `code`, `code_verifier`, `client_id`, `redirect_uri`. Refresh with `grant_type=refresh_token`.

## Use

REST:

```http
GET https://outserp.ai/api/v1/projects
Authorization: Bearer osk_live_…
Accept: application/json
```

MCP (Streamable HTTP):

```http
POST https://mcp.outserp.ai/mcp
Authorization: Bearer osk_pat_…
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}
```

`initialize`, `ping`, `tools/list`, `resources/list` and `resources/read` need no credential; `tools/call` does. Call `whoami` first: it returns the plan, usage against limits, credit balance and projects, and a sign-up link when the account has no active plan.

Scopes: `read` covers every list/get endpoint; `write` adds create/update; `generate` adds article and keyword generation; `publish` adds publishing to a connected CMS. A missing scope returns `403` with `required_scope` in the body.

Rate limits: each key has a per-minute and per-day budget, exposed as `X-RateLimit-Remaining-Minute` and `X-RateLimit-Remaining-Day` on every response. A `429` means back off until the next window.

Errors: JSON only, shape `{ "error": { "message": string, "status": number, ...details } }`. Never HTML.

## Handle revoke

- Keys and tokens are revoked from the same settings page (https://outserp.ai/agent-settings). A revoked credential returns `401` with the same `WWW-Authenticate` challenge as an unauthenticated request — treat that as "obtain a new credential", not as a transient error.
- OAuth refresh tokens are invalidated when the user disconnects the client; re-run the authorization code flow.
- No revocation event webhook is published today. Poll behaviour: on `401`, stop, surface the sign-in link to the user, and do not retry with the same credential.

## Contact

Questions about access, volume, or a partner key: support@outserp.ai.
