# Authentication for bots and agents

This document tells automated clients (AI agents, MCP clients, scripts) how to
authenticate against the Strand AI platform API. The public API is served from
`https://app.strandai.com/api/v1`; authorization is handled on the
`https://auth.strandai.com` zone. Every API request must carry a bearer
credential in the `Authorization: Bearer <token>` header.

There are two ways to authenticate. Both are organization-scoped, and per-org
rate and concurrency limits apply.

## 1. API keys (recommended for headless REST clients)

Mint an API key in the Strand Platform at
<https://app.strandai.com/settings/api-keys>. Keys look like
`sk-strand-XXXXXXXXXXXXXXXXXXXXXXXX` and are passed directly as the bearer
token:

```
Authorization: Bearer sk-strand-XXXXXXXXXXXXXXXXXXXXXXXX
```

This is the simplest path for server-to-server automation against the REST API.

**API keys do not work with the remote MCP server.** The
[MCP server](/.well-known/mcp.json) at `https://mcp.strandai.com/mcp` allows only
the exact unauthenticated `initialize` → `notifications/initialized` →
`tools/list` catalog handshake. Tool invocation, data-bearing methods, and every
other method require OAuth 2.1 and return a `WWW-Authenticate` challenge when no
token is present. Any supplied authorization is validated; an invalid token or
API key is rejected and never downgraded to public discovery. See the
[public tool listing](/.well-known/mcp/server-card.json) for what it exposes.

## 2. OAuth 2.1 (for acting on behalf of a user or organization)

Strand runs a standards-compliant OAuth 2.1 / OpenID Connect authorization
server for agents that act on behalf of a user with explicit organization
consent. It uses the authorization-code flow with S256 PKCE and RFC 8707
resource binding.

Discover the endpoints programmatically rather than hard-coding them:

- Authorization-server metadata (RFC 8414 / OpenID Connect Discovery):
  <https://auth.strandai.com/.well-known/openid-configuration>
- Protected-resource metadata (RFC 9728) for the REST API:
  <https://app.strandai.com/.well-known/oauth-protected-resource/api/v1>
- Protected-resource metadata (RFC 9728) for the remote MCP server, which is a
  separate resource with its own audience:
  <https://mcp.strandai.com/.well-known/oauth-protected-resource/mcp>

Key facts from that metadata:

- Authorization endpoint: `https://auth.strandai.com/oauth2/auth`
- Token endpoint: `https://auth.strandai.com/oauth2/token`
- Dynamic client registration: `https://auth.strandai.com/oauth2/register`
- Supported grant types: `authorization_code`, `refresh_token`
- PKCE code challenge method: `S256` (required)
- Scopes: `samples:read`, `samples:write`, `jobs:read`, `jobs:write`,
  `results:read`, `credits:spend` (plus `openid`, `email`, `offline_access`)

## Reference

- OpenAPI 3.1 spec: <https://app.strandai.com/api/v1/openapi.json>
- API reference (Markdown): <https://app.strandai.com/docs/api.md>
- Documentation: <https://docs.strandai.com>
- Support: <mailto:support@strandai.com>
