# Authentication and keys

> Sandbox and live keys, the Bearer header, and how to revoke a key.

Every request carries your key in one header. The REST API and the MCP server take the same key and the same header.

```bash
curl "https://data.heytownhall.com/v1/jurisdictions?limit=1" \
  -H "Authorization: Bearer $HTD_KEY"
```

## Two kinds of key

| Key starts with | Environment | Reaches                                                                                            | Requests a minute |
| --------------- | ----------- | -------------------------------------------------------------------------------------------------- | ----------------- |
| `htd_test_`     | sandbox     | The sandbox: Port Ellery, Marlow County and Tolland Township, fictional, in the live shapes. Free. | 10                |
| `htd_live_`     | live        | The live records. Billed per request.                                                              | 600               |

A sandbox key reads only the sandbox, and a live key reads only the live records. The prefix tells the API which one it has, and every answer says which with `environment`.

## Getting a key

**Sign-ups are not open yet.** Keys come from the [dashboard](https://data.heytownhall.com/dashboard) once sign-ups open. Until then you can read these guides and the reference, and plan your build against the sandbox shapes.

A live key needs a payment method on the account, and only an account owner can create one.

**Live keys are not open yet.** They open once the rates are final. Until then a card can be saved in the dashboard, and a request with a live key answers `403` with the code `live_not_open`. Sandbox keys work now.

## A key is shown once

The dashboard shows a key's full value once, when you create it. After that it shows the prefix and the last four characters, such as `htd_live_…a9Qz`, so you can tell your keys apart. Copy the key into your secret store when you create it. If you lose it, create a new one and revoke the old one.

## Keep keys on your server

Call the API from your server, not from a web page. The API sends no CORS headers, and a key in a page is a key anyone can read.

## Revoke a key

Revoke a key in the dashboard as soon as you think it may have leaked, then create a new one. A revoked key can still answer for up to a minute in a data centre that had it, and then it answers `401`.

## When a key is refused

| Answer | Code               | Why                                                                                                                           |
| ------ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `401`  | `unauthorized`     | No key, or not a valid one: unknown, revoked, or not a Hey Town Hall Data key. The answer carries `WWW-Authenticate: Bearer`. |
| `402`  | `billing_required` | A live key with no payment method on file, or live keys paused for an unpaid invoice.                                         |

[Errors](https://data.heytownhall.com/docs/errors) lists every code.
