# Creatives

Base URL: `https://api.brixsignage.com`. Send `Authorization: Bearer $BRIX_API_KEY` unless an operation says Auth: none.

## GET /v1/creatives

List creatives

Return the workspace's canvas creatives, including each one's name, stage size, location, and sharing state. The full layout of shapes is not included; use the get-creative operation to retrieve that.

Auth: Bearer token. Permission: `creative.view`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `limit` | query | integer | no | Page size. Omit to get every row; pass it to page by `cursor`. |
| `cursor` | query | string | no | The `nextCursor` of the previous page. |
| `count` | query | "1" | no | With `limit`: also return `total`, the number of matching rows. |
| `usableAt` | query | string | no | Location id: only rows usable at that location (homed there, at the workspace root, or shared to it). |

```bash
curl "https://api.brixsignage.com/v1/creatives" \
  -H "Authorization: Bearer $BRIX_API_KEY"
```

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | array of Creative |  |
| `data[].id` | string | Creative id. |
| `data[].spaceId` | string |  |
| `data[].name` | string |  |
| `data[].backgroundUrl` | string \| null |  |
| `data[].boxes` | array of object | The design's boxes (text, image, data-bound fields…), in paint order. |
| `data[].dataSourceId` | string \| null | The data source the boxes bind to, if any. |
| `data[].stage` | string \| null | Stage preset name. |
| `data[].stageWidth` | integer \| null |  |
| `data[].stageHeight` | integer \| null |  |
| `data[].scenes` | array of object | Scenes, for a multi-scene design; often empty. |
| `data[].touchEnabled` | boolean \| null |  |
| `data[].nodeId` | string \| null |  |
| `data[].approvalState` | "draft" \| "pending" \| "approved" \| "rejected" | Review state. Editing an approved row returns it to `draft`. |
| `data[].approvedSnapshot` | string \| null | JSON TEXT of the last approved version (not parsed). |
| `data[].sourceSignage` | any \| null | The template it was made from (JSON), if any. |
| `data[].look` | any \| null | Accent / Brand Kit / light-dark settings (JSON), if set. |
| `data[].masterId` | string \| null | The master template id, for a design made from one. |
| `data[].shareLockDefault` | any \| null | Which boxes recipients may edit when shared (JSON), if set. |
| `data[].shareEditsSkipApproval` | boolean |  |
| `data[].recalledAt` | string \| null |  |
| `data[].recalledBy` | string \| null |  |
| `data[].createdAt` | string | ISO-8601 timestamp (UTC). |
| `data[].updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data[].deletedAt` | string \| null | Always null on these reads: deleted rows are not listed. |
| `nextCursor` | string \| null | Present when `?limit` was passed. Send it back as `?cursor=` for the next page; null on the last page. |
| `total` | integer | Total matching rows, when the route computes it. |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: The token lacks the permission this operation needs (see `x-brix-permission`).

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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/creatives

Create a creative

Create a canvas creative. Accepts name and optional boxes, scenes, stageWidth, stageHeight, backgroundUrl, dataSourceId, touchEnabled, nodeId, and masterId. Safe to retry with the same Idempotency-Key header without creating duplicates.

**Notes.**
- The 201 body is the row as written, not re-read from the database, so columns the create does not set (for example `lastSnapshotAt`) are absent rather than null. `GET` returns every column.
- Send an `Idempotency-Key` header to make a retry safe.

Auth: Bearer token. Permission: `creative.create`.

Request body (`application/json`):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes |  |
| `backgroundUrl` | string \| null | no | An unsafe URL scheme is stored as null. |
| `boxes` | array of object | no | The whole box list; each box is checked and filled out with defaults. Default `[]`. |
| `dataSourceId` | string \| null | no | A data source in this workspace. |
| `stage` | string \| null | no |  |
| `stageWidth` | integer \| null | no |  |
| `stageHeight` | integer \| null | no |  |
| `scenes` | array of object | no | Default `[]`. |
| `touchEnabled` | boolean \| null | no |  |
| `nodeId` | string \| null | no | Home location. Default: the caller's own location. |
| `sourceSignage` | any | no |  |
| `masterId` | string \| null | no | The master template it was made from (`GET /v1/signage-master-templates`). |
| `shareLockDefault` | any | no | Which box fields recipients may edit when it is shared (JSON). |
| `shareEditsSkipApproval` | boolean | no | Recipients' edits air without review. Needs `creative.approve`. |
| `look` | object \| null | no |  |

```bash
curl -X POST "https://api.brixsignage.com/v1/creatives" \
  -H "Authorization: Bearer $BRIX_API_KEY" \
  -H "Content-Type: application/json"
```

