# auth.md

You are an agent. This document tells you how to get credentials for the agent APIs of **Surf Inc.**, and when you do not need any. Follow it top to bottom.

**There is no paywall, no signup and no sales call.** The catalogue, prices, stock, shipping quotes and policies are free to read with no account, no API key and no registration of any kind — a free tier that is simply the whole read surface. Only the MCP endpoint expects a bearer token, and you can issue yourself one in a single request: no human is involved.

**No sandbox is needed.** Every operation here is read-only — nothing creates, changes or deletes anything — so there is no destructive call to practise away from production. Point your client at this store directly.

## Discover

Machine-readable metadata:

```http
GET https://surf.inc/.well-known/oauth-protected-resource/agent/mcp
GET https://surf.inc/.well-known/oauth-authorization-server
GET https://surf.inc/.well-known/api-catalog
GET https://surf.inc/.well-known/agent-skills/index.json
```

The first document describes the MCP endpoint. The same metadata for the store as a whole is at https://surf.inc/.well-known/oauth-protected-resource. The `agent_auth` block in the authorization server metadata restates the registration method below.

No credentials are required for any of the above, nor for [llms.txt](https://surf.inc/llms.txt), the [agent sitemap](https://surf.inc/agent-sitemap.xml), or any page requested with `Accept: text/markdown`.

## Pick a method

| Method | Supported here | Notes |
| --- | --- | --- |
| `anonymous` | yes | Register with no identity and get a read-only bearer token back in the same response. See Register. |
| `identity_assertion` | no | This store runs no authorization server: no ID-JAG is accepted and there is no token endpoint. |
| `service_auth` | no | There is no email-based claim ceremony. |

There is no claim step. A token here reaches only what the store publishes without one, so there is nothing for a person to take ownership of.

## Register

Registration is **automatic** and anonymous. POST to the endpoint below and the token comes back in the same response. No human, no form, no waiting.

```http
POST https://surf.inc/v1/register
Content-Type: application/json
Idempotency-Key: <any unique string>

{"type": "anonymous", "label": "my-agent"}
```

The same request with curl:

```
curl -X POST https://surf.inc/v1/register \
  -H "Content-Type: application/json" \
  -d '{"type": "anonymous", "label": "my-agent"}'
```

Both fields are optional. `type` may only be `anonymous`: any other value is refused with a `400` naming the method as not enabled. The response carries `access_token`, `token_type`, `expires_in` and `scope`. Tokens are valid for 30 days and are free. Registration is limited to 10 per hour per address, so reuse the one you hold rather than asking again. With an `Idempotency-Key`, a retry after a dropped connection returns the token already issued instead of a second one.

The token is read-only and reaches exactly the data this store already publishes without any credential. It exists because the MCP protocol expects a bearer credential, not because it unlocks anything.

## Use the access_token

```http
POST https://surf.inc/agent/mcp
Authorization: Bearer <token>
Content-Type: application/json

{"jsonrpc":"2.0","id":1,"method":"tools/list"}
```

Discovery (`initialize`, `tools/list`, `resources/list`) answers without a token; only `tools/call` needs one. There is no refresh flow. A self-issued token expires after 30 days: when it does, register again. A token issued by the owner stays valid until the owner regenerates it.

## Errors

| Status | Meaning | What to do |
| --- | --- | --- |
| `400` | Registration asked for a method this store does not offer (`issuer_not_enabled`, `service_auth_not_enabled`). | Register as `anonymous`. |
| `401` | Missing, expired or withdrawn token. | Register again for a fresh one. `WWW-Authenticate` points at the Protected Resource Metadata. |
| `403` | The store owner blocked your agent. | Respect it. Do not retry with a different user agent. |
| `404` | The feature is switched off on this store. | Treat as absent, not as an outage. |
| `405` | Wrong method on the MCP endpoint. | It accepts POST only. |
| `429` | Rate limited, or too many registrations from your address. | Wait for `Retry-After` seconds; reuse the token you hold. |
| `503` | Temporary failure generating a document. | Retry with backoff. |

## Revocation

- Self-issued tokens expire after 30 days. The owner can also withdraw every self-issued token at once in the Back Office. Either way you get `401`: register again.
- The owner revokes their own token by regenerating it in the Back Office, which invalidates the previous one immediately. Expect `401` from then on.
- Access can also be withdrawn per agent in robots.txt; a `403` means exactly that.
- Every tool here is **read-only** — nothing writes a cart, an order or customer data — so a leaked token exposes catalogue information the store already publishes.
