GDPR API
GDPR endpoints in the Brix REST API for digital signage: 3 operations (POST, GET). Each lists its path, auth, required permission and a curl example.
Base URL https://api.brixsignage.com. Send Authorization: Bearer $BRIX_API_KEY unless an operation says No auth. The permission chip names what the key must hold. See Authentication and scopes, Errors and rate limits and Pagination.
POST/v1/gdpr/erase
Permanently anonymizes a user's profile and deletes their associated personal data, including linked identities, passkeys, sessions, and pending email verifications, to satisfy a right-to-be-forgotten request. You cannot erase your own account or the last remaining account owner. Only an account owner can do this to an owner, and you cannot do it to a person who holds a permission you do not hold. An API key is never an owner.
**Notes.**
- Irreversible. Unlike POST /v1/users/:id/erase, the person does not have to be deactivated first.
Request body application/json
| Field | Type | Required | Description |
|---|---|---|---|
userId | string | yes |
curl -X POST "https://api.brixsignage.com/v1/gdpr/erase" \
-H "Authorization: Bearer $BRIX_API_KEY" \
-H "Content-Type: application/json" Response 200 Success.
| Field | Type | Description |
|---|---|---|
data | object | |
data.userId | string | |
data.erased | 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 You do not hold the permission for the whole workspace (a grant at one location, or in a franchise workspace, is not enough). Also `owner_required` or `outranked`: the person is an owner, or holds a permission you do not hold.
| 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 person 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 `cant_erase_self` or `last_owner`.
| 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 `userId` is missing.
| 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/gdpr/export
Assembles a data subject access request export for the whole workspace: every person, screen and piece of content, and the last 365 days of the activity log, as one JSON file with secret values withheld. The key or person must have billing.edit for the whole workspace. Each table is capped; complete is false when one was cut.
**Notes.**
- Exports the whole workspace, not one person: every person, screen and piece of content, and the last 365 days of the activity log.
- No { data } envelope: the body is the export file (Content-Disposition: attachment).
- Credentials are never exported: their columns are kept with null or a [secret; not exported] / [encrypted; not exported] marker.
curl "https://api.brixsignage.com/v1/gdpr/export" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200 Success.
| Field | Type | Description |
|---|---|---|
schemaVersion | 1 | |
generatedAt | string | ISO-8601 timestamp (UTC). |
subject | object | |
subject.spaceId | string | The workspace exported. |
subject.requestedByUserId | string | null | Null for an API key. |
limits | object | |
limits.perTable | integer | At most this many rows per table. |
limits.auditEvents | integer | At most this many activity log events. |
limits.auditWindowDays | integer | Activity log events from this many days back. |
truncated | object | The tables cut at the limit; empty when none. |
complete | boolean | False when a table was cut at the limit. |
tables | object | |
tables.workspace | object | null | The workspace record, every column (the Screen Lock PIN hash replaced by `kioskHasGlobalPin` inside `prefs`). |
tables.users | array of object | |
tables.users[].id | string | |
tables.users[].name | string | |
tables.users[].email | string | |
tables.users[].title | string | null | |
tables.users[].phone | string | null | |
tables.users[].status | string | |
tables.users[].lastLoginAt | string | null | |
tables.users[].emailVerifiedAt | string | null | |
tables.users[].createdAt | string | ISO-8601 timestamp (UTC). |
tables.users[].updatedAt | string | ISO-8601 timestamp (UTC). |
tables.users[].deletedAt | string | null | |
tables.screens | array of object | Every column; credentials withheld, and `kioskHasCustomPin` / `kioskHasRecovery` added. |
tables.media | array of object | |
tables.playlists | array of object | |
tables.schedules | array of object | |
tables.layouts | array of object | |
tables.creatives | array of object | |
tables.appInstances | array of object | |
tables.dataSources | array of object | `config` is `[encrypted; not exported]` (or null). |
tables.banners | array of object | |
tables.auditEvents | array of object | Newest first. |
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 You do not hold the permission for the whole workspace (a grant at one location, or in a franchise workspace, is not enough).
| 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/gdpr/export
Same as the GET version of this operation: assembles a data subject access request export for the whole workspace as one JSON file, with secret values withheld. The key or person must have billing.edit for the whole workspace. Takes no request body.
**Notes.**
- Exports the whole workspace, not one person: every person, screen and piece of content, and the last 365 days of the activity log.
- No { data } envelope: the body is the export file (Content-Disposition: attachment).
- Credentials are never exported: their columns are kept with null or a [secret; not exported] / [encrypted; not exported] marker.
- Takes no body; the same export as the GET.
curl -X POST "https://api.brixsignage.com/v1/gdpr/export" \
-H "Authorization: Bearer $BRIX_API_KEY" Response 200 Success.
| Field | Type | Description |
|---|---|---|
schemaVersion | 1 | |
generatedAt | string | ISO-8601 timestamp (UTC). |
subject | object | |
subject.spaceId | string | The workspace exported. |
subject.requestedByUserId | string | null | Null for an API key. |
limits | object | |
limits.perTable | integer | At most this many rows per table. |
limits.auditEvents | integer | At most this many activity log events. |
limits.auditWindowDays | integer | Activity log events from this many days back. |
truncated | object | The tables cut at the limit; empty when none. |
complete | boolean | False when a table was cut at the limit. |
tables | object | |
tables.workspace | object | null | The workspace record, every column (the Screen Lock PIN hash replaced by `kioskHasGlobalPin` inside `prefs`). |
tables.users | array of object | |
tables.users[].id | string | |
tables.users[].name | string | |
tables.users[].email | string | |
tables.users[].title | string | null | |
tables.users[].phone | string | null | |
tables.users[].status | string | |
tables.users[].lastLoginAt | string | null | |
tables.users[].emailVerifiedAt | string | null | |
tables.users[].createdAt | string | ISO-8601 timestamp (UTC). |
tables.users[].updatedAt | string | ISO-8601 timestamp (UTC). |
tables.users[].deletedAt | string | null | |
tables.screens | array of object | Every column; credentials withheld, and `kioskHasCustomPin` / `kioskHasRecovery` added. |
tables.media | array of object | |
tables.playlists | array of object | |
tables.schedules | array of object | |
tables.layouts | array of object | |
tables.creatives | array of object | |
tables.appInstances | array of object | |
tables.dataSources | array of object | `config` is `[encrypted; not exported]` (or null). |
tables.banners | array of object | |
tables.auditEvents | array of object | Newest first. |
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 You do not hold the permission for the whole workspace (a grant at one location, or in a franchise workspace, is not enough).
| 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. |