# Serial templates

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

## GET /v1/serial-templates

List serial command templates

List saved RS232 serial command templates for your workspace, such as profiles for turning a display on or switching its input. Each template includes the exact bytes each command sends.

**Notes.**
- Not paginated. Only templates at locations where the key has `screen.view` are listed.

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

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

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | array of SerialTemplate |  |
| `data[].id` | string | Serial template id. |
| `data[].spaceId` | string |  |
| `data[].name` | string |  |
| `data[].model` | string \| null | Free-text panel model (`Sony Bravia FW-series`). |
| `data[].nodeId` | string \| null | Home location; null = workspace root. |
| `data[].createdAt` | string | ISO-8601 timestamp (UTC). |
| `data[].updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data[].items` | array of object |  |
| `data[].items[].id` | string | Command id. Kept across edits, so saved buttons that name it keep working. |
| `data[].items[].name` | string |  |
| `data[].items[].value` | string | The command: literal text (`ascii`) or hex digits (`hex`). |
| `data[].items[].encoding` | "ascii" \| "hex" |  |
| `data[].items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | Line ending added after the value. |
| `data[].items[].hexPreview` | string | The exact bytes sent, as spaced hex (`2A 53 0A`). |

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/serial-templates

Create a serial command template

Create an RS232 command template. Provide a `name`, an optional `model`, an `items` array of commands each with `name`, `value`, `encoding` (`ascii` or `hex`), and `eol`, and an optional `nodeId`.

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

Request body (`application/json`):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes |  |
| `model` | string \| null | no |  |
| `nodeId` | string \| null | no | Home location; null = workspace root. |
| `items` | array of object | no | The commands, at most 200. On update the list replaces the stored one. |
| `items[].id` | string | no | Keep an existing command's id; omit to get a new one. |
| `items[].name` | string | yes |  |
| `items[].value` | string | yes | At most 512 characters, and it must give at least one byte. |
| `items[].encoding` | "ascii" \| "hex" | no | Default `ascii`. An unknown value is read as `ascii`. |
| `items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | no | Default `none`. An unknown value is read as `none`. |

```bash
curl -X POST "https://api.brixsignage.com/v1/serial-templates" \
  -H "Authorization: Bearer $BRIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Sony Bravia","model":"FW-55BZ35","items":[{"name":"Power on","value":"*SCPOWR0000000000000001","encoding":"ascii","eol":"lf"}]}'
```

Response 201: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | SerialTemplate | A saved set of RS232 commands for one panel model. |
| `data.id` | string | Serial template id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.model` | string \| null | Free-text panel model (`Sony Bravia FW-series`). |
| `data.nodeId` | string \| null | Home location; null = workspace root. |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.items` | array of object |  |
| `data.items[].id` | string | Command id. Kept across edits, so saved buttons that name it keep working. |
| `data.items[].name` | string |  |
| `data.items[].value` | string | The command: literal text (`ascii`) or hex digits (`hex`). |
| `data.items[].encoding` | "ascii" \| "hex" |  |
| `data.items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | Line ending added after the value. |
| `data.items[].hexPreview` | string | The exact bytes sent, as spaced hex (`2A 53 0A`). |

```json
{
  "data": {
    "id": "sertpl_2b3c4d5e6f7a8b9c",
    "spaceId": "space_1a2b3c4d5e6f7a8b",
    "name": "Sony Bravia",
    "model": "FW-55BZ35",
    "nodeId": null,
    "createdAt": "2026-09-28T09:00:00.000Z",
    "updatedAt": "2026-09-28T09:00:00.000Z",
    "items": [
      {
        "id": "sti_3c4d5e6f7a8b9c0d",
        "name": "Power on",
        "value": "*SCPOWR0000000000000001",
        "encoding": "ascii",
        "eol": "lf",
        "hexPreview": "2A 53 43 50 4F 57 52 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 0A"
      }
    ]
  }
}
```

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 422: `name` is missing, `invalid_node` (the location is not in this workspace), or a command is not valid (no name, no value, too long, no bytes, a duplicate id, over 200 commands); `message` names it.

| 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/serial-templates/{id}

Get a serial command template

Get one RS232 command template, including a preview of the exact bytes each command will send to the device.

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

Parameters:

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

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

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | SerialTemplate | A saved set of RS232 commands for one panel model. |
| `data.id` | string | Serial template id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.model` | string \| null | Free-text panel model (`Sony Bravia FW-series`). |
| `data.nodeId` | string \| null | Home location; null = workspace root. |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.items` | array of object |  |
| `data.items[].id` | string | Command id. Kept across edits, so saved buttons that name it keep working. |
| `data.items[].name` | string |  |
| `data.items[].value` | string | The command: literal text (`ascii`) or hex digits (`hex`). |
| `data.items[].encoding` | "ascii" \| "hex" |  |
| `data.items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | Line ending added after the value. |
| `data.items[].hexPreview` | string | The exact bytes sent, as spaced hex (`2A 53 0A`). |

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 serial template 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/serial-templates/{id}

Update a serial command template

Update an RS232 command template's name, model, organization node, or list of commands. Existing command IDs are preserved, so anything referencing a specific command continues to work.

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

Parameters:

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

Request body (`application/json`):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | no | Required on create. Cut to 120 characters. |
| `model` | string \| null | no |  |
| `nodeId` | string \| null | no | Home location; null = workspace root. |
| `items` | array of object | no | The commands, at most 200. On update the list replaces the stored one. |
| `items[].id` | string | no | Keep an existing command's id; omit to get a new one. |
| `items[].name` | string | yes |  |
| `items[].value` | string | yes | At most 512 characters, and it must give at least one byte. |
| `items[].encoding` | "ascii" \| "hex" | no | Default `ascii`. An unknown value is read as `ascii`. |
| `items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | no | Default `none`. An unknown value is read as `none`. |

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

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | SerialTemplate | A saved set of RS232 commands for one panel model. |
| `data.id` | string | Serial template id. |
| `data.spaceId` | string |  |
| `data.name` | string |  |
| `data.model` | string \| null | Free-text panel model (`Sony Bravia FW-series`). |
| `data.nodeId` | string \| null | Home location; null = workspace root. |
| `data.createdAt` | string | ISO-8601 timestamp (UTC). |
| `data.updatedAt` | string | ISO-8601 timestamp (UTC). |
| `data.items` | array of object |  |
| `data.items[].id` | string | Command id. Kept across edits, so saved buttons that name it keep working. |
| `data.items[].name` | string |  |
| `data.items[].value` | string | The command: literal text (`ascii`) or hex digits (`hex`). |
| `data.items[].encoding` | "ascii" \| "hex" |  |
| `data.items[].eol` | "none" \| "cr" \| "lf" \| "crlf" | Line ending added after the value. |
| `data.items[].hexPreview` | string | The exact bytes sent, as spaced hex (`2A 53 0A`). |

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: No `screen.edit` at the destination location.

| 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 serial template 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: An empty `name`, `invalid_node` (the destination is not in this workspace), or a command is not valid; `message` names it.

| 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/serial-templates/{id}

Delete a serial command template

Delete an RS232 command template. Commands already queued using this template are unaffected, because they carry their own fully expanded bytes rather than a reference to the template.

**Notes.**
- Answers `{ data: { ok: true } }`, not the `{ id, deleted: true }` most other deletes return. There is no restore route.

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

Parameters:

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

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

Response 200: Success.

| Field | Type | Description |
| --- | --- | --- |
| `data` | object |  |
| `data.ok` | 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 serial template 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. |
