# API authentication and your first request

> Create a scoped access token, make your first call to the Broadcast API, and handle permissions, errors and rate limits correctly.

Source: https://sendbroadcast.net/university/developers/api-authentication

The Broadcast API lets your own code do what you do in the dashboard. In this lesson you create a token with only the permissions it needs, make your first request, and learn how the API reports errors and limits. Every later lesson in this course builds on this one.

## Where the API lives

The API runs on your own installation, under `/api/v1`. If your dashboard is at `https://broadcast.example.com`, the subscribers endpoint is `https://broadcast.example.com/api/v1/subscribers.json`. There is no shared cloud endpoint. Your data never leaves your server on the way to your app.

## Step 1: Create a scoped token

Tokens belong to one channel and can only see that channel. To create one:

1. Open **Access Tokens** in the sidebar.
2. Click **New Token**.
3. Give it a name that says where it is used, such as "Website signup form".
4. Tick only the permissions it needs.
5. Click **Create token**.

![The New Access Token form with a Token name field and a table of resources with Read and Write checkboxes](https://sendbroadcast.net/assets/docs/api-authentication/api-authentication-new-token-4d9fc7d8.png)

Read and Write are separate checkboxes for each resource.

Each resource has two permissions, **Read** and **Write**, set on their own. Resources include Broadcasts, Transactional Emails, Templates, Subscribers, Sequences, Segments, Webhook Endpoints, Suppressions and more.

Warning

**Write does not imply read.** A token with only Write for Segments can create a segment and then get a `401` when it lists segments. If your code reads and writes, tick both.

Keep the scope small. A token for your signup form needs Subscribers write and nothing else. If it leaks, the damage stays small. Store tokens in environment variables, never in code or version control.

A fresh install already has one token, with transactional email permissions.

![The Access Tokens page with one token, Default transactional email, its masked value and a Transactional permission badge](https://sendbroadcast.net/assets/docs/api-authentication/api-authentication-tokens-index-1835d634.png)

A new channel, with its default token.

## Step 2: Make your first request

Send the token in the `Authorization` header of every request:

```bash
curl "https://broadcast.example.com/api/v1/subscribers.json?page=1" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
```

The response has a `subscribers` array and a `pagination` object with `total`, `current` and `total_pages`. Ask for the next page with `page=2`.

To check one person, use the find endpoint:

```bash
curl "https://broadcast.example.com/api/v1/subscribers/find.json?email=ada@example.com" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

If both calls return JSON, your token, permissions and network path all work.

## Read the status code

| Code | Meaning |
|---|---|
| `400` | A parameter could not be read, or the combination cannot be satisfied. |
| `401` | The token is missing, wrong or expired, or lacks the read or write permission for this endpoint. |
| `403` | The endpoint needs an admin API token, or a limit was reached. |
| `422` | The request was understood but the data is not valid. The body has the message. |
| `429` | You hit the rate limit. |

When you see a `401` on a token you know works, check the permission first. It is the most common cause.

## Dates are ISO 8601

Send dates as `2026-01-24` and timestamps as `2026-01-24T09:30:00Z`. Broadcast does not accept locale formats such as `01/02/2026`, because nothing says which month you meant.

## Warnings: read them

Some list filters do not reject a value they cannot read. They ignore it, answer the rest of the query, and add a `parameter_ignored` entry to a `warnings` array in the response. An ignored filter returns **more** rows than you asked for, not fewer. Check that array in your code. See [API response warnings](/docs/api-response-warnings).

## Rate limits

Each token gets 1,200 requests per minute by default, counted per token, so one busy integration never slows another. A token can set its own limit in its **Rate limit (requests per minute)** field.

Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. A `429` also carries `Retry-After`, in seconds. Wait that long, then retry with exponential backoff.

## Admin tokens: only when you must

A script that works across several channels needs an **admin API token**, created under **Application → Admin API Tokens**. Every channel request with an admin token must name its channel with a `broadcast_channel_id` query parameter, or it fails with `400`.

An admin token reaches every channel, can manage users, and can read the migration export with server credentials in it. Treat it like a database backup. Use a channel token wherever one will do.

### Channel token

- Sees one channel
- Permissions you tick, per resource
- Created under Access Tokens

### Admin API token

- Reaches every channel and can manage users
- Needs `broadcast_channel_id` on channel requests
- Created under Application, Admin API Tokens

Use a channel token wherever one will do.

## Get the exact spec for your version

Your installation serves an OpenAPI 3.1 description of its own API at `GET /api/v1/openapi`, with a token like any other call. It is generated from your running version, so it lists exactly the endpoints your server accepts. Import it into Postman or Insomnia, or generate a client from it. See [API authentication](/docs/api-authentication).

## What you learned

- Create one token per integration, in its channel, with only the permissions it needs.
- Send `Authorization: Bearer ` on every request to `/api/v1` on your own domain. - A `401` on a working token usually means a missing read or write permission. - Respect the 1,200 per minute default, `Retry-After`, and the `warnings` array.

## Quiz
1. A token has Write ticked for Segments but not Read. It creates a segment, then lists segments. What happens?
   - The list works, write includes read
   - The list returns 401, because write does not imply read (correct)
   - The list returns an empty array
   For almost every resource, read and write are checked on their own. Tick both if the integration needs both.
2. How many requests per minute does a token get by default?
   - 60
   - 600
   - 1,200 (correct)
   - Unlimited
   The default limit is 1,200 requests per minute per token, unless the token sets its own limit.
3. Which channel does a channel access token reach?
   - Only the channel it was created in (correct)
   - Every channel in the installation
   - The channel named in each request
   A channel token is scoped to one channel. Only an admin API token can reach several channels.
