# Keys and access

Every request carries a key in the `Authorization` header:

**HeaderCopy**

```http
Authorization: Bearer YOUR_API_KEY
```

A key is an opaque 32-character secret. It is not a JWT, and there is nothing inside it to read. Keep it on your server, in an environment variable or a secret store, and out of logs, URLs and code.

No key, a wrong key, or a key that was turned off or regenerated gets `401`. If the API cannot check a key for a moment, it answers `503` with `Retry-After: 5`. That is not a revoked key: wait a few seconds and try again.

**Response401 UnauthorizedCopy**

```json
{
  "error": "Unauthorized",
  "message": "Invalid token or inactive user."
}
```

## Main and API Messaging keys

The portal makes two kinds of key. The API itself cannot create or change keys.

| Property | Main key | API Messaging keys |
| --- | --- | --- |
| Made in | Integrations page, Portal Public API, **Generate** | Textdock, **API Messaging** |
| How many | One per account | Up to 10 per account: one for each integrator, each with its own label |
| Reaches | Every route | Texting only (the `messaging` scope) |
| Sending texts | Up to 20 a minute and 200 a day through `POST /v1/messages`, inside the account's included texting (50 texts an hour and 150 a day as standard, shared with the texts the account's people send) | A whole batch is accepted and paced out by a queue, 60 message parts a minute and 5,000 messages a day to start, set per key. Paid per message, so the account's included texting limit never holds these back and they never use it up |
| IP allow-list | Optional | Required |

API Messaging keys are metered. A key can also be narrowed to `agents`, `support` or `knowledge`, for an AI agent, a help desk or a chat bot that should reach nothing else. [Ask Vocatech support](https://vocatech.com/developers/guide#support) for one.

## Scopes

A key with no scope reaches every route. A narrowed key reaches only the routes of its scopes. Any key may call `GET /v1/whoami`.

| Scope | Reaches | Notes |
| --- | --- | --- |
| `messaging` | `/v1/messages` (send, history, queue), `/v1/reports/messages`, `/v1/media`, `/v1/webhooks` | Media: message attachments only, never recordings or faxes. Webhooks: the three message events, on endpoints this key created. |
| `agents` | `/v1/agents`, `/v1/callers`, `/v1/contacts/lookup` | What an AI agent needs: who is calling, and your agents. |
| `support` | `/v1/support`, `/v1/knowledge` | Open tickets and ask the knowledge base. |
| `knowledge` | `/v1/knowledge` | Ask the knowledge base, nothing else. |

Outside its scope, a key gets `403`:

**Response403 ForbiddenCopy**

```json
{
  "error": "Forbidden",
  "message": "This API key is limited to messaging and cannot be used for /v1/calls.",
  "scopes": "messaging",
  "path": "/v1/calls"
}
```

## IP allow-list

Lock a key to the addresses your servers call from, and a copied key is useless anywhere else.

- Enter exact IPv4 or IPv6 addresses. Ranges are not accepted. An empty list means any address.
- Main key: on the Integrations page, fill **Allowed IPs** and press **Save allowed IPs**. It is optional.
- API Messaging keys: the portal requires the list when it makes the key.

Before you lock a key, call `GET /v1/whoami` from the server that will use it and allow the `client_ip` it reports. The **Connections** panel next to the key lists every address the key was called from. Matching is exact: an IPv4 address and its IPv6 form (`::ffff:203.0.113.24`) count as two different addresses.

A request from any other address gets `403`. The answer names the address the API saw, so when calls that worked start failing, you can see at once that your server's address changed:

**Response403 ForbiddenCopy**

```json
{
  "error": "Forbidden",
  "message": "This API key is restricted to specific IP addresses and 203.0.113.24 is not one of them.",
  "client_ip": "203.0.113.24"
}
```

## Rotating a key

Press **Regenerate** next to the key and confirm. The new key replaces the old one at once: from that moment the old key gets `401`. So rotate in this order:

1. Make sure your system can take a new key quickly, from a secret store or an environment variable.
2. Regenerate in the portal and copy the new key.
3. Put it in place and restart whatever reads it.

Regenerating the main key does not touch your API Messaging keys, and each API Messaging key regenerates on its own. If a key leaks, regenerate it right away and [tell us](https://vocatech.com/developers/guide#support).
