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

# API reference

> The HTTP API behind the Keenable CLI, MCP server, and integrations.

Two endpoints sit under everything else Keenable ships — the [CLI](/cli), the [MCP server](/mcp-server), and every [integration](/integrations) call one or both of them. Reach for the HTTP API directly when you are building something none of those cover.

## Base URL

```
https://api.keenable.ai
```

## Authentication

There are two ways in, and the one you pick decides the path you call.

**With an API key**, in the `X-API-Key` header:

```bash theme={"dark"}
curl -X POST "https://api.keenable.ai/v1/search" \
  -H "X-API-Key: keen_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{ "query": "typescript best practices" }'
```

`Authorization: Bearer keen_<your_key>` works too, and `X-API-Key` wins if both are present. See [Authentication](/authentication) for obtaining and rotating a key, and for the error responses both endpoints share.

**Without one**, on the `/public` twin of each endpoint:

```bash theme={"dark"}
curl -X POST "https://api.keenable.ai/v1/search/public" \
  -H "X-Keenable-Title: My App" \
  -H "Content-Type: application/json" \
  -d '{ "query": "typescript best practices" }'
```

`X-Keenable-Title` names the application making the call. It is **required** on the public endpoints — a request without it is rejected with `400 Missing app identifier` — and it is how keyless traffic is attributed. Values longer than 256 characters are truncated, and `?keenable_title=` carries the same value when a header is not an option.

Parameters and response shapes are identical on both sides, so moving between them means changing the path and swapping one header. This keyless tier is what the [CLI](/cli), the [MCP server](/mcp-server), and every [integration](/integrations) fall back to when no key is configured.

## Endpoints

| Endpoint                        | Method | Path         | Keyless path        | Returns                                                       |
| ------------------------------- | ------ | ------------ | ------------------- | ------------------------------------------------------------- |
| [Search](/api-reference/search) | `POST` | `/v1/search` | `/v1/search/public` | Ranked results with URLs, titles, descriptions, and snippets  |
| [Fetch](/api-reference/fetch)   | `GET`  | `/v1/fetch`  | `/v1/fetch/public`  | Page content as markdown, with title, description, and author |

Each endpoint page carries the full request and response shape, examples in curl, Python, and TypeScript, and a playground you can call with your own key.

## Limits and billing

Authenticated requests are rate limited per organization rather than per IP — see [Rate limits](/rate-limits) for the numbers — and draw on your [credit](/credits) balance.

Keyless requests are limited per IP instead, on a public pool capped at 1,000 requests per hour and 10 per second, and they consume no credits. Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, and a `429` adds `Retry-After`. That pool is shared with everyone else on your egress address, so its headroom is outside your control: use a key for anything past a first look.
