Brix Proof API

The proof API from Brix — 6 operation(s) for proof.

Operations 6

GET /v1/proof Get a proof-of-play report #
GET /v1/proof/events List proof-of-play events #
GET /v1/proof/export Export verified proof of play #
GET /v1/proof/keys List a screen's signing keys #
POST /v1/proof/keys/{keyId}/revoke Revoke a screen's signing key #
POST /v1/proof/verify-bundle Verify a proof-of-play export #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/brixsignage-com:brixsignage-com-proof-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

brixsignage-com-proof-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Brix Proof API
  version: '1'
  summary: 'Control plane for Brix digital signage: screens, content, playlists, schedules, casts and emergencies.'
  description: 'Generated from the route table the API actually mounts

    (`apps/api/routes.snapshot.json`), the description each route is required to

    carry (`tests/contracts/route-registry.json`), and request/response schemas

    (`apps/api/src/openapi/`). CI enforces all three, so this document cannot list a

    route that does not exist or omit one that does.


    **Schemas.** 447 operations carry request and response schemas

    (`x-brix-schema: verified`). Each is checked in CI against the response the

    real handler returns — a missing, mistyped or undeclared field fails the build.

    The remaining operations are route-level only (`x-brix-schema: none`): their

    path, method, permission and purpose are exact, but the shape of `data` is not

    yet modelled, and we would rather say so than publish a schema that validates

    against nothing. Objects are open: a new field is not a breaking change.


    **Envelope.** Success bodies are `{ "data": … }`. Failures are

    `{ "error": "", "message": "…" }`, plus `requestId` on a 5xx.

    Many list routes page opt-in (see each operation): pass `?limit=` and

    follow `nextCursor` via `?cursor=` until it is null.


    **Authentication.** `Authorization: Bearer ` with an API key

    (`ak_…`, created in the console under Settings → API & MCP) or a user session. An

    API key carries a creator-chosen set of `resource.verb` permissions and may be

    pinned to one location''s subtree; a key can never be granted a permission its

    creator does not hold. The permission an operation needs is in

    `x-brix-permission` and in its security requirement.


    **Tenancy.** Every request resolves to one workspace. A resource belonging to

    another tenant returns 404, never 403, so a response never confirms that an

    account exists.


    **Rate limits.** A 429 carries `Retry-After`; a 503 `database_busy` means retry

    after the `Retry-After` interval.'
servers:
- url: https://api.brixsignage.com
  description: Production
