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

# API keys

> Create platform API keys in the dashboard, choose their scopes, and set expiry, IP allowlists and rate limits. Rotate, revoke and read request logs.

export const Screenshot = ({id, src, srcDark, alt, caption}) => {
  if (!src) {
    return <Placeholder id={id} kind="screenshot" label="Screenshot coming soon" description={alt} icon={<ImageIcon />} />;
  }
  return <figure className="brd-media" data-media-id={id}>
      <img className="brd-media-frame block dark:hidden" src={src} alt={alt} />
      <img className="brd-media-frame hidden dark:block" src={srcDark || src} alt={alt} />
      {caption && <figcaption className="brd-media-caption">{caption}</figcaption>}
    </figure>;
};

An API key lets your code call the platform API for one organization, with the permissions you
choose.

<Screenshot id="ss-developers-api-keys-hero" alt="The API Keys page showing Total Keys, Active and Requests (24h) above the list of keys" />

<Info>
  API keys are managed in the dashboard only. The platform API can't create, rotate or revoke keys,
  so a leaked key can never create another.
</Info>

## Create a key

<Steps>
  <Step title="Open the create panel">
    Go to **Developers > API Keys** and select **Create API Key**.
  </Step>

  <Step title="Name the key">
    Enter a **Key Name** (up to 255 characters) that says where the key will live, such as
    `Production backend`. Add a **Description (optional)** if it helps your team.
  </Step>

  <Step title="Choose an expiration">
    Pick **Never**, **30 days**, **90 days**, **6 months** or **1 year**. After that date the key
    stops working.
  </Step>

  <Step title="Set permissions">
    For each group under **Permissions**, choose **No access**, read-only access, or
    **Full access**. **Full access** grants both the read and the write scope for that group. You
    need at least one.

    <Screenshot id="ss-developers-api-keys-01-permissions" alt="The Permissions list in the Create API Key panel, with a dropdown per group" />
  </Step>

  <Step title="Restrict IP addresses (optional)">
    In **IP Allowlist (optional)**, enter the IP addresses allowed to use the key, separated by
    commas. Leave it empty to allow any address.

    <Warning>
      Enter individual addresses, such as `203.0.113.10`. Each request's address is compared
      exactly, so a range such as `203.0.113.0/24` won't match anything.
    </Warning>
  </Step>

  <Step title="Create and copy the secret">
    Select **Create**. The panel shows the **Key ID** and the **Secret Key**. Copy the secret key
    now: it's shown only once. The key ID isn't secret. Use it to find the key in logs and in the
    dashboard.
  </Step>
</Steps>

## Scopes

There are 18 scopes: a read scope and a write scope for each of nine groups. The dashboard shows
the group names and the read-access labels below.

| Group                 | Read scope                             | Write scope                                   | Covers                                                                                                             |
| --------------------- | -------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Messages**          | `messages:read` (**Read Message Log**) | `messages:send` (**Send Messages**)           | The message log. The write scope also lets the key send through the [email send API](/developers/sending/http-api) |
| **Contacts**          | `contacts:read`                        | `contacts:write`                              | Contacts, lists, tags, custom fields, segments, imports, exports and suppressions                                  |
| **Campaigns**         | `campaigns:read`                       | `campaigns:write`                             | Campaigns, their content, audiences, schedules and send actions                                                    |
| **Templates**         | `templates:read`                       | `templates:write`                             | Message templates                                                                                                  |
| **Analytics**         | `analytics:read` (**Read Analytics**)  | `analytics:write` (**Create Report Exports**) | Reports, dashboard figures and report exports                                                                      |
| **Webhooks**          | `webhooks:read`                        | `webhooks:write`                              | Webhook endpoints and their deliveries                                                                             |
| **Sending Domains**   | `domains:read`                         | `domains:write`                               | Sending domains, IP pools and IP pool requests. Not sending keys or SMTP users                                     |
| **Sender Identities** | `senders:read`                         | `senders:write`                               | Sender identities and push applications                                                                            |
| **Mailboxes**         | `mailboxes:read`                       | `mailboxes:write`                             | Mailboxes, aliases and mail domains                                                                                |

How a scope is chosen for a request:

* `GET` requests need the group's read scope.
* `POST`, `PATCH`, `PUT` and `DELETE` requests need the write scope. That includes action
  endpoints that only read, such as previewing a campaign or a contact import.

A request without the right scope fails with `403`. The response names the missing scope and lists
the ones the key has:

```json theme={"system"}
{
  "success": false,
  "message": "This API key is missing the contacts:write scope required by this endpoint. Issue a key that carries it to continue.",
  "code": "E_INSUFFICIENT_SCOPE",
  "requiredScope": "contacts:write",
  "grantedScopes": ["contacts:read", "messages:read"]
}
```

