# API Authentication

> Learn how to create and manage API access tokens to authenticate your requests to the Broadcast API.

Source: https://sendbroadcast.net/docs/api-authentication

Access tokens authenticate your requests to the Broadcast API. Each token can be configured with specific permissions to control what actions it can perform.

![Access Tokens index page showing a list of API tokens](https://sendbroadcast.net/assets/docs/api-authentication/api-authentication-tokens-index-1835d634.png)

## How Access Tokens Work

Access tokens are API keys that:

- Authenticate requests to the Broadcast API
- Control access through granular permissions
- Can be created, refreshed, and revoked at any time
- Are scoped to a specific broadcast channel

When you install Broadcast, a default access token is created with transactional email permissions. You can create additional tokens with different permission sets for various use cases.

## Creating an Access Token

To create a new access token:

1. Navigate to **Access Tokens** in the sidebar
2. Click **New Token**
3. Enter a descriptive name (e.g., "Production API", "Transactional emails")
4. Select the permissions this token needs
5. Click **Create token**

![New access token form showing permission options](https://sendbroadcast.net/assets/docs/api-authentication/api-authentication-new-token-4d9fc7d8.png)

### Token Permissions

Each resource type has two permission levels:

| Permission | Description |
|------------|-------------|
| **Read** | List and view resources |
| **Write** | Create, update, and delete resources |

You can set permissions independently for each of these eleven resources:

![Token permissions table listing all eleven resources with read and write checkboxes](https://sendbroadcast.net/assets/docs/api-authentication/token-permissions-table-39199e48.png)

| Resource | Description | Documentation |
|----------|-------------|---------------|
| Broadcasts | Email campaigns and scheduling | [Broadcasts API](https://sendbroadcast.net/docs/api-broadcasts) |
| Transactional Emails | Send one-off emails via API | [Transactional Email API](https://sendbroadcast.net/docs/api-transactional-email) |
| Templates | Reusable email templates | [Templates API](https://sendbroadcast.net/docs/api-templates) |
| Subscribers | Manage contacts and their data | [Subscribers API](https://sendbroadcast.net/docs/api-subscribers) |
| Sequences | Automated email workflows | [Sequences API](https://sendbroadcast.net/docs/api-sequences) |
| Segments | Subscriber groups and filters | [Segments API](https://sendbroadcast.net/docs/api-segments) |
| Email Servers | SMTP and delivery settings | [Email Servers API](https://sendbroadcast.net/docs/api-email-servers) |
| Webhook Endpoints | Outgoing webhook configurations | [Webhook Endpoints API](https://sendbroadcast.net/docs/api-webhook-endpoints) |
| Autopilot | AI-generated newsletters | [Autopilots API](https://sendbroadcast.net/docs/api-autopilots) |
| Suppressions | This channel's suppression list | [Suppressions API](https://sendbroadcast.net/docs/api-suppressions) |
| Opt-In Forms | Subscription forms and widgets | [Opt-In Forms API](https://sendbroadcast.net/docs/api-opt-in-forms) |

Warning

**Write does not imply read.** For almost every resource the two are checked independently, so a token with only write ticked can create a segment and then get a `401` trying to list segments. If an integration both reads and writes, tick both boxes. Autopilot is the one exception: there, write satisfies read.

**Best practice:** Create tokens with only the permissions they need. A token for sending transactional emails doesn't need access to broadcasts or segments.

### Quick Permission Selection

When creating or editing a token, use the quick selection buttons:

- **All** - Enable all read and write permissions
- **Read only** - Enable only read permissions for all resources
- **None** - Disable all permissions

## Admin API Tokens

The tokens described above belong to one channel and can only ever see that channel. When an integration has to reach several channels, for example a provisioning script or a reporting job that runs across an installation, use an **admin API token** instead.

Create them under **Application → Admin API Tokens**.

![Admin API tokens list showing a token with masked value, permission badges, and last-used state](https://sendbroadcast.net/assets/docs/api-authentication/admin-api-tokens-a4657edb.png)

Admin tokens carry the same eleven permissions as channel tokens, plus one only they have: **Users**, for the [Users API](https://sendbroadcast.net/docs/api-users). People can sign in to the whole installation, so no channel token can ever manage them. What differs otherwise is scope, and one requirement that follows from it.

Admin tokens are also the only tokens that can read the [Migration API](https://sendbroadcast.net/docs/api-migration), the read-only export used to move a channel to another server. That export includes email server credentials and channel token values, so any admin token is as sensitive as a database backup.

### Every channel-scoped request needs `broadcast_channel_id`

Because an admin token is not tied to a channel, it has to be told which channel each request is for. Send `broadcast_channel_id` as a query parameter. (The Users API is the exception: users belong to the installation, not a channel, so those endpoints don't need it.)

```bash
curl -X GET "https://your-broadcast-domain.com/api/v1/subscribers?broadcast_channel_id=3" \
  -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \
  -H "Content-Type: application/json"
```

Omit it and the request fails immediately:

```json
{
  "error": "broadcast_channel_id is required for admin API tokens"
}
```

That is a `400 Bad Request`. A channel id that does not exist returns `404` with `Broadcast channel not found`.

### When to use which

| Use a channel token when | Use an admin token when |
|--------------------------|-------------------------|
| The integration serves one newsletter or brand | A script provisions or reports across channels |
| You want the blast radius limited to that channel | You are writing to the global suppression list |
| | You are creating users or managing their permissions |

Warning

An admin token can reach every channel in the installation, so it is the most valuable credential Broadcast issues. Prefer a channel token wherever one will do, and keep admin tokens to the specific jobs that genuinely need to cross channels.

Every request made with an admin token is written to the application log with the token id and the channel it accessed, so there is an audit trail. See [Monitoring and Logs](https://sendbroadcast.net/docs/monitoring-and-logs).

## Using an Access Token

Include your access token in the `Authorization` header of every API request:

```
Authorization: Bearer YOUR_ACCESS_TOKEN
```

### Example Request

```bash
curl -X GET "https://your-broadcast-instance.com/api/v1/subscribers" \
  -H "Authorization: Bearer 8779fc02262b9701fe0fff82f1eec8b9" \
  -H "Content-Type: application/json"
```

### Error Responses

| Status Code | Description |
|-------------|-------------|
| 400 Bad Request | A parameter could not be read, or the combination cannot be satisfied |
| 401 Unauthorized | Missing, invalid or expired token, or the token lacks the read or write permission the endpoint needs |
| 403 Forbidden | The endpoint needs an admin API token, the target is a sudo user (read-only through the [Users API](https://sendbroadcast.net/docs/api-users)), or a plan limit was reached |
| 429 Too Many Requests | Rate limit exceeded |

## Dates and Times

Send every date and timestamp as ISO 8601, and expect the same format back:

| Kind | Format | Example |
|------|--------|---------|
| Date | `YYYY-MM-DD` | `2026-01-24` |
| Timestamp | `YYYY-MM-DDTHH:MM:SSZ` | `2026-01-24T09:30:00Z` |

Either form is accepted wherever a date or timestamp is expected: a bare date is
read as midnight, and a timestamp given to a date parameter contributes its date
part. Unix seconds work too. A value carrying no timezone is read in your
instance's configured timezone.

Locale date formats are not part of the API. This is deliberate rather than fussy:
`01/02/2026` is the 1st of February in most of the world and the 2nd of January in
the United States, and nothing in the request says which one you meant. An API that
guesses hands a different month's data to half its callers with no error to signal
it, so Broadcast asks for the unambiguous form instead.

Note

The same reasoning applies to the data you import. If a subscriber’s custom field holds `24/01/2025`, segment rules that compare it as a date cannot use it: store dates as `2025-01-24` and they work everywhere, including segments, exports, and Liquid templates.

What happens to a value that cannot be read depends on what the parameter does, and
each endpoint's reference page says which applies:

- A parameter that **changes data** rejects the request, so nothing is written from
  a value the server had to guess at.
- A parameter that **filters a list** may instead ignore the value and answer the
  rest of the query, reporting a `parameter_ignored` entry in the response's
  `warnings` array. Check that array rather than assuming every filter you sent was
  applied: an ignored filter returns *more* rows than you asked for, not fewer. See
  [API Response Warnings](https://sendbroadcast.net/docs/api-response-warnings).

## Rate Limiting

The API enforces rate limiting to protect against abuse and ensure fair usage for all users.

### Limits

| Scope | Limit |
|-------|-------|
| Per API token | 1,200 requests per minute, unless the token sets its own |

Each API token is counted separately, so one busy integration never slows down another.

#### Setting a limit on one token

Channel tokens and admin API tokens both have an optional **Rate limit (requests per minute)** field, from 1 to 100,000. Use it to give a busy integration or an AI agent more headroom, or to hold a third-party integration to less. Leave it blank to use the installation default. A change applies to the token's next request, with no restart.

#### Changing the default

The default applies to every token without its own limit. Set it with the `API_RATE_LIMIT` environment variable (requests per minute) and restart Broadcast. For example:

```
API_RATE_LIMIT=600
```

`X-RateLimit-Limit` always reports the limit in effect for the token making the request, and so does `rate_limit.requests_per_minute` in the [Agents API](https://sendbroadcast.net/docs/api-agents) `prime` response.

Note

A tool call through the MCP server counts once against the token’s limit, even though it makes an API request on your behalf.

### Rate Limit Headers

Every API response includes rate limit headers so you can monitor your usage:

| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Maximum requests allowed per period |
| `X-RateLimit-Remaining` | Requests remaining in current period |
| `X-RateLimit-Reset` | ISO 8601 timestamp when the limit resets |

When you receive a `429 Too Many Requests` response, the following additional header is included:

| Header | Description |
|--------|-------------|
| `Retry-After` | Seconds until you can retry |

### Example Rate Limited Response

```json
{
  "error": "Rate limit exceeded. Please retry later."
}
```

### Handling Rate Limits

When you receive a `429` response:

1. Check the `Retry-After` header for how long to wait
2. Implement exponential backoff in your retry logic
3. Consider batching requests where possible
4. Use multiple tokens if you need higher throughput

```ruby
# Example retry logic
def make_api_request
  response = api_call

  if response.status == 429
    retry_after = response.headers['Retry-After'].to_i
    sleep(retry_after)
    retry
  end

  response
end
```

## Viewing Token Details

Click any token in the list to view its details:

![Token detail modal showing the full API token and permissions](https://sendbroadcast.net/assets/docs/api-authentication/api-authentication-token-detail-35823440.png)

The detail view shows:

- **Full token value** - Click **Copy** to copy to clipboard
- **Permissions** - What this token can access
- **Usage stats** - When the token was created and last used

## Managing Access Tokens

### Refreshing Tokens

You can regenerate a token's value while keeping its permissions:

1. Click on the token you want to refresh
2. Click **Refresh**
3. Confirm the refresh
4. Copy the new token value

**Warning:** Refreshing a token immediately invalidates the old value. Update all applications using this token before refreshing.

### Editing Permissions

To change a token's permissions:

1. Click on the token
2. Click **Edit permissions**
3. Update the permission checkboxes
4. Click **Update token**

### Deleting Tokens

To revoke a token permanently:

1. Click the delete button (trash icon) next to the token
2. Confirm the deletion

Deleted tokens cannot be recovered. Any applications using the deleted token will immediately lose access.

## OpenAPI Specification

Your installation serves a machine-readable OpenAPI 3.1 description of its own API:

```
GET /api/v1/openapi
```

It needs a token like any other endpoint, and returns YAML:

```bash
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://your-broadcast-domain.com/api/v1/openapi > broadcast-api.yaml
```

`/api/v1/openapi.yaml` works identically, for tooling that insists on a file extension.

Use it to generate a client library, import the API into Postman or Insomnia, or point an API explorer at it. The document names your own installation as its server, so requests work as soon as you add a token, with no editing.

Note

The spec is generated from the running application’s routing table, so it describes **your** version rather than the latest release. Fetching it from the installation you are integrating against is the reliable way to see exactly which endpoints and parameters that installation accepts.

## Security Best Practices

1. **Use descriptive names** - Make it easy to identify what each token is used for
2. **Minimize permissions** - Only grant the permissions each token actually needs
3. **Rotate regularly** - Refresh tokens periodically, especially after team changes
4. **Never commit tokens** - Keep tokens out of version control and public repositories
5. **Use environment variables** - Store tokens in environment variables, not in code
6. **Monitor usage** - Check the "last used" timestamp to identify unused tokens
7. **Revoke unused tokens** - Delete tokens that are no longer needed

## Common Use Cases

### Transactional Emails Only

For sending transactional emails (password resets, receipts, etc.):
- Transactional Emails: Read + Write

### Subscriber Management Integration

For syncing subscribers from another system:
- Subscribers: Read + Write
- Segments: Read (optional, to assign subscribers to segments)

### Read-Only Dashboard

For a reporting dashboard that displays metrics:
- Broadcasts: Read
- Subscribers: Read
- Sequences: Read

### Full API Access

For admin tools that need complete access:
- All resources: Read + Write

**Note:** Only use full access tokens when absolutely necessary.