security:
- bearerAuth: []
tags:
- name: proof
paths:
  /v1/proof:
    get:
      operationId: getProofOfPlay
      tags:
      - proof
      summary: Get a proof-of-play report
      description: 'Get proof-of-play totals for a date range, broken down by content item and by screen, including digital-out-of-home verification fields. Use the `from` and `to` query parameters to set the date range.


        Counts what played, where and for how long, over a time window. Only screens the caller can see are counted.'
      x-brix-permission: playback-log.view
      x-brix-schema: verified
      parameters:
      - name: from
        in: query
        required: false
        schema:
          type: string
        description: 'Window start (ISO-8601). Default: the start of the retention window.'
      - name: to
        in: query
        required: false
        schema:
          type: string
        description: 'Window end (ISO-8601). Default: now.'
      - name: screenId
        in: query
        required: false
        schema:
          type: string
        description: Only this screen.
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ProofOfPlayReport'
                required:
                - data
        '401':
          description: Missing, expired or revoked bearer token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: The token lacks the permission this operation needs (see `x-brix-permission`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
      - bearerAuth:
        - playback-log.view
  /v1/proof/events:
    get:
      operationId: listProofEvents
      tags:
      - proof
      summary: List proof-of-play events
      description: 'List individual playback events, one per play, for a date range. The number of events returned is capped. For totals rolled up by content item and screen, use GET /v1/proof instead.


        **Notes.**

        - `rollup` sits beside `data`, outside the usual envelope.'
      x-brix-permission: playback-log.view
      x-brix-schema: verified
      x-brix-notes:
      - '`rollup` sits beside `data`, outside the usual envelope.'
      parameters:
      - name: from
        in: query
        required: false
        schema:
          type: string
        description: 'ISO-8601 start (default: the start of the report window).'
      - name: to
        in: query
        required: false
        schema:
          type: string
        description: 'ISO-8601 end (default: now).'
      - name: screenId
        in: query
        required: false
        schema:
          type: string
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        screenId:
                          type: string
                        screenName:
                          type: string
                          description: The screen id when the screen no longer exists.
                        contentKind:
                          type: string
                          description: '`media` when not reported.'
                        contentId:
                          type: string
                          description: '`unknown` when not reported.'
                        contentName:
                          type: string
                          description: '`Unknown content` when not reported.'
                        startedAt:
                          type: string
                          description: ISO-8601 timestamp (UTC).
                        durationSec:
                          type: integer
                        result:
                          type: string
                          enum:
                          - played
                          - skipped
                          - failed
                        reason:
                          anyOf:
                          - type: string
                          - type: 'null'
                      required:
                      - id
                      - screenId
                      - screenName
                      - contentKind
                      - contentId
                      - contentName
                      - startedAt
                      - durationSec
                      - result
                      - reason
                    description: One row per play, newest first (at most 2000), from screens the caller can see.
                  rollup:
                    type: array
                    items:
                      type: object
                      properties:
                        day:
                          type: string
                          description: '`YYYY-MM-DD`.'
                        screenId:
                          type: string
                        contentId:
                          type: string
                        plays:
                          type: integer
                        totalDurationMs:
                          type: integer
                        played:
                          type: integer
                        skipped:
                          type: integer
                        failed:
                          type: integer
                      required:
                      - day
                      - screenId
                      - contentId
                      - plays
                      - totalDurationMs
                      - played
                      - skipped
                      - failed
                    description: Daily totals for the part of the range older than the raw-event window; empty when `from` is inside it.
                required:
                - data
                - rollup
        '401':
          description: Missing, expired or revoked bearer token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: The token lacks the permission this operation needs (see `x-brix-permission`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
      - bearerAuth:
        - playback-log.view
  /v1/proof/export:
    get:
      operationId: exportProof
      tags:
      - proof
      summary: Export verified proof of play
      description: Downloads the plays in a date range with the signature and chain status of each play, a summary of counts, a SHA-256 hash of the bundle and a detached server signature. Use `from`, `to` and `screenId` to filter and `format=json` or `format=csv`. The newest 5,000 plays are included. Available only to workspaces with digital-out-of-home enabled; other workspaces get 404.
      x-brix-permission: playback-log.view
      x-brix-schema: none
      responses:
        2XX:
          description: 'Success. Body is `{ data: … }` unless the endpoint serves bytes. The shape of `data` is not yet modelled for this operation.'
        4XX:
          description: Client error. 404 rather than 403 for another tenant's resource, so account existence is not leaked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
      - bearerAuth:
        - playback-log.view
  /v1/proof/keys:
    get:
      operationId: listProofKeys
      tags:
      - proof
      summary: List a screen's signing keys
      description: Lists the proof-of-play signing keys that one screen has registered. `screenId` is required. Each key shows its key id, when it was first seen, the key it replaced and when it was revoked. Key material is never returned. Available only to workspaces with digital-out-of-home enabled.
      x-brix-schema: none
      responses:
        2XX:
          description: 'Success. Body is `{ data: … }` unless the endpoint serves bytes. The shape of `data` is not yet modelled for this operation.'
        4XX:
          description: Client error. 404 rather than 403 for another tenant's resource, so account existence is not leaked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/proof/keys/{keyId}/revoke:
    post:
      operationId: createProofKeyRevoke
      tags:
      - proof
      summary: Revoke a screen's signing key
      description: Marks one of a screen's signing keys as bad. Send the `screenId` in the body. From that time, plays signed with the key show as revoked, and the next new key from the screen registers as a replacement. Calling it again has no further effect. The change is recorded in the activity log.
      x-brix-schema: none
      parameters:
      - name: keyId
        in: path
        required: true
        schema:
          type: string
        description: Identifier for keyId.
      responses:
        2XX:
          description: 'Success. Body is `{ data: … }` unless the endpoint serves bytes. The shape of `data` is not yet modelled for this operation.'
        4XX:
          description: Client error. 404 rather than 403 for another tenant's resource, so account existence is not leaked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/proof/verify-bundle:
    post:
      operationId: createProofVerifyBundle
      tags:
      - proof
      summary: Verify a proof-of-play export
      description: 'Checks a downloaded proof-of-play export against the published signing keys: the bundle hash, the server signature, and the device signature and chain of each play. No credential is needed. Requests are rate limited, and a bundle can be at most 8 MB and 5,000 plays.'
      x-brix-schema: none
      responses:
        2XX:
          description: 'Success. Body is `{ data: … }` unless the endpoint serves bytes. The shape of `data` is not yet modelled for this operation.'
        4XX:
          description: Client error. 404 rather than 403 for another tenant's resource, so account existence is not leaked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        5XX:
          description: Server error. The body carries a `requestId` to quote to support.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: 'Machine-readable code: `unauthorized`, `forbidden`, `not_found`, `validation_error`, `conflict`, `rate_limited`, `internal_error`, …'
        message:
          description: Human-readable explanation. Safe to show an operator.
          type: string
        requestId:
          description: 'Present on 5xx: quote it to support.'
          type: string
      required:
      - error
      additionalProperties: {}
      description: Error envelope returned by every failing request.
    ProofOfPlayReport:
      type: object
      properties:
        totals:
          type: object
          properties:
            plays:
              type: integer
              description: Successful plays (neither skipped nor failed).
            skipped:
              type: integer
            failed:
              type: integer
            events:
              type: integer
              description: 'Every playback-end event: plays + skipped + failed.'
            uniqueContent:
              type: integer
            screensReporting:
              type: integer
          required:
          - plays
          - skipped
          - failed
          - events
          - uniqueContent
          - screensReporting
        byContent:
          type: array
          items:
            type: object
            properties:
              contentId:
                type: string
                description: '`unknown` when the player did not report one.'
              contentName:
                type: string
                description: Falls back to the id when no name was reported.
              contentKind:
                type: string
                description: '`media`, `app`, `creative`, …; `media` for days read from the daily rollup.'
              screenName:
                anyOf:
                - type: string
                - type: 'null'
                description: Set only when exactly one screen played it.
              played:
                type: integer
              skipped:
                type: integer
              failed:
                type: integer
              screenCount:
                type: integer
              totalDurationSec:
                type: integer
              firstAt:
                type: string
                description: ISO-8601 timestamp (UTC).
              lastAt:
                type: string
                description: ISO-8601 timestamp (UTC).
            required:
            - contentId
            - contentName
            - contentKind
            - screenName
            - played
            - skipped
            - failed
            - screenCount
            - totalDurationSec
            - firstAt
            - lastAt
          description: Per content, most successful plays first.
        screens:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
            required:
            - id
            - name
          description: Screens that reported in the window, by name.
        from:
          type: string
          description: ISO-8601 timestamp (UTC).
        to:
          type: string
          description: ISO-8601 timestamp (UTC).
        retentionDays:
          type: integer
          description: How far back raw play events exist; older days come from the daily rollup.
        truncated:
          type: boolean
          description: 'Always false: the whole window is counted.'
        fromRollup:
          type: boolean
          description: Part of the window was read from the daily rollup.
      required:
      - totals
      - byContent
      - screens
      - from
      - to
      - retentionDays
      - truncated
      - fromRollup
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An API key (`ak_…`) or a user session token. API keys carry `resource.verb` permissions.