# Authentication

> Authenticate every request with a bearer API key.

All API (and [MCP](/integrations/mcp)) requests authenticate with an API key,
passed as a bearer token.

```
Authorization: Bearer inb_xxxxxxxxxxxxxxxxxxxxxxxx
```

## Creating keys

Create keys in the console under **API keys**. The full key is shown **once** at
creation — copy it then. Inboundr stores only a hash, so a lost key can't be
recovered; revoke it and create a new one.

Keys start with `inb_`. Treat them like passwords: never commit them or expose
them in client-side code.

## Scopes

Every key is one of two kinds, chosen when you create it:

| Scope | Can do | Cannot do |
| --- | --- | --- |
| **Read-only** | `GET` on every resource — list and fetch email, domains, addresses, endpoints, rules | Anything that writes |
| **Full access** | Everything | — |

Read-only is the default, and it's the right choice for most keys. An agent that
polls an inbox, a dashboard, a sync job — none of them need to create resources
or change where mail is routed, and a read-only key that leaks can't do either.

The rule is the HTTP method: `GET` and `HEAD` are reads, everything else is a
write. A read-only key attempting a write gets `403` and the request is not
performed:

```json
{
  "error": "This API key is read-only. Create a key with full access to send email or change configuration."
}
```

Over [MCP](/integrations/mcp), where every call is a `POST`, the *tool* decides
instead. `create_inbox`, `create_shield_rule`, and `delete_shield_rule` need
full access; every `list_*` and `get_*` tool works with a read-only key.

<Note>
  A key's scope is fixed once created — there's no way to widen a read-only key
  into a full one, which is the point. Create a second key instead, and revoke
  whichever you stop using.
</Note>

Keys created before scopes existed have **full access**, so nothing that was
working stopped. If you have long-lived keys that only ever read, replacing them
with read-only ones costs one deploy and removes most of what a leak could do.

## Using a key

```bash
curl https://inboundr.net/api/v1/domains \
  -H "Authorization: Bearer $INBOUNDR_API_KEY"
```

A key is scoped to the account that created it; every request acts on that
account's data only.

## Revoking keys

Revoke a key from the console at any time. Revocation is immediate — subsequent
requests with that key return `401`.

## Errors

| Status | When |
| --- | --- |
| `401 Unauthorized` | Missing/malformed header, or unknown/revoked key. |
| `403 Forbidden` | Read-only key attempting a write. |
| `429 Too Many Requests` | Over the [rate limit](/api-reference/rate-limits). |

```json
{ "error": "Invalid API key" }
```
