Users API
The Users API manages the people who sign in to Broadcast: the same accounts you see under User Management. Use it to provision a team when you migrate from another platform, to keep Broadcast in step with your own staff directory, or to remove access when someone leaves.
It covers three things:
- Users at
/api/v1/users: create, update, deactivate, activate and delete - Channel permissions at
/api/v1/users/{id}/channel_permissions: what a user can do on each channel, set with individual flags, a built-in role or a saved preset - System permissions at
/api/v1/users/{id}/system_permissions: installation-wide abilities such as user management or system settings
For what each role and permission means, see Users & Permissions.
Authentication and permissions
Every Users API endpoint requires an admin API token. A channel token gets
403 Forbidden, because a user can sign in to the whole installation, not just
one channel.
Warning
Admin tokens only. A channel token is rejected with:
{ "error": "Admin API token required for user management" }
The admin token also needs the Users permission:
- Read for
GETendpoints - Write for everything else
A token without the right permission gets 401 Unauthorized. Tick the Users
row when you create or edit the token under Application → Admin API Tokens.
See API Authentication.
Unlike other admin token requests, these endpoints do not need
broadcast_channel_id. If your SDK client sends one because it is configured
with a default channel, it is ignored.
Sudo users are read-only
Sudo access can never be granted or removed through the API, and users who already have sudo access are read-only here. Updating, deactivating, activating or deleting a sudo user, or changing their permissions, returns:
{ "error": "Sudo users cannot be changed through the API" }
That is a 403 Forbidden. The rule includes users whose sudo access comes from
their system permissions. Changing a sudo user’s email address or password would
hand over the most powerful account on the installation, so those changes are
made in the web interface by another sudo user.
Note
You can still read sudo users. The sudo field on every user tells you
whether they have sudo access, however it was granted.
User Object
| Field | Description |
|---|---|
id |
Unique identifier. Use it in every /api/v1/users/{id} path. |
email |
Sign-in email address |
first_name |
First name |
last_name |
Last name |
active |
false when the user has been deactivated and cannot sign in |
locked |
true when the account is locked after too many failed sign-ins |
sudo |
Whether the user has sudo access |
two_factor_enabled |
Whether two-factor authentication is on |
last_login_at |
Last successful sign-in, or null |
created_at |
When the user was created |
updated_at |
When the user was last changed |
Single-user responses (get, create, update, deactivate and activate) also
include system_permissions and channel_permissions, described below.
List Users
GET /api/v1/users
Query Parameters
q(optional): Matches email address, first name or last namestatus(optional):activeorinactive. Any other value returns422.limit(optional): Maximum number of users to return, from 1 to 1000offset(optional): Number of users to skip, 0 or more
A limit or offset outside those ranges, or that is not a whole number, returns 422 Unprocessable Entity.
Request
curl -X GET "https://your-broadcast-domain.com/api/v1/users?status=active&limit=25" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
Response
{ "data": [ { "id": 7, "email": "daniel.meyer@example.com", "first_name": "Daniel", "last_name": "Meyer", "active": true, "locked": false, "sudo": false, "two_factor_enabled": false, "last_login_at": "2026-09-15T08:12:44Z", "created_at": "2026-09-01T10:00:00Z", "updated_at": "2026-09-15T08:12:44Z" } ], "total": 1 }
total counts every user matching the filters, not just the ones on this page.
Get User
GET /api/v1/users/{id}
Request
curl -X GET "https://your-broadcast-domain.com/api/v1/users/7" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
Response
{ "id": 7, "email": "daniel.meyer@example.com", "first_name": "Daniel", "last_name": "Meyer", "active": true, "locked": false, "sudo": false, "two_factor_enabled": false, "last_login_at": "2026-09-15T08:12:44Z", "created_at": "2026-09-01T10:00:00Z", "updated_at": "2026-09-15T08:12:44Z", "system_permissions": { "user_management": false, "channel_management": false, "system_settings": false, "system_monitoring": true, "system_backups": false, "system_updates": false, "billing_management": false }, "channel_permissions": [ { "broadcast_channel_id": 3, "broadcast_channel_name": "Product Updates", "role": "Editor", "permissions": { "subscribers_read": true, "subscribers_write": true, "broadcasts_send": false }, "created_at": "2026-09-01T10:05:00Z", "updated_at": "2026-09-01T10:05:00Z" } ] }
The permissions object lists every channel permission flag. It is shortened
here.
Create User
POST /api/v1/users
A new user needs a way to sign in. Either set a password, or set
send_password_reset to true and Broadcast emails them a link to choose their
own. One of the two is required.
Parameters
user[email](required): Sign-in email addressuser[first_name](required)user[last_name](required)user[password](optional): The user’s passworduser[send_password_reset](optional):trueto email a password-reset link instead of setting a password
Request
curl -X POST "https://your-broadcast-domain.com/api/v1/users" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": { "email": "daniel.meyer@example.com", "first_name": "Daniel", "last_name": "Meyer", "send_password_reset": true } }'
Response
201 Created with the full user, including empty channel_permissions. A new
user can’t see any channel until you grant access, so follow up with
Set Channel Permissions or
Bulk Apply Channel Permissions.
Note
The password-reset link expires after two hours. If it lapses, the user can request a new one from the sign-in page.
A missing password and reset flag, or an email address already in use, returns
422:
{ "error": "Email has already been taken" }
Requests that are rejected, not ignored
Create and update refuse keys that ask for something these endpoints will not
do. The request fails with 422, nothing in it is applied, and the message
tells you where to go instead:
Key in user |
Why it is rejected |
|---|---|
sudo, sudo_access |
Sudo access can’t be granted through the API |
active, is_active |
Use Deactivate User or Activate User |
system_permissions |
Use Update System Permissions |
channel_permissions, role, preset_id, permissions |
Use Set Channel Permissions or Bulk Apply Channel Permissions |
send_password_reset (update only) |
A reset email can only be sent when the user is created |
{ "error": "Unprocessable Content", "message": "active cannot be set on update. Use POST /api/v1/users/7/deactivate or POST /api/v1/users/7/activate." }
Warning
Why an error and not a warning? Other endpoints accept unknown keys and
report them in a warnings array (see API Response Warnings).
The SDKs log warnings by default, and without a logger nobody sees them. For a
request like “make this user sudo” or “deactivate this user”, a warning would
look like success, so these keys fail the whole request instead. Any other
unrecognized key still produces a warning.
Update User
PATCH /api/v1/users/{id}
Send only the fields you want to change: email, first_name, last_name or
password, wrapped in user.
Request
curl -X PATCH "https://your-broadcast-domain.com/api/v1/users/7" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": { "last_name": "Meyer-Schulz" } }'
Response
The updated user, with permissions.
Deactivate User
POST /api/v1/users/{id}/deactivate
The user can no longer sign in. Their permissions are kept, so activating them again restores the same access.
curl -X POST "https://your-broadcast-domain.com/api/v1/users/7/deactivate" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
Returns the user with "active": false.
Activate User
POST /api/v1/users/{id}/activate
Re-enables sign-in. This also clears a lockout from too many failed sign-in attempts.
curl -X POST "https://your-broadcast-domain.com/api/v1/users/7/activate" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
Returns the user with "active": true and "locked": false.
Delete User
DELETE /api/v1/users/{id}
Permanently deletes the user and their permissions. Prefer deactivating if you might need the account again.
curl -X DELETE "https://your-broadcast-domain.com/api/v1/users/7" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
{ "message": "User deleted successfully" }
Channel Permission Object
| Field | Description |
|---|---|
broadcast_channel_id |
The channel these permissions apply to |
broadcast_channel_name |
The channel’s name |
role |
Viewer, Editor or Manager when the flags match a built-in role, the name of a saved preset when they match one, otherwise Custom |
permissions |
Every channel permission flag, true or false |
created_at |
When access to this channel was first granted |
updated_at |
When it last changed |
Flag names match the checkboxes in the web interface, without a prefix, for
example subscribers_read, broadcasts_send or templates_write. Read the
current list from any channel permission response.
List Channel Permissions
GET /api/v1/users/{id}/channel_permissions
Returns one entry per channel the user can access. Channels with no entry are channels the user can’t see.
curl -X GET "https://your-broadcast-domain.com/api/v1/users/7/channel_permissions" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
{ "data": [ { "broadcast_channel_id": 3, "broadcast_channel_name": "Product Updates", "role": "Viewer", "permissions": { "subscribers_read": true, "subscribers_write": false }, "created_at": "2026-09-01T10:05:00Z", "updated_at": "2026-09-01T10:05:00Z" } ], "total": 1 }
Set Channel Permissions
PUT /api/v1/users/{id}/channel_permissions/{broadcast_channel_id}
Grants access to a channel, or changes existing access. A request replaces the user’s whole permission record on that channel. Send exactly one of:
permissions: an object of flag names. Flags you leave out are set tofalse.role:Viewer,EditororManagerpreset_id: the id of a saved permission preset
Request with a role
curl -X PUT "https://your-broadcast-domain.com/api/v1/users/7/channel_permissions/3" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "role": "Editor" }'
Request with flags
curl -X PUT "https://your-broadcast-domain.com/api/v1/users/7/channel_permissions/3" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "permissions": { "subscribers_write": true, "broadcasts_read": true } }'
Response
The saved channel permission object.
Note
The response shows what was saved, which can be more than you sent. The
same rules as the web interface apply: granting a write permission also grants
the matching read permission, for example. Each flag granted this way is listed
in a parameter_overridden warning, and the response always shows the saved
flags. Use the response, not your request, as the record of what the user can
do.
Errors
422when the body has none, or more than one, ofpermissions,roleandpreset_id422for an unknown role, a preset that does not exist, or an unknown flag name (the message names it)422withAt least one permission must be grantedwhen no flag ends uptrue. To remove access, use Remove Channel Permissions.404when the channel does not exist
Remove Channel Permissions
DELETE /api/v1/users/{id}/channel_permissions/{broadcast_channel_id}
Removes the user’s access to one channel.
curl -X DELETE "https://your-broadcast-domain.com/api/v1/users/7/channel_permissions/3" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
{ "message": "Channel permissions removed successfully" }
Returns 404 when the user has no access to that channel.
Bulk Apply Channel Permissions
POST /api/v1/users/{id}/channel_permissions/bulk
Applies the same access to many channels in one request. This is the quickest
way to set up a new team member. Send broadcast_channel_ids and exactly one of
permissions, role or preset_id. As with
Set Channel Permissions, each channel’s record is
replaced.
Request
curl -X POST "https://your-broadcast-domain.com/api/v1/users/7/channel_permissions/bulk" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "broadcast_channel_ids": [3, 4, 99], "role": "Viewer" }'
Response
{ "applied": [ { "broadcast_channel_id": 3, "broadcast_channel_name": "Product Updates", "role": "Viewer", "permissions": { "subscribers_read": true } }, { "broadcast_channel_id": 4, "broadcast_channel_name": "Weekly Digest", "role": "Viewer", "permissions": { "subscribers_read": true } } ], "failed": [ { "broadcast_channel_id": 99, "error": "Broadcast channel not found" } ] }
One bad channel does not stop the rest. Every id comes back in either applied
or failed. The status is 200 when at least one channel was applied, and
422, with the same applied and failed body, when none were.
System Permissions
System permissions are installation-wide. Through the API you can read and change these seven:
| Permission | What it allows |
|---|---|
user_management |
Create, edit, and manage user accounts and their permissions |
channel_management |
Create and manage broadcast channels |
system_settings |
Modify system-wide settings and configuration |
system_monitoring |
Access monitoring and performance data |
system_backups |
Create and restore backups |
system_updates |
Install updates and manage software |
billing_management |
Access billing and subscription management |
Sudo access is never part of the API, and neither is admin API token management.
Get System Permissions
GET /api/v1/users/{id}/system_permissions
curl -X GET "https://your-broadcast-domain.com/api/v1/users/7/system_permissions" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"
{ "user_management": false, "channel_management": false, "system_settings": false, "system_monitoring": true, "system_backups": false, "system_updates": false, "billing_management": false }
Update System Permissions
PATCH /api/v1/users/{id}/system_permissions
Changes only the permissions you name. Everything else stays as it is.
curl -X PATCH "https://your-broadcast-domain.com/api/v1/users/7/system_permissions" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "permissions": { "user_management": true } }'
Returns all seven permissions after the change.
Warning
A request that includes sudo_access, or any name outside the table above, is
rejected with 422 and nothing in it is applied, including the valid
permissions.
Error Responses
| Status | Meaning |
|---|---|
401 Unauthorized |
Missing or invalid token, or the token lacks the Users read or write permission |
403 Forbidden |
A channel token was used, or the user has sudo access and cannot be changed |
404 Not Found |
The user or channel does not exist |
422 Unprocessable Content |
Validation failed. The body explains why. |
Example: provisioning a team member
Create the user, let them choose a password, and give them Editor access to two channels:
# 1. Create the user and email them a password-reset link curl -X POST "https://your-broadcast-domain.com/api/v1/users" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user": { "email": "sam@example.com", "first_name": "Sam", "last_name": "Lee", "send_password_reset": true } }' # 2. Use the returned id to grant Editor on channels 3 and 4 curl -X POST "https://your-broadcast-domain.com/api/v1/users/12/channel_permissions/bulk" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "broadcast_channel_ids": [3, 4], "role": "Editor" }'
When they leave, deactivate them:
curl -X POST "https://your-broadcast-domain.com/api/v1/users/12/deactivate" \ -H "Authorization: Bearer YOUR_ADMIN_API_TOKEN"