# Agent authentication on ora.ai

How an agent gets access to ora's surfaces, and exactly which credentials exist. Most of ora needs no credential at all: every read endpoint is open. This file follows the auth.md convention (WorkOS spec: https://workos.com/auth-md/docs/auth-md) and documents what ora implements and what it deliberately does not.

## Discover

- All read endpoints are public and keyless: `GET /api/score/{domain}`, `GET /api/leaderboard`, `GET /api/checks`, `GET /api/stats`, the ARD search surfaces, and the MCP server at `https://ora.ai/api/mcp`. Rate limits apply per IP.
- `/.well-known/openid-configuration` exists as a machine-readable service descriptor pointing agents at the MCP endpoint. It is a discovery signal, not a live OAuth authorization server: no endpoint on ora.ai issues OAuth access tokens.
- There is no `/.well-known/oauth-protected-resource` (RFC 9728) and no `agent_auth` metadata block, because no ora API is OAuth-protected.

## Pick a method

- **No credential** - every read, and anonymous scans via `POST /api/scan` within the public rate limits. Start here; it covers almost every agent task.
- **API key** - the keyed tier. A key lifts the scan-family rate limits and unlocks two things: selective check runs whose results are patched into the domain's stored scan (`POST /api/scan/checks` reporting `storedScanUpdated: true`), and the partner journey surfaces (`POST /api/journey/domains/{host}`, free-text intents on `POST /api/journey/runs`).
- **Agent verification** - feedback writes are MCP-only: call the `get_verification_challenge` tool, solve the reverse challenge that proves the caller is an agent, and include the returned token with the submission. No account and no key involved.

## Register

ora does not currently support agentic self-registration: there is no `register_uri`, and no anonymous or `verified_email` registration shape. API keys are provisioned manually per partner - request one by email at hello@ora.ai with the surface you want to call and your expected volume.

## Claim

There is no claim ceremony and no `claim_uri`. A key arrives ready to use.

## Use the API key

Send the key as a bearer credential on keyed endpoints:

```
Authorization: Bearer <your-key>
```

Keyless requests stay valid everywhere else - never send a key you do not have. On `POST /api/scan/checks`, a recognized key is what makes `storedScanUpdated` true; keyless runs execute the same checks statelessly.

## Errors

- `401` with code `PARTNER_KEY_REQUIRED` - `POST /api/journey/domains/{host}` called without a key (that surface has no anonymous tier).
- `401` with code `CUSTOM_INTENT_REQUIRES_KEY` - free-text intent on `POST /api/journey/runs` without a recognized key.
- `429` with a `Retry-After` header and code `RATE_LIMIT_EXCEEDED` - rate-limited; back off for the stated seconds and retry.
- On the scan surface an unrecognized key is not an error: the caller is treated as anonymous and the public limits apply.

## Revocation

There is no `revocation_uri`. Keys are issued per partner and revoked or rotated on request through the same channel that issued them (hello@ora.ai); revoking one partner's key never affects another's.
