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

# Authentication

> Your DSN, access tokens, API keys, and which endpoints are public.

## Access tokens

Every request to `/api/v1` needs an access token in the `X-API-KEY` header:

```bash theme={null}
curl "$EE_URL/api/v1/accounts" -H "X-API-KEY: $EE_KEY"
```

* Generate tokens in your dashboard under **API keys**, or with the [API keys endpoints](#api-keys). A token is shown **once**: the engine only stores its SHA-256 hash.
* Revoke a token in the same place. It stops working at once.
* Give each app or environment its own token, so you can revoke one without affecting the others.
* Tokens go in the header only. A token in the query string is ignored.

A missing, wrong or revoked token gets:

```json 401 Unauthorized theme={null}
{ "status": 401, "type": "errors/unauthorized", "title": "Unauthorized", "detail": "missing or invalid API key" }
```

## DSN

Your **DSN** is your workspace's API address, shown on your dashboard, for example `https://mail-api.example.com`. All API paths start with `/api/v1`:

```
https://mail-api.example.com/api/v1/emails
```

## API keys

You can also manage access tokens through the API. Each key has a `pk_…` id.

### Create a key

```bash theme={null}
curl -X POST "$EE_URL/api/v1/api-keys" \
  -H "X-API-KEY: $EE_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "Production" }'
```

<ParamField body="name" type="string" required>Your name for the key, up to 100 characters.</ParamField>

```json Response theme={null}
{
  "object": "ApiKey",
  "id": "pk_0f1e2d3c4b5a69788796a5b4c3d2e1f0",
  "name": "Production",
  "prefix": "ee_Zq3Rk",
  "role": "service",
  "issued_at": "2026-10-07T08:00:00Z",
  "last_used_at": null,
  "key": "ee_Zq3Rk8Tn2Vb6Xy1Lm4Pw7Hs9Jd5Fg0aB"
}
```

`key` is the access token. It's in this response **only**, so store it safely.

### List and revoke keys

| Request | What it does |
| - | - |
| `GET /api/v1/api-keys` | Your keys, without the tokens themselves. Paged with `offset` and `limit` (see [Pagination](/reference/pagination)) |
| `DELETE /api/v1/api-keys/{pk_id}` | Revokes the key at once. Returns `{ "object": "ApiKeyDeleted", "id": "pk_…" }` |

```bash theme={null}
curl -X DELETE "$EE_URL/api/v1/api-keys/pk_0f1e2d3c4b5a69788796a5b4c3d2e1f0" -H "X-API-KEY: $EE_KEY"
```

Each key in the list has these fields:

| Field | |
| - | - |
| `id` | The key's `pk_…` id |
| `name` | Your name for it |
| `prefix` | The first characters of the token, so you can recognise it |
| `role` | Always `service` |
| `issued_at` | When it was created |
| `last_used_at` | When it was last used, or `null` |

## Public endpoints

A few paths are reached by your users' browsers, so they don't take an access token. Each is protected in its own way:

| Path | Used by | Protected by |
| - | - | - |
| `/t/{id}/o.gif`, `/t/{id}/c` | Open and click tracking | Link signatures (no open redirect) |
| `/up` | Health checks | Nothing sensitive (returns `ok`) |

<Warning>
  Keep access tokens on your server. Never put them in a browser or mobile app: anyone with a token can read every connected mailbox.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.