# For agents

Capless is built to be set up and operated by coding agents. Everything a human can do in the dashboard, an agent can do with one HTTP API or the MCP server, and every docs page is plain Markdown.

## The one-liner

Tell your coding agent:

```text
Add Capless analytics to this site. Instructions: https://capless.sh/llms.txt
```

The agent follows [/AGENTS.md](https://capless.sh/AGENTS.md): create an account with the signup API, add the snippet, verify that events arrive, and hand you the dashboard link.

## Machine-readable docs

| URL | What |
|---|---|
| [/llms.txt](https://capless.sh/llms.txt) | Index in [llmstxt.org](https://llmstxt.org) format, linking every page as Markdown |
| [/llms-full.txt](https://capless.sh/llms-full.txt) | All docs in one file |
| `/docs/<page>.md` | Any docs page as Markdown, e.g. [/docs/cel.md](https://capless.sh/docs/cel.md) |
| [/AGENTS.md](https://capless.sh/AGENTS.md) | Install instructions an agent can follow verbatim |
| [api.capless.sh/v1/openapi.yaml](https://api.capless.sh/v1/openapi.yaml) | OpenAPI 3.1 spec |
| `GET /v1/functions` | The CEL environment: variables per context, limits, number and regex rules |

## Signup API

`POST https://api.capless.sh/v1/signup` creates a user, a project on the 14-day trial, an API key and (with `siteName`) a web analytics site, in one call. No authentication.

| Field | Type | |
|---|---|---|
| `email` | string, required | The human's email. A verification email is sent to it. |
| `password` | string, optional | Omit it to sign in with emailed links only. |
| `projectName` | string, optional | |
| `siteName` | string, optional | Creates a site and returns its snippet. |
| `allowedOrigins` | string[], optional | Origins allowed to send events for the site, e.g. `["https://example.com"]`. |

```sh
curl -s https://api.capless.sh/v1/signup \
  -d '{"email":"jane@example.com","projectName":"acme","siteName":"acme.com","allowedOrigins":["https://acme.com"]}'
```

`201 Created`:

```json
{
  "user": { "id": "…", "email": "jane@example.com" },
  "project": { "id": "prj_…", "name": "acme", "plan": "trial", "trialEndsAt": "…" },
  "apiKey": "cpl_…",
  "site": { "key": "cs_…", "snippet": "<script async src=\"https://c.capless.sh/c.js\" data-site=\"cs_…\"></script>" },
  "dashboardUrl": "https://app.capless.sh/…",
  "mcp": { "url": "https://mcp.capless.sh/mcp", "headers": { "Authorization": "Bearer cpl_…" } }
}
```

* `apiKey` is shown once. Store it where the project keeps secrets (e.g. `.env` as `CAPLESS_API_KEY`); never commit it and never put it in client-side code. The site key `cs_…` is public and write-only, so it is safe in HTML.
* `dashboardUrl` is a one-time sign-in link valid for 15 minutes. Give it to the human.
* `409 email_taken`: the human already has an account. Ask them for an API key from [the dashboard](https://app.capless.sh/login) instead of creating another account.
* `429 rate_limited`: wait and retry later; do not loop.

## End-to-end with curl

No CLI, no SDK. Replace the email and origin.

```sh
# 1. Account + site
curl -s https://api.capless.sh/v1/signup \
  -d '{"email":"jane@example.com","siteName":"acme.com","allowedOrigins":["https://acme.com"]}' > capless.json
export CAPLESS_API_KEY=$(node -p 'require("./capless.json").apiKey')
node -p 'require("./capless.json").site.snippet'    # paste before </head>
node -p 'require("./capless.json").dashboardUrl'    # give to the human

H="authorization: Bearer $CAPLESS_API_KEY"

# 2. After the site is loaded in a browser: events arrived?
curl -s https://api.capless.sh/v1/streams/web.events -H "$H"          # entryCount > 0
curl -s https://api.capless.sh/v1/streams/web.events/read -H "$H" -d '{"limitResultEntries":5}'

# 3. Your own data: a stream with a validator, an idempotent insert, a filtered read
curl -s https://api.capless.sh/v1/streams -H "$H" -d '{"name":"orders","validator":"entry.amount >= 0"}'
curl -s https://api.capless.sh/v1/streams/orders/entries -H "$H" \
  -d '{"idempotencyKey":"import-2026-10-30","entries":[{"user":"u1","amount":42},{"user":"u2","amount":7}]}'
curl -s https://api.capless.sh/v1/streams/orders/read -H "$H" -d '{"filter":"entry.amount > 10"}'

# 4. GDPR: erase one user everywhere
curl -s https://api.capless.sh/v1/streams/web.events/erasures -H "$H" -d '{"filter":"entry.userId == \"user_42\""}'
```

Delete `capless.json` once the key is stored safely.

## MCP

The signup response includes a ready-made MCP config. Install it for Claude Code:

```sh
claude mcp add --transport http capless https://mcp.capless.sh/mcp --header "Authorization: Bearer cpl_…"
```

Then call the `get_started` tool. See [MCP server](https://capless.sh/docs/mcp.md) for other clients and the full tool list.

## Rules of thumb for agents

* Retry writes with the same `idempotencyKey`; a retry returns the original result with `duplicate: true`.
* Read with cursors, not offsets. Persist `nextCursor`; it never skips or repeats.
* Dry-run CEL with `POST /v1/functions/evaluate` before using it on real data.
* Errors carry a stable `code`; branch on it, not on the message.
