Skip to content

API

The API is defined by the contract repository freedome_contract v1.0.0-rc.1 (pinned in this repo under fixtures/contract/, see fixtures/contract/PIN). The server serves the contract documents themselves, so names and shapes cannot drift.

Transport Endpoint Contract source
REST /api/v1/*; OpenAPI at /api/v1/openapi.json; Swagger UI /api/docs openapi/mediaserver.yaml
GraphQL POST / GET /api/v1/graphql; subscriptions over graphql-transport-ws (and legacy graphql-ws) on the same path graphql/mediaserver.graphql
WebSocket GET /api/v1/ws, sub-protocol freedome.v1 asyncapi/ws.yaml
socket.io path /socket.io/, namespace /v1 (EIO v4) asyncapi/socketio.yaml
OSC UDP / TCP 7000, replies 7001 osc/addresses.yaml — see OSC
gRPC unix:///run/freedome/mediaserver.sock, optional TCP 50062 proto/mediaserver/freedome/mediaserver/v1/mediaserver.proto (this repo)
Health /health, /ready, /metrics (Prometheus, freedome_mediaserver_*) —

Authorization: Bearer <token> where the token is an API key fdk_<id>_<secret> (POST /api/v1/api-keys), a local session JWT (POST /api/v1/auth/session, refresh with rotation) or a cloud token exchanged at POST /api/v1/auth/token-exchange. Apps pair with a 6-digit code (POST /api/v1/auth/pairings, approved by an operator). Roles: guest, operator, admin, superadmin = scope bundles; every operation declares its scope in the OpenAPI. WebSocket: hello.token, the Authorization header or ?access_token=; socket.io: auth: {token}; GraphQL WS: connection_init.payload.authorization; gRPC: bearer metadata, Unix peer credentials or mTLS; OSC: no tokens — per-listener CIDR allow-list and role.

WebSocket call, socket.io call, GraphQL mutations, gRPC OperationsService.Call and OSC addresses run the same REST operation (operationId) in-process: same scopes, validation and errors. Errors are RFC 9457 problem objects (application/problem+json, code from the contract catalogue) and are carried as GraphQL extensions.problem, WS / socket.io error, gRPC status + freedome-problem-bin trailer, OSC /freedome/v1/error ,sss.

One topic tree (events/topics.yaml): venues/{v}/players/{p}, venues/{v}/output, venues/{v}/displays/{d}, venues/{v}/calibration/jobs/{j}, assets/{a}, shows/{s}, engines/{name} (visual@node-1 on multi-node installations), system/health, … Subscriptions accept + / # wildcards. Every event has a monotonically increasing seq; clients resume with sinceSeq (ring buffer 10 000 events / 10 min, then resync). History: GET /api/v1/events?topics=…&sinceSeq=….

Large media use tus 1.0 at /api/v1/uploads (chunks ≤ 95 MB, resumable, sha256 checksums), then POST /api/v1/assets {uploadId}. Simple multipart upload is accepted up to 100 MB.