<Note>
  Older keys may hold `email:send` and `email:read`. These are the previous names of
  `messages:send` and `messages:read`, and they still work. See the
  [changelog](/developers/changelog#api-key-scopes-renamed).
</Note>

### The Send Messages permission

A key with **Send Messages** also works on the email send API, where it can send from any sending
domain your organization owns. You can remove the permission from a key later. You can't add it to
an existing key: create a new key instead.

## Rate limits

Each key has its own limits, so one busy integration can't use up another's budget.

| Limit               | Default      | Where to change it                                            |
| ------------------- | ------------ | ------------------------------------------------------------- |
| Requests per minute | 300          | **Settings** tab, **Rate Limits**: 60, 120, 300, 600 or 1,200 |
| Requests per day    | No daily cap | **Settings** tab, **Rate Limits**: 10,000 to 1,000,000        |

A request over either limit fails with `429`. See [Rate limits](/developers/rate-limits) for the
headers and how to retry.

## Manage a key

Select a key in **Developers > API Keys** to open it. It has three tabs:

| Tab          | What's there                                                                                                                                               |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Overview** | **Key Information** (key ID, the masked key, created, last used, expiry), **Permissions**, **Recent Requests** (the last five) and **Access Restrictions** |
| **Usage**    | **Usage Overview** and the full **Request Logs**                                                                                                           |
| **Settings** | **Key Details**, **Security** (the IP allowlist), **Rate Limits**, **Expiration** and the **Danger Zone**                                                  |

To change the name, description or IP allowlist, select **Edit** on **Key Information**. To change
scopes, select **Edit** on **Permissions**. To change the expiry, use **Expiration** on the
**Settings** tab.

### Rotate a key

1. On the **Overview** tab, select the regenerate icon next to the masked key.
2. Confirm with **Regenerate**.
3. Copy the new secret. It's shown once.

The old secret stops working immediately. The key keeps its ID, scopes and limits.

<Tip>
  For a rotation without downtime, create a second key with the same permissions, deploy it,
  then revoke the first.
</Tip>

### Revoke a key

On the **Settings** tab, under **Danger Zone**, select **Revoke Key** and confirm. Every request
using the key fails from then on, including sends through the email send API. You can't undo this.

## Request logs

The **Usage** tab lists every request made with the key, newest first. Each entry has the
**Method**, **Endpoint**, **Status**, **Time**, **IP Address** and **Timestamp**. Filter by method
or by status code to find failures.

<Screenshot id="ss-developers-api-keys-02-request-logs" alt="The Request Logs table on the Usage tab, filtered to 4xx status codes" />

Only requests that authenticated with the key are logged. A request rejected as
`Unauthorized access` never matched the key, so it won't appear here.

## Key statuses

| Status    | Shown as    | Meaning                                                                     |
| --------- | ----------- | --------------------------------------------------------------------------- |
| `active`  | **Active**  | The key works                                                               |
| `expired` | **Expired** | The expiry date has passed. Requests are rejected                           |
| `revoked` | **Revoked** | Someone revoked the key, or the member who created it left the organization |

<AccordionGroup>
  <Accordion title="“Unauthorized access”" icon="circle-alert">
    **Why:** The key is wrong, revoked or expired, or the request came from an IP address that
    isn't on the key's allowlist.

    **Fix:** Check the key's status and allowlist. If your servers' addresses change, remove the
    allowlist or keep it up to date.
  </Accordion>

  <Accordion title="“This API key is missing the … scope required by this endpoint”" icon="circle-alert">
    **Why:** The key doesn't have the scope in `requiredScope`.

    **Fix:** Select **Edit** on the key's **Permissions** and add it. For `messages:send`, create
    a new key instead.
  </Accordion>

  <Accordion title="“The &#x22;messages:send&#x22; scope cannot be added to an existing API key”" icon="circle-alert">
    **Why:** The send API can only receive a key when it's created or regenerated.

    **Fix:** Create a new key with **Messages** set to **Full access**.
  </Accordion>

  <Accordion title="“This endpoint cannot be accessed with an API key”" icon="circle-alert">
    **Why:** Key management, billing, the wallet and a few other areas are dashboard-only.

    **Fix:** Do this in the dashboard.
  </Accordion>
</AccordionGroup>

## Related

<Columns cols={2}>
  <Card title="Authentication" icon="shield" href="/developers/authentication">
    How to send the key, and which credential works where.
  </Card>

  <Card title="Sending keys" icon="send" href="/developers/sending-keys">
    The separate credential the email send API needs.
  </Card>

  <Card title="Rate limits" icon="gauge" href="/developers/rate-limits">
    Per-key limits, headers and retries.
  </Card>

  <Card title="Errors" icon="circle-alert" href="/developers/errors">
    Error codes and what to do.
  </Card>
</Columns>
