File Assets API

Note

Requires Broadcast 2.48.0 or later.

The File Assets API manages the channel’s file library, the same files you see under File Assets in Broadcast. Each file has a public URL that never expires. Use the URL in emails and templates, or send it as the logo in the Brand Kit API.

The file library holds images: PNG, JPEG and GIF files under 10 MB.

Required Permissions

  • File Assets read: list files and get a file
  • File Assets write: upload and delete files

File Assets read and write are off on every token until you tick them, including tokens created before 2.48.0. Write does not include read: if an integration uploads and then lists files, tick both. Set the permissions under Access Tokens (and Admin API Tokens). See API Authentication.

A token without the permission gets 401 Unauthorized, the same as the other API endpoints:

{ "error": "Unauthorized" }

An admin API token must name the channel with broadcast_channel_id: as a query parameter for GET and DELETE, and in the body (or as a form field) for POST.

File Object

{
  "id": 42,
  "filename": "logo.png",
  "content_type": "image/png",
  "byte_size": 18734,
  "url": "https://your-broadcast-domain.com/files/eyJfcmFpbHMi...--3f2a...-logo.png",
  "created_at": "2026-10-14T09:30:00Z"
}
Field Type Description
id integer The file’s ID.
filename string The file name, with its extension.
content_type string image/png, image/jpeg or image/gif.
byte_size integer The size of the file in bytes.
url string The public URL of the file. It never expires and needs no token.
created_at string When the file was uploaded (ISO 8601).

Which Files a Channel Sees

A channel sees the files linked to it, and the files linked to no channel. This is the same rule as the File Assets page. A file of another channel is a 404.

When you upload a file, Broadcast links it to every channel, as the File Assets page does. Send channel_restricted: true to link it to the token’s channel only.

List Files

GET /api/v1/file_assets

curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  "https://your-broadcast-domain.com/api/v1/file_assets?limit=20"
Parameter Description
filter Finds files by file name. The closest matches come first.
limit The number of files to return, from 1 to 1000. Another value is a 422.
offset The number of files to skip, 0 or more. Another value is a 422.

Without limit, the response holds every matching file. Without filter, the newest files come first.

{
  "data": [
    {
      "id": 42,
      "filename": "logo.png",
      "content_type": "image/png",
      "byte_size": 18734,
      "url": "https://your-broadcast-domain.com/files/eyJfcmFpbHMi...--3f2a...-logo.png",
      "created_at": "2026-10-14T09:30:00Z"
    }
  ],
  "total": 1
}

total counts every file that matches, before limit and offset.

Get a File

GET /api/v1/file_assets/:id

curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://your-broadcast-domain.com/api/v1/file_assets/42

Returns 200 with the file object. A file that does not exist, or that the channel cannot see, returns 404:

{ "error": "File asset not found" }

Upload a File

POST /api/v1/file_assets

Send the file in one of two ways. Both return 201 with the file object.

As a multipart upload

Send multipart/form-data with the file in a file part. The file name and the content type come from the part.

curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -F "file=@logo.png;type=image/png" \
  https://your-broadcast-domain.com/api/v1/file_assets

As base64 in a JSON body

Send the bytes base64-encoded in data. Use this form when your client cannot send multipart, for example an AI agent through the MCP server.

curl -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data-raw "{
    \"filename\": \"logo.png\",
    \"content_type\": \"image/png\",
    \"data\": \"$(base64 < logo.png | tr -d '\n')\"
  }" \
  https://your-broadcast-domain.com/api/v1/file_assets
Field Required Description
filename Yes The file name, with its extension, such as logo.png. Broadcast keeps only the last part of a path, so images/logo.png is stored as logo.png.
data Yes The file, base64-encoded (standard alphabet, with padding). Broadcast ignores line breaks and spaces.
content_type No image/png, image/jpeg or image/gif. When you leave it out, Broadcast finds the type from the bytes and the file name.
channel_restricted No true links the file to the token’s channel only. The default is false. Also accepted as a multipart form field. Any value other than true or false (or "true", "false", 1, 0) is a 422.

Broadcast never downloads a file from a URL. Upload the bytes.

Safe retries

Send an Idempotency-Key header to make a retry safe. Broadcast keeps the first response for 24 hours and returns it again for the same key, with the Idempotency-Replayed: true header, so the file is stored only once. The same key with a different body is a 422. See Transactional Email API for the full rules.

Errors

A 422 stores nothing:

  • The data is not valid base64.
  • The file is 10 MB or larger.
  • The file is not a PNG, JPEG or GIF image.
  • The body has neither a file part nor data, or data has no filename.
  • channel_restricted is not true or false.
{
  "error": "Unprocessable Content",
  "message": "data is not valid base64"
}
{
  "error": "Stored file has an invalid content type (authorized content types are PNG, JPG, GIF)"
}

A key that the endpoint does not know is ignored with an unrecognized_parameter warning (see API Response Warnings).

Delete a File

DELETE /api/v1/file_assets/:id

curl -X DELETE \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://your-broadcast-domain.com/api/v1/file_assets/42
{ "message": "File asset deleted successfully" }

Warning

Emails that were already sent show the file from its URL. After you delete the file, those emails show a broken image.

You cannot delete a file that is a channel’s brand kit logo. Broadcast returns a 422:

{
  "error": "This file is the channel's Brand Kit logo. Choose another logo (or none) in Settings > Brand Kit or with PATCH /api/v1/channel/design, then delete the file."
}

When the file is the logo of another channel, the message is different:

{
  "error": "This file is the Brand Kit logo of another channel. Choose another logo for that channel, then delete the file."
}

Set another logo (or null) with the Brand Kit API first.

  1. Upload the image with POST /api/v1/file_assets.
  2. Send the url from the response as channel_design.brand.logo_url to PATCH /api/v1/channel/design.
{ "channel_design": { "brand": { "logo_url": "https://your-broadcast-domain.com/files/eyJfcmFpbHMi...--3f2a...-logo.png" } } }

The logo must be linked to the channel. An upload without channel_restricted is linked to every channel, so any channel can use it as the logo.

Last updated

Was this page helpful?

Thanks for your feedback!

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