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

# API keys

> Create scoped API keys, authenticate with a Bearer token, and understand the rate limit and pagination on the public REST API.

An API key lets a script, a CI job, the [MCP server](/integrations/mcp), or a Terraform run talk to Tallwatch without a browser session. You create a key in the dashboard, copy it once, and send it as a Bearer token on every request. Tallwatch stores only a SHA-256 hash of the key, so a key cannot be recovered after you close the dialog.

## Create a key

<Steps>
  <Step title="Open API keys">
    Go to **Settings → API keys** and click **Create API key**. Give it a name you'll recognise later (for example `ci-deploy` or `terraform`).
  </Step>

  <Step title="Pick scopes and expiry">
    Choose `read`, `write`, or both, and an expiry (never, 30 days, 90 days, or a year). Scopes default to `read` if you pick nothing.
  </Step>

  <Step title="Copy the key now">
    The full key, which starts with `tw_live_`, is shown **once**. Copy it and store it in a secret manager or an environment variable. Once you dismiss the dialog, Tallwatch has only the hash and cannot show it again.
  </Step>
</Steps>

<Warning>
  The key is shown a single time. If you lose it, revoke it and create a new one. There is no way to retrieve a key after the create dialog closes.
</Warning>

In the list, each key shows its visible prefix (for example `tw_live_a4f2`), its scopes, when it was last used, and its expiry. That prefix is enough to identify a key in your logs without exposing the secret.

## Authenticate

Send the key as a Bearer token in the `Authorization` header:

```bash theme={null}
curl https://api.tallwatch.com/api/v1/monitors \
  -H "Authorization: Bearer tw_live_your_key_here"
```

A request with no key and no session cookie returns `401` with `{ "code": "no_session" }`.

## Scopes

Scopes are deliberately coarse in v1: a key carries `read`, `write`, or both.

| Scope   | Authorizes                                                                                               |
| ------- | -------------------------------------------------------------------------------------------------------- |
| `read`  | `GET` requests on the public resource routes (list and fetch monitors, incidents, status pages, alerts). |
| `write` | Mutations: create, update, and delete monitors, and acknowledge or resolve incidents.                    |

If a key lacks the scope a route needs, the request returns `403` with `{ "code": "insufficient_scope", "required_scope": "write" }`. Give a key only the scopes it needs: a read-only dashboard exporter should never hold a `write` key.

## What a key can reach

These routes accept a Bearer key. Anything not listed (bulk pause/resume/delete, the "test now" check, status-page create/edit, incident comments, rename, and post-mortems) stays session-only in v1.

| Method   | Path                                   | Scope   |
| -------- | -------------------------------------- | ------- |
| `GET`    | `/api/v1/monitors`                     | `read`  |
| `GET`    | `/api/v1/monitors/{id}`                | `read`  |
| `POST`   | `/api/v1/monitors`                     | `write` |
| `PATCH`  | `/api/v1/monitors/{id}`                | `write` |
| `DELETE` | `/api/v1/monitors/{id}`                | `write` |
| `GET`    | `/api/v1/monitors/{id}/rollups`        | `read`  |
| `GET`    | `/api/v1/monitors/{id}/rollups/phases` | `read`  |
| `GET`    | `/api/v1/monitors/{id}/availability`   | `read`  |
| `GET`    | `/api/v1/incidents`                    | `read`  |
| `GET`    | `/api/v1/incidents/{id}`               | `read`  |
| `POST`   | `/api/v1/incidents/{id}/ack`           | `write` |
| `POST`   | `/api/v1/incidents/{id}/resolve`       | `write` |
| `GET`    | `/api/v1/alerts`                       | `read`  |
| `GET`    | `/api/v1/projects/overview`            | `read`  |
| `GET`    | `/api/v1/status-pages`                 | `read`  |
| `GET`    | `/api/v1/status-pages/{id}`            | `read`  |

## Pagination

The list endpoints (`/monitors`, `/incidents`, `/status-pages`) are cursor-paginated, and the pagination is opt-in so older integrations keep working.

* **With no pagination params**, a list returns the legacy shape: `{ "items": [...] }`, the whole set.
* **With a `cursor` or `limit` param**, it returns `{ "data": [...], "next_cursor": "..." }`. The `items` field is mirrored alongside `data` on this path too, so a legacy reader still works.

Pass `limit` to size a page (default `50`, max `100`) and follow `next_cursor` to walk the rest. When `next_cursor` is `null`, you've reached the last page.

```bash theme={null}
# First page of 25
curl "https://api.tallwatch.com/api/v1/monitors?limit=25" \
  -H "Authorization: Bearer tw_live_your_key_here"

# Next page: feed back the next_cursor
curl "https://api.tallwatch.com/api/v1/monitors?limit=25&cursor=<next_cursor>" \
  -H "Authorization: Bearer tw_live_your_key_here"
```

The cursor is an opaque token. Don't parse it or build one yourself; just hand back the value Tallwatch gave you.

## Rate limit

Bearer requests are rate limited per key: **120 requests per minute** by default. Session (cookie) requests from the dashboard are not affected.

Every response carries the standard rate-limit headers so you can pace yourself before you hit the wall:

| Header                | Meaning                              |
| --------------------- | ------------------------------------ |
| `RateLimit-Limit`     | Requests allowed per window.         |
| `RateLimit-Remaining` | Requests left in the current window. |
| `RateLimit-Reset`     | Seconds until the window resets.     |

When you go over, the request returns `429` with `{ "code": "rate_limited", "retry_after_sec": <seconds> }` and a `Retry-After` header set to the same number of seconds. Wait that long, then retry.

## Revoke a key

Delete a key from **Settings → API keys** to revoke it. Revocation is a soft delete: the key stops working immediately, but the row stays in the list (greyed out) so the audit trail survives. Revoking is the right move the moment a key leaks or a script is retired.

## OpenAPI spec

The public API ships an OpenAPI 3.1 spec at a public URL, with no auth required:

```
https://api.tallwatch.com/api/v1/openapi.json
```

It describes the monitor, incident, and status-page routes, the Bearer security scheme, and the paginated response shapes. Point Postman, Insomnia, or a client generator at it to scaffold a typed client.

<Note>
  Tallwatch is pre-1.0. Scopes are coarse (`read` / `write`) by design in this
  release; per-resource scopes are a later concern. The rate limit is enforced
  per API replica, so a key's effective ceiling scales with the number of API
  instances.
</Note>