Response 201: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string | Creative id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.backgroundUrl` | string \| null |  |
| `data.boxes` | array of object | The design's boxes (text, image, data-bound fields…), in paint order. |
| `data.dataSourceId` | string \| null | The data source the boxes bind to, if any. |
| `data.stage` | string \| null | Stage preset name. |
| `data.stageWidth` | integer \| null |  |
| `data.stageHeight` | integer \| null |  |
| `data.scenes` | array of object | Scenes, for a multi-scene design; often empty. |
| `data.touchEnabled` | boolean \| null |  |
| `data.nodeId` | string \| null |  |
| `data.approvalState` | "draft" \| "pending" \| "approved" \| "rejected" | Review state. Editing an approved row returns it to `draft`. |
| `data.approvedSnapshot` | string \| null | JSON TEXT of the last approved version (not parsed). |
| `data.sourceSignage` | any \| null | The template it was made from (JSON), if any. |
| `data.look` | any \| null | Accent / Brand Kit / light-dark settings (JSON), if set. |
| `data.masterId` | string \| null | The master template id, for a design made from one. |
| `data.shareLockDefault` | any \| null | Which boxes recipients may edit when shared (JSON), if set. |
| `data.shareEditsSkipApproval` | boolean |  |
| `data.recalledAt` | string \| null |  |
| `data.recalledBy` | string \| null |  |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.deletedAt` | string \| null | Always null on these reads: deleted rows are not listed. |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: Setting `shareEditsSkipApproval` without `creative.approve`.

| 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. |

Response 404: `dataSourceId` names no data source in this workspace.

| 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. |

Response 422: Missing name, invalid JSON, malformed boxes, scenes or look, or a location outside this workspace.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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. |

## GET /v1/creatives/{id}

Get a creative

Return one creative in full, including its boxes, scenes, background, any linked data source, and stage dimensions.

Auth: Bearer token. Permission: `creative.view`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Creative id. |

```bash
curl "https://api.brixsignage.com/v1/creatives/{id}" \
  -H "Authorization: Bearer $BRIX_API_KEY"
```

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string | Creative id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.backgroundUrl` | string \| null |  |
| `data.boxes` | array of object | The design's boxes (text, image, data-bound fields…), in paint order. |
| `data.dataSourceId` | string \| null | The data source the boxes bind to, if any. |
| `data.stage` | string \| null | Stage preset name. |
| `data.stageWidth` | integer \| null |  |
| `data.stageHeight` | integer \| null |  |
| `data.scenes` | array of object | Scenes, for a multi-scene design; often empty. |
| `data.touchEnabled` | boolean \| null |  |
| `data.nodeId` | string \| null |  |
| `data.approvalState` | "draft" \| "pending" \| "approved" \| "rejected" | Review state. Editing an approved row returns it to `draft`. |
| `data.approvedSnapshot` | string \| null | JSON TEXT of the last approved version (not parsed). |
| `data.sourceSignage` | any \| null | The template it was made from (JSON), if any. |
| `data.look` | any \| null | Accent / Brand Kit / light-dark settings (JSON), if set. |
| `data.masterId` | string \| null | The master template id, for a design made from one. |
| `data.shareLockDefault` | any \| null | Which boxes recipients may edit when shared (JSON), if set. |
| `data.shareEditsSkipApproval` | boolean |  |
| `data.recalledAt` | string \| null |  |
| `data.recalledBy` | string \| null |  |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.deletedAt` | string \| null | Always null on these reads: deleted rows are not listed. |
| `data.requiresApproval` | boolean | The home location requires approval before content airs. |
| `data.canEditBase` | boolean | The caller may edit the design itself (not only its unlocked boxes). |
| `data.canWaiveApproval` | boolean | The caller holds `creative.approve` at its home location. |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: The token lacks the permission this operation needs (see `x-brix-permission`).

| 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. |

Response 404: No such creative in this workspace.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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. |

## PATCH /v1/creatives/{id}

Update a creative

Edit a creative. The boxes and scenes fields each replace the entire existing list, so retrieve the creative first and send back the complete array with changes included. If the location requires approval before content goes live, updating the creative resets that approval.

**Notes.**
- The response is the stored row: it has no `requiresApproval`, `canEditBase` or `canWaiveApproval` (GET has them).

Auth: Bearer token. Permission: `creative.edit`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Creative id. |

Request body (`application/json`):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | no |  |
| `backgroundUrl` | string \| null | no | An unsafe URL scheme is stored as null. |
| `boxes` | array of object | no | The whole box list; each box is checked and filled out with defaults. Default `[]`. |
| `dataSourceId` | string \| null | no | A data source in this workspace. |
| `stage` | string \| null | no |  |
| `stageWidth` | integer \| null | no |  |
| `stageHeight` | integer \| null | no |  |
| `scenes` | array of object | no | Default `[]`. |
| `touchEnabled` | boolean \| null | no |  |
| `nodeId` | string \| null | no | Home location. Default: the caller's own location. |
| `sourceSignage` | any | no |  |
| `masterId` | string \| null | no | The master template it was made from (`GET /v1/signage-master-templates`). |
| `shareLockDefault` | any | no | Which box fields recipients may edit when it is shared (JSON). |
| `shareEditsSkipApproval` | boolean | no | Recipients' edits air without review. Needs `creative.approve`. |
| `look` | object \| null | no |  |
| `baseUpdatedAt` | string | no | Optimistic concurrency: the `updatedAt` you read. A stale value is refused with 409 `conflict` and the `current` row. |

