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