Media API (part 3 of 3)
Media endpoints in the Brix REST API, part 3 of 3: 16 operations from /v1/media/backfill-avif, each with auth, permission and curl.
View as Markdown · For AI agents: the full docs index is at /llms.txt
Base URL https://api.brixsignage.com. Send Authorization: Bearer $BRIX_API_KEY unless an operation says Auth: none or Auth: no API key. The Permission line names what the key must hold. See Authentication and scopes, Errors and rate limits and Pagination.
Media is split into 3 pages: part 1 (/v1/media to /v1/media/{id}), part 2 (/v1/media/{id} to /v1/media/{id}/web-secrets), part 3 (/v1/media/backfill-avif to /v1/media/upload/package).
POST /v1/media/backfill-avifPOST /v1/media/backfill-codec-warningsPOST /v1/media/backfill-heicPOST /v1/media/backfill-video-metadataPOST /v1/media/bulk-deletePOST /v1/media/import-urlPOST /v1/media/moderateGET /v1/media/statsPOST /v1/media/uploadPUT /v1/media/upload/{uploadId}GET /v1/media/upload/multipart/{id}POST /v1/media/upload/multipart/{id}/abortPOST /v1/media/upload/multipart/{id}/completePUT /v1/media/upload/multipart/{id}/part/{partNumber}POST /v1/media/upload/multipart/createPOST /v1/media/upload/package
Every 4xx and 5xx response below returns this body:
| Field | Type | Description |
|---|---|---|
error | string | Machine-readable code: unauthorized, forbidden, not_found, validation_error, conflict, rate_limited, internal_error, … |
message | string | Human-readable explanation. Safe to show an operator. |
requestId | string | Present on 5xx: quote it to support. |
POST /v1/media/backfill-avif
Convert this workspace's existing AVIF image assets to JPEG.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | no | |
after | string | no | nextAfter of the previous run. |
curl -X POST "https://api.brixsignage.com/v1/media/backfill-avif" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.scanned | integer | |
data.transcoded | integer | |
data.rows | array of object | |
data.rows[].id | string | |
data.rows[].name | string | null | |
data.rows[].result | "source_gone" | "undecodable" | "service_error" | "binding_absent" | "transcoded" | "already_done" | "not_avif" | |
data.nextAfter | string | null | Pass as after to continue; null when done. |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 429: More than 10 runs a minute.
Response 503: binding_absent: image conversion is not available.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/backfill-codec-warnings
Recompute codec-compatibility warnings for this workspace's video assets under the current compatibility rules, and clear any outdated re-export warnings. Safe to run more than once.
curl -X POST "https://api.brixsignage.com/v1/media/backfill-codec-warnings" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.scanned | integer | |
data.cleared | integer |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 429: More than 10 runs a minute.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/backfill-heic
Convert this workspace's existing HEIC image assets to JPEG so they display correctly on devices that cannot decode HEIC. Safe to run more than once, and applies only to your own workspace. Returns a 503 error if the conversion feature is temporarily unavailable.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | no | |
after | string | no | nextAfter of the previous run. |
curl -X POST "https://api.brixsignage.com/v1/media/backfill-heic" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.scanned | integer | |
data.transcoded | integer | |
data.rows | array of object | |
data.rows[].id | string | |
data.rows[].name | string | null | |
data.rows[].result | "source_gone" | "undecodable" | "service_error" | "binding_absent" | "transcoded" | "already_done" | "not_heic" | |
data.nextAfter | string | null |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 429: More than 10 runs a minute.
Response 503: binding_absent: HEIC conversion is not available.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/backfill-video-metadata
Scan this workspace's existing video files to fill in missing width, height, and duration values, and correct codec information that was guessed from the filename. Also updates the codec-compatibility warning where applicable.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
limit | integer | no | Most videos to read this run. |
curl -X POST "https://api.brixsignage.com/v1/media/backfill-video-metadata" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.scanned | integer | |
data.updated | integer | |
data.reclassified | integer |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 429: More than 10 runs a minute.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/bulk-delete
Move up to 500 media items to the recycle bin in one call. Permission is checked for each one. The answer lists the deleted IDs in ok and the rest in failed, so one failure does not stop the rest.
curl -X POST "https://api.brixsignage.com/v1/media/bulk-delete" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 4XX: Client error. 404 rather than 403 for another tenant's resource, so account existence is not leaked.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/import-url
Import a file from a remote URL into the media library. The API fetches the file server-side, checking that the URL does not point to a disallowed destination, stores its bytes, and creates the media asset record. This is the same path used by the upload_media_from_url tool.
Fetches a public http(s) URL into the library. SVG is refused.
Notes.
- The response is the row as built for insert, not the GET shape: tags is a JSON string (not an array), sourceUrl is present but not stored, and most columns (state, fit, width, …) are absent. Read GET /v1/media/{id} for the settled asset.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | Public http(s) address of the file. |
name | string | no | Display name; defaults to the file name in the URL. |
folderId | string | no | |
nodeId | string | no | Home location; defaults to your own. |
tags | array of string | no | |
autoCaption | boolean | no | Videos: generate captions. |
autoSmartFit | boolean | no | Images: detect a focal region (default true). |
curl -X POST "https://api.brixsignage.com/v1/media/import-url" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 201: Success.
| Field | Type | Description |
|---|---|---|
data | ImportedMedia | The row created by an import, before processing settles. |
data.id | string | Media asset id. |
data.spaceId | string | |
data.name | string | |
data.kind | string | |
data.url | string | /v1/media/<id>/file. |
data.bytes | integer | |
data.checksum | string | null | |
data.active | true | |
data.folderId | string | null | |
data.nodeId | string | null | |
data.tags | string | JSON-encoded array of strings — NOT decoded here, unlike GET /v1/media. |
data.sourceUrl | string | The URL that was imported. Not stored; returned by this route only. |
data.autoCaption | boolean | |
data.captionState | "pending" | null | |
data.autoSmartFit | boolean | |
data.createdAt | string | ISO-8601 timestamp (UTC). |
data.updatedAt | string | ISO-8601 timestamp (UTC). |
data.deletedAt | null |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 413: too_large: the file is over the size limit for its kind.
Response 415: unsupported_type: SVG or an unknown content type.
Response 422: Missing or non-http URL, a blocked address (url_blocked), or an unknown folder or location.
Response 502: fetch_failed / source_status: the source did not answer with the file.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/moderate
Run a safety classifier over a piece of user-submitted text, such as banner copy or a message board post, and return its verdict. This operation only classifies the text; it does not store it.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
text | string | yes |
curl -X POST "https://api.brixsignage.com/v1/media/moderate" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.flagged | boolean | |
data.reason | string | Present when flagged. |
data.checked | boolean | False when the check could not run (the text is then not flagged). |
Response 400: text is missing.
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 5XX: Server error. The body carries a requestId to quote to support.
GET /v1/media/stats
Return summary counts for the media library in one response: total assets, unused assets, and a count per folder. Use this instead of listing all media when only summary counts are needed.
curl "https://api.brixsignage.com/v1/media/stats" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.total | integer | |
data.unused | integer | Items used nowhere. |
data.folders | array of object | Items per folder; folderId null = not in a folder. |
data.folders[].folderId | string | null | |
data.folders[].count | integer |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/upload
Upload a file in a single request using multipart form data. Accepts form fields file (required), and optional name, nodeId, and folderId. This stores the file and creates the media asset record in one step, and is safe to retry with the same Idempotency-Key header. For large files or programmatic clients, minting an upload URL and then uploading with PUT is usually simpler.
Notes.
- Form fields other than file are strings, as multipart sends them.
- For files over ~100 MB use the multipart upload.
Request body: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file | string (binary) | yes | The file. SVG is refused. |
name | string | no | Display name; default the file name. |
nodeId | string | no | Home location; default the caller's own. |
folderId | string | no | |
alt | string | no | Alt text. |
decorative | "1" | no | 1: the image is decorative (empty alt text). |
autoCaption | "1" | no | Videos: 1 generates captions. |
autoSmartFit | "0" | "1" | no | Images: 0 skips focal-region detection (default on). |
durationSec | string | no | Videos: length in seconds, when the client measured it. |
loopDurationMs | string | no | Animated images: loop length. |
width | string | no | |
height | string | no | |
codec | string | no | |
codecString | string | no | |
fps | string | no |
curl -X POST "https://api.brixsignage.com/v1/media/upload" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 201: Success.
| Field | Type | Description |
|---|---|---|
data | UploadedMedia | The media row an upload creates, before processing settles. |
data.id | string | Media asset id. |
data.spaceId | string | Workspace id. |
data.nodeId | string | null | Home location; null = workspace library root. |
data.folderId | string | null | |
data.name | string | |
data.kind | string | Media kind: image, video, audio, pdf, powerpoint, web, dashboard, weather, rss, clock, qr, menu, directory, donor-wall, hall-of-fame, birthday-board, recognition, wayfinding, check-in, emergency, touch-kiosk, package, font. Free text in storage, so a very old row may carry another value. |
data.url | string | Where the bytes live: a /v1/media/<id>/file path, an https URL, r2://…, or (for a web link) the page address. |
data.bytes | integer | Stored size in bytes (0 for links and apps). |
data.checksum | string | SHA-256 of the bytes. |
data.active | boolean | False when archived. |
data.altText | string | null | |
data.width | integer | null | |
data.height | integer | null | |
data.durationSec | number | null | Video/audio length in seconds. |
data.loopDurationMs | integer | null | Animated image loop length. |
data.fontFamily | string | null | |
data.fontWeights | array of integer | null | Font files: the weights in the file. |
data.state | "ready" | "failed" | "processing" | "ready_with_warnings" | "needs_action" | |
data.stateReason | string | null | |
data.stateCode | string | null | |
data.stateFault | "user" | "platform" | null | |
data.codec | string | null | |
data.frameLumaMean | number | null | |
data.frameLumaVariance | number | null | |
data.frameEdgeDensity | number | null | |
data.autoCaption | boolean | |
data.captionState | "pending" | null | |
data.autoSmartFit | boolean | |
data.createdAt | string | ISO-8601 timestamp (UTC). |
data.updatedAt | string | ISO-8601 timestamp (UTC). |
data.deletedAt | null |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: The folder or location does not exist.
Response 413: The file is over the limit for its kind (images 250 MB, video 2 GB, documents 100 MB, fonts 10 MB).
Response 415: SVG, or a type the library does not take.
Response 422: file is missing.
Response 5XX: Server error. The body carries a requestId to quote to support.
PUT /v1/media/upload/{uploadId}
Upload the raw file bytes for a previously created upload slot. Send the file as the request body and set the Content-Type header to match the file's type. After uploading, finalize the upload to create the media asset record. Notes. - This stores the bytes for a bulk import; the import itself creates the media rows.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
uploadId | path | string | yes | An upl_… id from POST /v1/import/upload-urls. |
curl -X PUT "https://api.brixsignage.com/v1/media/upload/{uploadId}" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.uploadId | string | |
data.bytes | integer |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: No mint with this id in this workspace.
Response 413: Over 500 MB.
Response 415: SVG.
Response 422: Empty body or a malformed id.
Response 5XX: Server error. The body carries a requestId to quote to support.
GET /v1/media/upload/multipart/{id}
Return the state of an in-progress multipart upload, including the file's name, size, kind, part size, and every part already received, each with its part number, ETag, and size. Use this to resume an interrupted upload from the last completed part instead of starting over. Returns 404 if the upload belongs to another workspace, has already finished, or has expired.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | The upload's media id, from POST /v1/media/upload/multipart/create. |
curl "https://api.brixsignage.com/v1/media/upload/multipart/{id}" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string | |
data.name | string | |
data.contentType | string | |
data.kind | string | |
data.sizeBytes | integer | |
data.partSize | integer | |
data.masterOf | string | null | |
data.createdAt | string | ISO-8601 timestamp (UTC). |
data.parts | array of object | Parts already stored: resume from the first missing one. |
data.parts[].partNumber | integer | |
data.parts[].etag | string | |
data.parts[].size | integer |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: No such upload.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/upload/multipart/{id}/abort
Cancel an in-progress multipart upload and discard any parts already received. Safe to call more than once.
Notes.
- Answers aborted: true also when there was nothing to cancel.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | The upload's media id, from POST /v1/media/upload/multipart/create. |
curl -X POST "https://api.brixsignage.com/v1/media/upload/multipart/{id}/abort" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.aborted | true |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/upload/multipart/{id}/complete
Finalize a multipart upload by sending the list of uploaded parts, each with partNumber and etag. If the list is left empty, the server completes the upload using the parts it already has on record, so a client resuming an interrupted upload does not need to know every part's ETag. This creates the media asset record; video files are automatically queued for processing.
Notes.
- For a master upload (masterOf) the body is { id, masterKey, masterBytes }; otherwise it is the new media row.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | The upload's media id, from POST /v1/media/upload/multipart/create. |
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
parts | array of object | yes | |
parts[].partNumber | integer | yes | |
parts[].etag | string | yes |
curl -X POST "https://api.brixsignage.com/v1/media/upload/multipart/{id}/complete" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 201: Success.
| Field | Type | Description |
|---|---|---|
data | object | object |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: No such upload.
Response 409: A part is missing or does not match.
Response 422: No parts.
Response 5XX: Server error. The body carries a requestId to quote to support.
PUT /v1/media/upload/multipart/{id}/part/{partNumber}
Upload one part of a file for an in-progress multipart upload, identified by its part number. Returns the part's ETag, which is needed to complete the upload. Returns 404 if the upload belongs to another workspace.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | yes | The upload's media id, from POST /v1/media/upload/multipart/create. |
partNumber | path | string | yes | 1-based part number. |
curl -X PUT "https://api.brixsignage.com/v1/media/upload/multipart/{id}/part/{partNumber}" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.partNumber | integer | |
data.etag | string | Send it back in complete. |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: No such upload.
Response 413: The part is larger than partSize.
Response 422: Bad part number or empty part.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/upload/multipart/create
Begin a multipart upload for large files, such as multi-gigabyte videos, that are too large for a single request. Validates the file kind and checks its size against the limit allowed for that kind. Returns an upload id and the part size to use for subsequent part uploads.
Request body: application/json
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | |
contentType | string | no | The file's media type; decides the kind. |
sizeBytes | integer | yes | |
folderId | string | null | no | |
nodeId | string | null | no | |
alt | string | null | no | |
decorative | boolean | no | |
loopDurationMs | number | null | no | |
durationSec | number | null | no | |
width | integer | null | no | |
height | integer | null | no | |
codec | string | null | no | |
codecString | string | null | no | |
fps | number | null | no | |
masterOf | string | null | no | An existing video's id: upload a high-resolution master for it instead of a new asset. |
importSourceId | string | null | no | Your own id for the file. If a live asset already has it, the answer is 200 with exists: true. |
curl -X POST "https://api.brixsignage.com/v1/media/upload/multipart/create" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200: Success: importSourceId matched a live asset: { id, exists: true }, nothing started.
| Field | Type | Description |
|---|---|---|
data | object | object |
Response 201: Success.
| Field | Type | Description |
|---|---|---|
data | object | object |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 413: sizeBytes is over the limit for the kind.
Response 415: SVG.
Response 422: Unknown file type, or sizeBytes missing.
Response 5XX: Server error. The body carries a requestId to quote to support.
POST /v1/media/upload/package
Upload a zipped HTML5 package as a media asset, using multipart form data with fields file (required), and optional name, nodeId, and folderId. The archive is validated, expanded into storage, and its entry page is identified automatically.
Request body: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
file | string (binary) | yes | The .zip. It must hold an entry page (index.html). |
name | string | no | Display name; default the file name. |
nodeId | string | no | Home location; default the caller's own. |
folderId | string | no |
curl -X POST "https://api.brixsignage.com/v1/media/upload/package" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 201: Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.id | string | Media asset id. |
data.spaceId | string | Workspace id. |
data.nodeId | string | null | Home location; null = workspace library root. |
data.folderId | string | null | |
data.name | string | |
data.kind | "package" | |
data.url | string | Where the bytes live: a /v1/media/<id>/file path, an https URL, r2://…, or (for a web link) the page address. |
data.bytes | integer | Stored size in bytes (0 for links and apps). |
data.checksum | string | SHA-256 of the .zip. |
data.active | boolean | False when archived. |
data.packageEntry | string | The entry page found in the archive, e.g. index.html. |
data.packageFiles | integer | Files in the archive. |
data.packageBytes | integer | Expanded size of the archive, in bytes. |
data.state | "ready" | |
data.createdAt | string | ISO-8601 timestamp (UTC). |
data.updatedAt | string | ISO-8601 timestamp (UTC). |
data.deletedAt | null |
Response 401: Missing, expired or revoked bearer token.
Response 403: The token lacks the permission this operation needs (see x-brix-permission).
Response 404: The folder or location does not exist.
Response 413: The .zip, or its expanded contents, is over the limit.
Response 422: file is missing, the .zip cannot be read, or a file in it is refused (unsafe path, type not allowed, no entry page).
Response 5XX: Server error. The body carries a requestId to quote to support.