# API keys, roles and rate limits

Every request to WarpSearch is authenticated. There is no anonymous access, including to the
compatible endpoints. You authenticate with an API key, and the key's role decides what the request
may do. This page covers keys, roles, visibility and rate limits.

## Authenticate

Send the key as a bearer token:

```bash
curl https://api.warpsearch.io/v1/collections \
  -H "Authorization: Bearer $WARPSEARCH_API_KEY"
```

Keys look like `ws_live_...`. The same key works on `/v1`, on the Elasticsearch, OpenSearch and
Solr compatible endpoints, and on the MCP server at `/mcp`. For clients that cannot set a bearer
header, the key is also accepted as `X-API-Key: <key>`, as `Authorization: ApiKey <key>`, or as the
password of HTTP Basic with an empty or any username.

Keep keys out of source control and browser code. Anyone holding a key has its role.

Missing or invalid credentials answer `401`. Repeated failures from one address are throttled
with `429 too_many_auth_failures`, so a script with a wrong key should stop rather than retry in
a tight loop.

## Roles

Each key has one of three roles, and so does each member of your organization.

| Role | Can do |
|---|---|
| `viewer` | List and describe collections, search, count, translate, get a document by id, read usage. |
| `editor` | Everything a viewer can, plus index, replace and delete documents, and refresh. |
| `admin` | Everything an editor can, plus create, change and delete collections, change mappings, force merge, and manage members and API keys. |

Roles are cumulative. A refused call answers `403 forbidden`, and the message names the role you
needed, for example that the key lacks the admin role on a collection.

Pick the lowest role that works: a search service gets `viewer`, a loader gets `editor`, and only
provisioning scripts get `admin`.

## Create and revoke keys

Create keys in the [console](/console/) under **API keys**:

1. Create a key, give it a descriptive name (for example `ci-loader`) and pick a role.
2. Copy the secret. It is shown once and cannot be retrieved later.
3. To revoke, delete the key in the same place. Revocation takes effect within a few minutes
   everywhere.

Rules to know:

- A key's role can never be higher than the role of the person who created it.
- A key acts only in the organization it was created in.
- A key stops working if the person who created it leaves the organization, so use a dedicated
  member for long-lived automation.
- Keys cannot create other keys or send invitations. Both need a signed-in console session, so a
  leaked key cannot mint credentials that outlive its revocation.
- Editors manage their own keys. Admins see and manage all keys in the organization.

Agents get keys through a consent flow instead of copy and paste: the agent registers, you approve
in the console and choose the role, and the key is created in your name. See
[Guide for AI agents](agents.md).

## Members and invitations

Admins invite people by email from the console and choose a role. The person accepts the invitation
by link, and may belong to several organizations. Removing a member also revokes their keys in your
organization.

> **Not supported:** single sign-on with your own identity provider.

## Visibility

A collection you hold no role on does not exist as far as your key can tell. It is absent from
listings, and every route answers `404` exactly as it does for a name that was never created. A
collection you can see but cannot use for the request answers `403` with the role you need.

`GET /v1/auth/me` shows who the key belongs to, its role on each visible collection, its
permissions and its effective rate limit. It is the first thing to call when a request is refused.

## Rate limits

Requests are limited by a token bucket per organization, based on your plan, and your plan also
sets how many requests may run at the same time. A request over either limit answers `429` with a
`Retry-After` header:

| Code | Meaning |
|---|---|
| `rate_limited` | You exceeded your requests per second. Retry after `Retry-After`. |
| `too_many_concurrent_requests` | Too many requests are in flight at once. Retry in a moment. |
| `too_many_auth_failures` | Too many failed authentications from your address. |

Responses carry `RateLimit-Limit` and `RateLimit-Remaining` headers, so a client can slow down
before it is refused. The limits depend on your plan: see [Pricing](pricing.md#free-tier) for the
free tier and [/pricing](/pricing) for paid plans.

How to behave:

- On `429`, wait for `Retry-After` and retry with some jitter. Do not retry in a tight loop.
- Batch writes instead of sending many small requests. See
  [Ingesting documents](ingesting-documents.md).
- Debounce search-as-you-type, and cache repeated queries.
- Cap an agent's retries and tool calls, because it can issue queries faster than a person.

A plan can count the limit per client address instead of per organization, which matters when many
end users share one key. `GET /v1/auth/me` reports the effective limit.

## Usage and plan

`GET /v1/usage` returns your plan, how many collections you have against the limit, and stored
documents and bytes. The call needs a key with permission to view usage; the console shows the same
numbers. For the limits themselves, see [Limits and errors](limits-and-errors.md).

## Good practice

- One key per service and environment, so you can revoke one without touching the rest.
- Keep browser-facing search behind your own server, or use a `viewer` key that can only search.
- Rotate keys by creating the new one, deploying it, then deleting the old one.
- Check each key's last-used time in the console to find keys that nothing uses any more.
