Skip to main content
Caesar uses standard Bearer authentication. If you have a partner key, set it in the Authorization header:
curl -s https://search-api-staging-779189860552.europe-west1.run.app/v1/search \
  -H "Authorization: Bearer $CAESAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "rust async runtime comparison", "max_results": 3}'
Drop the Authorization header and the same call still works — anonymously, at a lower rate limit. You do not need a key to evaluate Caesar.

Anonymous tier vs API keys

AnonymousAPI key
Setupnonerestricted to partners
Rate limit30 requests/second per client IPper-key limit, default 100 requests/second
access.tier in responsesanonymousapi_key
Search and feedback attributionnonerecorded to your account
Document access by doc_idany documentaccount-granted documents
A key changes three things:
  1. A higher, dedicated rate limit. Keyed requests are counted per key, not per IP — your limit is yours regardless of where you call from. See rate limits.
  2. Account-scoped attribution. Keyed searches are recorded to your account, and /v1/feedback referencing a search_id or doc_id is checked against that ownership. Your feedback provably belongs to your searches.
  3. Document grants. For keyed callers, /v1/document lookups by doc_id resolve documents your account has been granted — by appearing in your search results or by a prior direct canonical_url lookup. Anonymous callers skip ownership checks entirely.

Key format

Keys start with sk_live_, followed by a 12-character key_prefix and a longer secret. The key_prefix is not secret — it is safe to display in dashboards and logs to identify a key. The full key is returned exactly once at creation and stored only as a hash; it cannot be retrieved again.

Scopes

ScopeGrants
search:readPOST /v1/search
document:readPOST /v1/document
feedback:writePOST /v1/feedback
New keys get all three scopes by default. Calling an endpoint your key lacks the scope for returns 403:
{
  "type": "error",
  "request_id": "ee314ccd-dbcd-418f-9c6a-f2917c599c67",
  "error": { "code": "insufficient_scope", "message": "API key is not allowed to call this endpoint" }
}

Getting a key

API keys are currently restricted to partners. Use anonymous access unless the Caesar team has issued you a partner key.

Invalid keys never fall back to anonymous

If a Bearer token is present, it is always validated. A malformed, unknown, expired, or revoked key returns 401 invalid_api_key — even on deployments where anonymous access is enabled. There is no silent downgrade:
{
  "type": "error",
  "request_id": "ee314ccd-dbcd-418f-9c6a-f2917c599c67",
  "error": { "code": "invalid_api_key", "message": "missing or invalid API key" }
}
To call anonymously on purpose, omit the Authorization header entirely.

One environment variable everywhere

Every first-party client reads CAESAR_API_KEY:
# set in your shell profile, or inject it from your secret manager
export CAESAR_API_KEY="$(your-secret-manager get caesar-api-key)"
The Python SDK and TypeScript SDK pick it up automatically in their constructors, the CLI resolves it after the --key flag, and the MCP server accepts it as a Bearer header. If the variable is unset, all of them run anonymously.

Client attribution: X-Caesar-Client

First-party clients send an attribution header of the form X-Caesar-Client: cli/0.1.4 (or python-sdk/0.1.1, ts-sdk/0.1.1). It is a convention, not a contract: the server does not validate or act on it. If you build on the raw API, sending X-Caesar-Client: yourtool/1.2.3 is encouraged because it helps the Caesar team understand client traffic.

Key hygiene

Never paste an API key into a chat, an issue, or a commit. Keys belong in CAESAR_API_KEY or your secret manager. The CLI stores keys safely via caesar-search auth login (use --key - to pipe from a secret manager), and masks them in all output. If a key leaks, contact the Caesar team to revoke it — the key itself cannot be recovered or rotated in place.