# Speko authentication

This walkthrough is the machine-readable authentication and authorization guide for Speko Router, the Agents API, and MCP clients. Its canonical URL is https://speko.ai/auth.md and it was last updated on 2026-08-24.

## Pick a method

- **Public discovery:** `GET /openapi.json`, `GET /.well-known/ai-catalog.json`, and the Speko Docs MCP at `POST /.well-known/mcp` require no authentication.
- **Hosted Router:** send `Authorization: Bearer $SPEKO_API_KEY` to `https://router.speko.dev`. Create a key in the self-serve console at `https://platform.speko.ai/api-keys`.
- **Hosted Agents API:** send the same Bearer API-key shape to `https://api.speko.dev`.
- **Operational MCP:** `https://mcp.speko.ai/mcp` accepts OAuth 2.0 or a Bearer API key. It is separate from the public docs MCP.

Never put an API key in a URL, query string, repository, browser bundle, ticket, or log. Treat it as an organization credential and rotate it from the console if it is exposed.

## Discover OAuth metadata

The operational MCP resource publishes RFC 9728 metadata at:

- Protected resource metadata: `https://mcp.speko.ai/.well-known/oauth-protected-resource/mcp`
- Authorization server issuer: `https://platform.speko.ai/api/auth`
- Authorization server metadata: `https://platform.speko.ai/api/auth/.well-known/oauth-authorization-server`
- Authorization endpoint: `https://platform.speko.ai/api/auth/oauth2/authorize`
- Token endpoint: `https://platform.speko.ai/api/auth/oauth2/token`
- Dynamic client registration: `https://platform.speko.ai/api/auth/oauth2/register`
- Token revocation: `https://platform.speko.ai/api/auth/oauth2/revoke`

Supported grants include authorization code with PKCE, client credentials, and refresh token. Published OAuth scopes are `openid`, `profile`, `email`, and `offline_access`; the protected-resource document narrows the scopes relevant to the MCP resource. Follow the endpoints returned by discovery metadata instead of constructing them from these examples.

## Register an OAuth client

Read the `registration_endpoint` from authorization-server metadata and POST an OAuth dynamic-client-registration document to it. For an interactive public client, register its exact redirect URI, request `authorization_code` and `refresh_token`, and use token endpoint authentication method `none`. Confidential automation may instead use `client_credentials` with the client authentication method returned at registration. Store every returned client secret outside source control.

## Claim authorization

Interactive clients open the published `authorization_endpoint` with `response_type=code`, their registered `client_id` and `redirect_uri`, the required scopes, a random `state`, and PKCE `code_challenge_method=S256`. After the user approves access, verify `state` and exchange the returned code plus the original PKCE verifier at the published `token_endpoint`. Never put an access token in the browser URL.

## Use the credential

Send the resulting OAuth access token or Speko API key in the HTTP header `Authorization: Bearer <credential>`. For MCP, configure the exact resource URL `https://mcp.speko.ai/mcp` and allow the client to negotiate the protocol. For Router and the Agents API, follow the operation and security scheme in their linked OpenAPI documents.

## Handle errors

A protected HTTP endpoint returns a non-2xx status and a structured JSON error. A protected MCP endpoint returns a JSON-RPC authentication error and may advertise its RFC 9728 resource metadata in `WWW-Authenticate`. Do not retry a 401 in a loop: obtain or refresh a credential, then retry once. Honor `Retry-After` on 429 responses and use exponential backoff.

## Revoke or rotate credentials

Revoke an OAuth access or refresh token at the published `revocation_endpoint`, currently `https://platform.speko.ai/api/auth/oauth2/revoke`, using the client authentication method in authorization-server metadata. Rotate a Speko API key from `https://platform.speko.ai/api-keys`: create a replacement, update the consumer, verify it, and then revoke the exposed or retired key.
