# OrcaLayer auth.md

You are an AI agent reading OrcaLayer data for a person: an MCP client (Claude, ChatGPT, Cursor and others), a coding
agent or script calling the REST API, or a research assistant reading the site. OrcaLayer is read-only analytics of
Polymarket smart money. Follow the steps in order.

- Resource server, REST API: https://orcalayer.com/api/v2 (OpenAPI 3.1: https://orcalayer.com/api/v2/openapi.json)
- Resource server, MCP: https://orcalayer.com/mcp, Streamable HTTP (server card: https://orcalayer.com/.well-known/mcp/server-card.json)
- Resource server, A2A: https://orcalayer.com/a2a, JSON-RPC (agent card: https://orcalayer.com/.well-known/agent-card.json).
  The same key rules apply: free skills without a key, Premium skills with `Authorization: Bearer sk_orca_...`.
- API catalog: https://orcalayer.com/.well-known/api-catalog
- Resource server, MCP with sign-in: https://orcalayer.com/mcp/premium. Without a token it answers `401` with
  `WWW-Authenticate: Bearer resource_metadata="https://orcalayer.com/.well-known/oauth-protected-resource/mcp/premium"`.
- Authorization server: https://orcalayer.com (OAuth 2.1, metadata: https://orcalayer.com/.well-known/oauth-authorization-server;
  protected resource metadata: https://orcalayer.com/.well-known/oauth-protected-resource). Authorization code with PKCE
  S256, public clients, dynamic client registration. The access token it issues is an OrcaLayer API key.

## Step 1: Discover

Read https://orcalayer.com/.well-known/api-catalog for the APIs and https://orcalayer.com/.well-known/mcp/server-card.json
for the MCP tools. For OAuth, start from the protected resource metadata above. A `401` from a keyed endpoint means the
call needs the `oauth` or `api_key` method below.

## Step 2: Pick a method

| Method | Registration | Credential | What it opens |
|---|---|---|---|
| `no_credential` | none | none | public REST read endpoints, free MCP tools, prompts and resources, every page |
| `anonymous` | the agent registers itself; the person claims it with a 6-digit code | access token (an OrcaLayer API key) | Premium REST endpoints and Premium MCP tools |
| `oauth` | dynamic client registration, then the person signs in and allows | access token (an OrcaLayer API key) | Premium REST endpoints and Premium MCP tools |
| `api_key` | the person registers and provisions a key | API key `sk_orca_<32 hex>` | Premium REST endpoints and Premium MCP tools |

1. You only need public data (a wallet profile, market search, the leaderboard, the free MCP tools) → `no_credential`.
2. You are an agent without a browser redirect (a CLI, a chat assistant) and need Premium → `anonymous` (agentic registration).
3. You are an MCP client that supports OAuth (Claude and ChatGPT connectors, Cursor, VS Code) and need Premium → `oauth`.
4. Otherwise → `api_key`.

## Step 3: Register

### anonymous (agentic registration)

