# API Keys

> API reference for managing Warmerly API keys programmatically: create, list, and revoke keys used to authenticate requests to the Warmerly API.

Source: https://warmerly.com/docs/keys

Manage the API keys used to authenticate requests to the Warmerly API. This page covers creating, listing, and revoking keys programmatically. If you're looking for how to use a key you already have, see [Authentication](https://warmerly.com/docs/authentication).

Key management endpoints are not project-scoped: they only need `X-Api-Key`, not `X-Project-Id`.

**API access is an Agency-plan feature.** Listing and creating keys returns `403 agency_plan_required` on any workspace that is not on Agency; upgrade at [warmerly.com/pricing](https://warmerly.com/pricing). Revoking a key is not plan-gated, so you can still revoke from the dashboard after a downgrade. A request authenticated with an API key, including a revoke, is plan-checked like any other and gets `403 agency_plan_required` until the workspace is back on Agency.

## List keys

```text
GET /keys
```

Returns all of your active (non-revoked) keys, newest first. The raw secret is never returned, only the id, name, prefix, rate limit, and usage metadata.

```bash
curl https://app.warmerly.com/api/v1/keys \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

```json
{
  "keys": [
    {
      "id": "3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b",
      "name": "CI pipeline",
      "prefix": "wmv_7f3a2c",
      "rateLimitPerMin": 60,
      "lastUsedAt": "2026-07-01T09:12:44.000Z",
      "createdAt": "2026-06-20T14:03:11.000Z"
    },
    {
      "id": "9a2d4c11-5e7b-4f10-b2aa-1c8f0d3e6a4b",
      "name": "Zapier",
      "prefix": "wmv_9d1e0b",
      "rateLimitPerMin": 120,
      "lastUsedAt": null,
      "createdAt": "2026-06-18T08:47:02.000Z"
    }
  ]
}
```

| Field | Type | Description |
| --- | --- | --- |
| `id` | string (UUID) | Key ID, use this to revoke the key. |
| `name` | string | The label you gave the key when creating it. |
| `prefix` | string | The first few characters of the key (`wmv_...`), useful for identifying which key is which without exposing the secret. |
| `rateLimitPerMin` | number | Requests per minute allowed for this key. |
| `lastUsedAt` | string \\| null | ISO 8601 timestamp of the key's most recent authenticated request, or `null` if it has never been used. |
| `createdAt` | string | ISO 8601 timestamp of when the key was created. |

Revoked keys are excluded from this list entirely.

## Create a key

```text
POST /keys
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string (1-120 chars) | Yes | A label to help you identify the key later. |
| `rateLimitPerMin` | integer (1-120) | No | Requests per minute allowed for this key. Defaults to `60`, capped at `120` regardless of plan. |

Each user can hold at most **10 active keys**; creating an 11th (without revoking one first) returns `400` with `error.code` `bad_request`, `error.message` `too_many_keys` and `error.details` `{ "max": 10 }`.

```bash
curl -X POST https://app.warmerly.com/api/v1/keys \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "CI pipeline", "rateLimitPerMin": 100 }'
```

```json
{
  "key": "wmv_7f3a2cdb9e1a4f0c8b6d2e5f7a1c3b9d",
  "id": "3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b",
  "prefix": "wmv_7f3a2c",
  "name": "CI pipeline"
}
```

**The `key` field is the only time the raw secret is ever returned.** Warmerly stores only a hash of the key, copy it and store it securely immediately. If you lose it, there is no way to recover it; revoke the key and create a new one instead.

A response with HTTP status `201` confirms the key was created.

### Validation errors

An invalid body (missing `name`, `name` over 120 characters, or `rateLimitPerMin` outside `1` to `120`) returns `400`:

```json
{ "error": { "code": "bad_request", "message": "invalid_body", "details": { /* field errors */ } } }
```

## Revoke a key

```text
DELETE /keys/{id}
```

Revokes (soft-deletes) the key. Revoked keys fail authentication immediately on their next request, there is no grace period, and revocation cannot be undone.

```bash
curl -X DELETE https://app.warmerly.com/api/v1/keys/3b1f6e2a-9c4d-4e2a-8b5f-6a2c1d9e0f7b \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

```json
{ "revoked": true }
```

If the key doesn't exist, doesn't belong to you, or has already been revoked, this returns `404`:

```json
{ "error": { "code": "not_found", "message": "not_found", "details": null } }
```

You can revoke the key you're currently authenticating with. The revocation takes effect immediately, so any subsequent request with that key (including further calls in the same script) will fail with `401 unauthorized`.

## Each part of this reference has its own page (3)

- [List keys](https://warmerly.com/docs/keys/list-keys)
- [Create a key](https://warmerly.com/docs/keys/create-a-key)
- [Revoke a key](https://warmerly.com/docs/keys/revoke-a-key)

## More in API reference

- [Webhooks](https://warmerly.com/docs/webhooks): API reference for Warmerly webhook subscriptions: get HTTP-signed notifications for mailbox health events…
- [Workspaces & Projects](https://warmerly.com/docs/workspaces): API reference for Warmerly workspaces and projects: the tenant/billing hierarchy that mailboxes, campaigns,…
- [Usage & Limits](https://warmerly.com/docs/usage): Read every monthly allowance and every plan limit for a Warmerly workspace over HTTP: GET /usage/quotas for…
