> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trycaesar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API reference

> Base URL, authentication, conventions, and the endpoints of the Caesar search API.

The playground and raw API calls require an API key. [Sign up in the Caesar app](https://app.trycaesar.com), create a key, and try it now:

```bash cURL theme={"system"}
curl -s https://alpha.api.trycaesar.com/v1/search \
  -H "Authorization: Bearer $CAESAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "linux kernel scheduler", "max_results": 3}'
```

## Base URL and spec

|              |                                                                               |
| ------------ | ----------------------------------------------------------------------------- |
| Base URL     | `https://alpha.api.trycaesar.com`                                             |
| OpenAPI spec | `GET /openapi/public.json` — stable, machine-readable, served unauthenticated |

Agents and code generators should fetch the spec directly; the generated endpoint pages alongside this one are rendered from it.

## Authentication

Send `Authorization: Bearer $CAESAR_API_KEY` on API calls. A missing or bad key returns `401` and the request does not proceed unauthenticated. See [Authentication](/authentication).

## Conventions

| Convention       | Detail                                                                                                                                                                                                                                                                                                               |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| JSON only        | Requests and responses are `application/json`. Bodies must be a single JSON object; unknown fields are rejected with `400 validation_error`; max body size is 1 MiB.                                                                                                                                                 |
| snake\_case      | All field names are snake\_case (`doc_id`, `max_results`, `canonical_url`) — exactly as the API returns them.                                                                                                                                                                                                        |
| UUIDs everywhere | Every identifier (`request_id`, `search_id`, `session_id`, `doc_id`, `passage_id`, `capture_id`, `feedback_id`) is a plain UUID string.                                                                                                                                                                              |
| `request_id`     | Every response — success or error — carries one. Quote it when reporting an issue.                                                                                                                                                                                                                                   |
| `session_id`     | If you do not supply one (`session_id` body field on `/v1/search` and `/v1/feedback`; the `X-Session-ID` header on any endpoint — `/v1/document` accepts only the header), the server issues a fresh UUID per request and echoes it. Pass it back on later calls for continuity. See [Sessions](/concepts/sessions). |
| `access` block   | Success responses include your live rate-limit state.                                                                                                                                                                                                                                                                |
| `usage` block    | Success responses include `requests` and `bytes_returned`.                                                                                                                                                                                                                                                           |

The `access` and `usage` blocks look like this:

```json theme={"system"}
{
  "access": {
    "rate_limit": { "limit_rps": 100, "remaining": 99, "reset_at": "2026-06-12T17:06:47Z" }
  },
  "usage": { "requests": 1, "bytes_returned": 550 }
}
```

## Endpoints

| Endpoint                        | Description                                                                     |
| ------------------------------- | ------------------------------------------------------------------------------- |
| `POST /v1/search`               | Run ranked retrieval over canonical documents and passages.                     |
| `POST /v1/document`             | Inspect one canonical document and retrieve selected content.                   |
| `POST /v1/feedback`             | Persist an agent or evaluation feedback event.                                  |
| `POST /v1/files/presign`        | Create a presigned upload URL for your [files knowledge base](/concepts/files). |
| `GET /v1/files`                 | List your organization's uploaded files.                                        |
| `DELETE /v1/files/{name}`       | Delete an uploaded file by name.                                                |
| `POST /v1/files/index`          | Start an indexing run so uploads become searchable.                             |
| `GET /v1/files/index/{sync_id}` | Poll an indexing run's progress.                                                |

The [SDKs](/clients/sdks/python) and [CLI](/clients/cli/usage) wrap these exact endpoints — same fields, same semantics. The [remote MCP server](/clients/mcp/remote) exposes the search and document endpoints as its `web_search` and `web_fetch` tools; feedback and file operations are REST/SDK/CLI-only.

## Rate limits

Every response carries three headers: `X-RateLimit-Limit-RPS`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` (RFC3339). Exceeding your per-second limit returns `429 rate_limited`. There is no `Retry-After` header — wait until `X-RateLimit-Reset` or back off exponentially. Details in [Rate limits](/rate-limits).

## Errors

All errors share one envelope: `type` is the literal string `"error"`, plus `request_id` and an `error` object with a stable snake\_case `code`, a human-readable `message`, and optional `details`.

```json theme={"system"}
{
  "type": "error",
  "request_id": "ee314ccd-dbcd-418f-9c6a-f2917c599c67",
  "error": { "code": "invalid_api_key", "message": "missing or invalid API key" }
}
```

Branch on `error.code`, not `message`. The full code table is in [Errors](/concepts/errors).

## Idempotency and caching

All three endpoints are POST and there is no idempotency key. Repeating an identical search is not guaranteed to return identical results: ordering, scores, and `search_id` values can differ between replays. `score.value` is response-local — comparable only within the response that returned it, never across responses or ranker versions. Treat each response as a snapshot, and use `doc_id` plus [provenance](/concepts/provenance) when you need reusable references.