Authorization server metadata carries an `agent_auth` block (https://orcalayer.com/.well-known/oauth-authorization-server):
`register_uri` / `identity_endpoint`, `claim_uri` / `claim_endpoint`, `identity_types_supported: ["anonymous"]`.

1. Register: `POST https://orcalayer.com/api/agent/identity` with `{"type": "anonymous", "client_name": "<your name>"}`.
   Response: `registration_id`, `claim_token` (secret, returned once: keep it in memory), `claim_token_expires`
   (24 hours) and `claim`: `{"user_code": "123456", "verification_uri": "https://orcalayer.com/agent/claim?t=...",
   "expires_in": 600, "interval": 5}`. Before the claim you need no credential for the free endpoints.
2. Hand off: show the person `claim.verification_uri` and `claim.user_code` in one message (see Step 4). They sign in
   on orcalayer.com, see your `client_name`, type the code and allow. The account needs Premium.
3. Poll: `POST https://orcalayer.com/api/oauth/token` (form-encoded) with
   `grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_...` every `interval` seconds.
   `authorization_pending` → keep polling; `expired_token` → `POST https://orcalayer.com/api/agent/identity/claim` with
   `{"claim_token": "clm_..."}` for a fresh `claim` block, or register again after 24 hours.
   Success: `{"access_token": "sk_orca_...", "token_type": "Bearer", "scope": "orcalayer:read"}`, issued once.
4. The person sees and removes it in Settings, API Keys as "Agent: <client_name>".

### no_credential

No registration and no credential. Call the endpoints as is:

- REST: public read endpoints, throttled per IP address.
- MCP: connect to https://orcalayer.com/mcp without an Authorization header. Free tools: leaderboard, wallet_overview,
  wallet_positions, markets, market_consensus. Limit: 60 requests per minute per client address.
- Pages: every public page returns markdown when requested with `Accept: text/markdown`.

### oauth

Standard OAuth 2.1 for public clients; most MCP clients do all of this by themselves when pointed at
https://orcalayer.com/mcp/premium.

1. Registration endpoint: `POST https://orcalayer.com/api/oauth/register` (RFC 7591) with
   `{"client_name": "...", "redirect_uris": ["https://..."], "token_endpoint_auth_method": "none"}` → `client_id`.
   Redirect URIs: https, http on localhost / 127.0.0.1, or a private-use scheme.
2. Send the person to `https://orcalayer.com/oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...`
   `&code_challenge=...&code_challenge_method=S256&scope=orcalayer:read&resource=https://orcalayer.com/mcp/premium`.
   They sign in and allow read-only access. The account needs Premium; otherwise the answer is `error=access_denied`.
3. Exchange the code: `POST https://orcalayer.com/api/oauth/token` (form-encoded) with `grant_type=authorization_code`,
   `code`, `redirect_uri`, `client_id`, `code_verifier` → `{"access_token": "sk_orca_...", "token_type": "Bearer"}`.
   Codes live 10 minutes and work once.
4. The token has no expiry and no refresh step; connecting the same application again replaces its previous token.
   Revoke: `POST https://orcalayer.com/api/oauth/revoke` with `token=...`, or the person removes "OAuth: <app>" in Settings.

### api_key

You cannot register yourself: the account and the key belong to the person. Registration endpoint for the person:
https://orcalayer.com/register. The account needs a linked email and the Premium plan
(https://orcalayer.com/upgrade?tier=premium, billed through Whop).

Provisioning endpoint. The Settings page (https://orcalayer.com/settings, section API Keys, button Generate Key) calls it
with the person's signed-in session; it does not accept an agent's request:

```http
POST https://orcalayer.com/api/auth/api-keys
Cookie: <the person's signed-in orcalayer.com session>
Content-Type: application/json

{ "name": "my-agent" }
```

Response (200), returned once:

```json
{
  "id": 123,
  "name": "my-agent",
  "api_key": "sk_orca_0123456789abcdef0123456789abcdef",
  "rate_limit": 600,
  "created_at": "2026-11-11T12:00:00.000Z",
  "warning": "Save this key now. It will not be shown again."
}
```

Errors: `401` not signed in; `403` the plan is not Premium; `400` no linked email, a missing name, or already 5 active keys.

## Step 4: Hand off to the person

For `anonymous`, in one message:

> Open https://orcalayer.com/agent/claim?t=..., sign in, and enter this code: **123456**

For `api_key`, in one message:

> Open https://orcalayer.com/settings, section API Keys, click Generate Key, and put the key into my secret store
> (environment variable `ORCALAYER_API_KEY`, or the connector's header setting). Do not paste it into the chat.

A key is shown once. Never put a key or a claim_token in a prompt, a URL or a log.

## Step 5: Use the credential

- MCP: send `Authorization: Bearer sk_orca_...` on the connection. The Premium tools (whale_alerts, pnl_leaderboard,
  resolution_events) then appear in `tools/list`.
- REST `/api/public/v1/*`: `Authorization: Bearer sk_orca_...` or `x-api-key: sk_orca_...`.
- REST Premium endpoints under `/api/v2/*`: `x-api-key: sk_orca_...`.
- There is no token exchange and no refresh step. The key has no expiry date and works while the account's plan
  includes the endpoint.

Limits:

- Premium: 600 requests per minute per account across all its keys. Subscriptions started from 1 October 2026 also
  have 25,000 requests per day, reset at 00:00 UTC.
- Business: 3,000 requests per minute, no daily cap.
- Every keyed response carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`.
- MCP tool calls made with a Premium key count against that key's API limit.

## Errors

- `401`: the key is missing, invalid or revoked (on endpoints that need a key). Go to Step 4.
- `403`: the key is valid, but the plan does not include the endpoint.
- `429`: over the limit. Wait for the number of seconds in `Retry-After`.

## Revocation

The person deletes the key in https://orcalayer.com/settings, section API Keys. Requests with it stop working within
about 5 minutes and return `401`.

## Not offered

- OpenID Connect (no ID tokens), confidential clients with secrets, refresh tokens, ID-JAG identity assertions,
  service_auth (email) registration, and any credential issued without a person who signs in and allows it.
- Anything that writes: every endpoint and tool is read-only, nothing places orders or moves funds.
