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 GET endpoints
  • 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 name
  • status (optional): active or inactive. Any other value returns 422.
  • limit (optional): Maximum number of users to return, from 1 to 1000
  • offset (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 address
  • user[first_name] (required)
  • user[last_name] (required)
  • user[password] (optional): The user’s password
  • user[send_password_reset] (optional): true to 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 to false.
  • role: Viewer, Editor or Manager
  • preset_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

  • 422 when the body has none, or more than one, of permissions, role and preset_id
  • 422 for an unknown role, a preset that does not exist, or an unknown flag name (the message names it)
  • 422 with At least one permission must be granted when no flag ends up true. To remove access, use Remove Channel Permissions.
  • 404 when 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"

Last updated

Was this page helpful?

Thanks for your feedback!

Thanks for letting us know. We'll work on improving this page.