# cloro auth.md

cloro's public API uses **API keys** (bearer tokens). Agents authenticate by
attaching the key as `Authorization: Bearer <key>` to every request against
`https://api.cloro.dev`.

The hosted MCP server also accepts **OAuth 2.1** access tokens, so an MCP
client such as Claude can connect with a browser sign-in and no key. See
[Identity types](#identity-types).

## Registration

API keys are issued from the cloro dashboard:

- Sign up: <https://cloro.dev>
- Manage keys: <https://dashboard.cloro.dev/api-keys>

Signup is self-serve, and a key is available immediately after it: no sales
call, no waiting list, no approval step. Every new account starts on a free
tier of 500 credits that refreshes monthly, which is enough to evaluate
response quality and coverage across every supported engine before paying
anything.

There is no programmatic agent-registration endpoint today, and no separate
sandbox host — the free-tier credits run against the production API, so what
you test is what you ship. If you need machine-to-machine onboarding for an
agent platform, write to us at <https://cloro.dev/contact/>.

### What is readable with no key at all

Two surfaces need no authentication, for an agent evaluating cloro before it
has a key:

- The [AI Visibility Leaderboard](https://cloro.dev/ai-visibility/), which is
  built on this API and republished weekly. It shows the shape of the data the
  monitor endpoints return.
- Every machine-readable file listed under [Discovery](#discovery) below.

## Identity types

- **API key** — opaque bearer token, scoped to a single workspace. The
  workspace owner can create or revoke keys at any time from the dashboard.
- **OAuth 2.1 access token** (MCP server only) — a JWT issued by
  `https://clerk.cloro.dev` after the user signs in and selects an
  organization. That organization's credits pay for the calls.

The MCP server publishes RFC 9728 protected resource metadata at
<https://mcp.cloro.dev/.well-known/oauth-protected-resource>. It lists
`https://clerk.cloro.dev` in `authorization_servers`, and the client reads the
authorization server metadata (RFC 8414) from there. The flow is
authorization code with PKCE (S256), and clients identify themselves with a
client ID metadata document. `initialize` and `tools/list` answer without a
credential. The first `tools/call` without one returns `401` with a
`WWW-Authenticate` challenge that starts the flow.

The REST API publishes no protected resource metadata. The `bearerAuth` security scheme in the
OpenAPI spec already says the same thing at a URL clients fetch anyway, and
nothing probes a `.well-known` path for a plain REST API unprompted.

## Credentials

- **Type**: bearer token
- **Header**: `Authorization: Bearer <key>`
- **Rotation**: create a new key, then revoke the old one, from
  <https://dashboard.cloro.dev/api-keys>. There is no rotate action.
- **Revocation**: from <https://dashboard.cloro.dev/api-keys> (a revoked key can
  stay valid for up to 60 seconds)

## Scopes

A single API key grants access to all endpoints documented in the OpenAPI
spec. Per-tool and least-privilege scoping is **not yet available**: there is
one permission level and an agent cannot request less than it. Treat a cloro
API key as a full-workspace credential and store it accordingly.

The MCP server's OAuth scopes are `profile`, `email` and `user:org:read`.
`user:org:read` puts the organization picker on the consent screen. None of
them narrows which tools a token can call.

## Versioning and deprecation

- **Versioning is in the URL path.** Every endpoint lives under `/v1/`, and the
  version is part of the path, never a header or a query parameter. The
  OpenAPI spec at the link below is the authoritative list.
- **Within a version, changes are additive.** New endpoints, new optional
  request fields, and new response fields can appear at any time. A client
  must ignore response fields it does not recognise; that is the one
  requirement for staying compatible.
- **A breaking change gets a new version path** (`/v2/`). Existing paths are
  not repurposed.
- **Deprecation is signalled in the response, not only in a changelog.** A
  deprecated endpoint returns the `Deprecation` header (RFC 9745) with the date
  the deprecation took effect, and `Sunset` (RFC 8594) with the date it stops
  responding. A `Link` header with `rel="deprecation"` points at the
  documentation for the replacement.
- **Minimum notice is six months** between the `Deprecation` date and the
  `Sunset` date on any endpoint that has been generally available.

Nothing is deprecated today, so no live endpoint carries these headers.

## Rate, credit, and concurrency limits

Every authenticated response carries its own limits, so an agent can
self-throttle from the response it already has rather than from a table in the
docs:

| Header | Meaning |
| --- | --- |
| `X-RateLimit-Limit` | Requests allowed in the current window |
| `X-RateLimit-Remaining` | Requests left in the current window |
| `Retry-After` | Seconds to wait, sent on `503` |
| `X-Concurrency-Limit`, `X-Concurrency-Current`, `X-Concurrency-Remaining` | Concurrent in-flight jobs |
| `X-Credits-Charged`, `X-Credits-Remaining` | Credits spent by this request, and the balance left |

The IETF `RateLimit-*` names are not sent today.

A `429` carries no `Retry-After`, so pick the backoff from which limit you
hit. The rate-limit window is one second and clears almost immediately; a
concurrency `429` clears when your in-flight jobs finish and wants a queue
rather than a retry. Plan-level limits: <https://cloro.dev/pricing/>.

## Errors

Every 4xx and 5xx response uses one envelope, described in the OpenAPI spec as
the `Error` schema:

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": { "field": "country" },
    "timestamp": "2026-01-15T12:00:00.000Z"
  }
}
```

`code` is a stable machine-readable identifier and is what a client should
branch on. `message` is for a human reading a log. `details` is
context-specific and optional. Status codes in use: `400`, `401`, `403`,
`404`, `409`, `422`, `429`, `499`, `500`, `502`, `503`.

## Discovery

- OpenAPI 3.1: <https://cloro.dev/openapi.json> (canonical copy:
  <https://cloro.dev/docs/api-reference/openapi.json>)
- API catalog (RFC 9727): <https://cloro.dev/.well-known/api-catalog>
- Hosted MCP server: <https://mcp.cloro.dev/mcp>
- MCP protected resource metadata (RFC 9728):
  <https://mcp.cloro.dev/.well-known/oauth-protected-resource>
- MCP server card: <https://cloro.dev/.well-known/mcp/server-card.json>
- Agent Skills index: <https://cloro.dev/.well-known/agent-skills/index.json>
- Site index for agents: <https://cloro.dev/llms.txt>, which repeats this
  list in its "Machine-readable surfaces" section