```bash
curl -X PATCH "https://api.brixsignage.com/v1/creatives/{id}" \
  -H "Authorization: Bearer $BRIX_API_KEY" \
  -H "Content-Type: application/json"
```

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | Creative | A canvas design (data-bound boxes on a stage). |
| `data.id` | string | Creative id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.backgroundUrl` | string \| null |  |
| `data.boxes` | array of object | The design's boxes (text, image, data-bound fields…), in paint order. |
| `data.dataSourceId` | string \| null | The data source the boxes bind to, if any. |
| `data.stage` | string \| null | Stage preset name. |
| `data.stageWidth` | integer \| null |  |
| `data.stageHeight` | integer \| null |  |
| `data.scenes` | array of object | Scenes, for a multi-scene design; often empty. |
| `data.touchEnabled` | boolean \| null |  |
| `data.nodeId` | string \| null |  |
| `data.approvalState` | "draft" \| "pending" \| "approved" \| "rejected" | Review state. Editing an approved row returns it to `draft`. |
| `data.approvedSnapshot` | string \| null | JSON TEXT of the last approved version (not parsed). |
| `data.sourceSignage` | any \| null | The template it was made from (JSON), if any. |
| `data.look` | any \| null | Accent / Brand Kit / light-dark settings (JSON), if set. |
| `data.masterId` | string \| null | The master template id, for a design made from one. |
| `data.shareLockDefault` | any \| null | Which boxes recipients may edit when shared (JSON), if set. |
| `data.shareEditsSkipApproval` | boolean |  |
| `data.recalledAt` | string \| null |  |
| `data.recalledBy` | string \| null |  |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.deletedAt` | string \| null | Always null on these reads: deleted rows are not listed. |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: Moving it to a location where you lack creative.edit, or changing `shareEditsSkipApproval` without `creative.approve`.

| 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. |

Response 404: No such creative (or `dataSourceId`) in this workspace.

| 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. |

Response 409: `conflict`: the row changed since `baseUpdatedAt`; the body carries `current`.

| 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. |

Response 422: Invalid JSON or malformed boxes, scenes or look.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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. |

## DELETE /v1/creatives/{id}

Delete a creative

Move a creative to the recycle bin. If the creative is shared into other locations, the request fails with a 409 error unless the deletion is explicitly confirmed, since deleting a shared creative removes it everywhere it is shared.

Auth: Bearer token. Permission: `creative.delete`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Creative id. |
| `force` | query | "true" | no | Delete even when it is shared into other places; the shares go with it. |

```bash
curl -X DELETE "https://api.brixsignage.com/v1/creatives/{id}" \
  -H "Authorization: Bearer $BRIX_API_KEY"
```

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string |  |
| `data.deleted` | true |  |
| `data.sharesRemoved` | integer | Shares removed with it. |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: The token lacks the permission this operation needs (see `x-brix-permission`).

| 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. |

Response 404: No such creative in this workspace.

| 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. |

Response 409: `content_shared`: it is shared into other places; `shareCount`, `crossSpaceShares`, `contentShares` say where. Repeat with `?force=true` to delete it and those shares.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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/creatives/{id}/restore

Restore a creative

Bring back a deleted creative so it returns to the library. The shares removed by the delete come back with it.

Auth: Bearer token. Permission: `creative.delete`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Creative id. |

```bash
curl -X POST "https://api.brixsignage.com/v1/creatives/{id}/restore" \
  -H "Authorization: Bearer $BRIX_API_KEY"
```

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.id` | string |  |
| `data.restored` | true |  |

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: The token lacks the permission this operation needs (see `x-brix-permission`).

| 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. |

Response 404: No such creative in this workspace, or it was purged.

| 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. |

Response 409: `not_deleted`: the creative is not in the recycle bin.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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. |

## GET /v1/creatives/{id}/thumbnail

Get a creative's thumbnail

Return an image of the creative, showing its shapes and pictures along with a representative preview of each content slot, such as a file's poster image, a playlist's first item, or an app's most recent snapshot. Text boxes are not drawn. The image is cached; add ?fresh=1 to bypass the cache after making an edit.

Auth: Bearer token. Permission: `creative.view`.

Parameters:

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | Creative id. |
| `fresh` | query | "1" | no | Skip the cached image and draw it again. |

```bash
curl "https://api.brixsignage.com/v1/creatives/{id}/thumbnail" \
  -H "Authorization: Bearer $BRIX_API_KEY"
```

Response 401: Missing, expired or revoked bearer token.

| 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. |

Response 403: The token lacks the permission this operation needs (see `x-brix-permission`).

| 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. |

Response 404: No such creative in this workspace.

| 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. |

Response 5XX: Server error. The body carries a `requestId` to quote to support.

| 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. |
