Skip to content
Reference

Get started

Overview

Control plane API

Health, token minting and the avatar provider catalogue, on the Node service.

The only process holding the media server's signing key. Everything else that needs a token asks it.

Base: $LIVEGRID_CONTROL_URL. Implemented in src/server.ts.

Authentication. Authorization: Bearer $UDK_SECRET, compared in constant time — === on a secret leaks its length and prefix through timing, and doing it properly costs three lines.

UDK_SECRET unset authorises every request. That is intended for local development and the process warns about it on boot. Nothing stops it running that way in production, where it is a public token-minting API.

GET /health#

Unauthenticated on purpose — a platform health check carries no bearer token.

{ "status": "ok", "version": "0.1.0",
  "mediaPlane": "reachable", "checkedAt": "2026-09-10T06:12:44.101Z" }

status is degraded, never 503, when the media plane cannot be reached. Health and status

POST /token#

{ "room": "support-8f3a21", "identity": "daniel", "role": "human", "ttlSeconds": 3600 }

room and identity are required. role is one of human, agent, observer and defaults to human; anything else is a 400 that names the ones it knows.

{ "token": "eyJhbGciOi...", "url": "wss://sg.example.com",
  "room": "support-8f3a21", "identity": "daniel",
  "expiresAt": "2026-09-10T07:12:44.000Z" }

A caller names a role; it never supplies a grant. A caller that could assemble its own could give a browser participant canPublishData and drive the agent. Access tokens and grants

StatusMeans
400missing room/identity, or an unknown role
401wrong or missing bearer
503LIVEKIT_API_KEY / LIVEKIT_API_SECRET unset here

GET /providers/avatar#

QueryEffect
available=trueonly vendors whose key is set in this environment
{ "providers": [ { "id": "bithuman", "label": "bitHuman",
                   "usdPerMinute": 0.04, "apiKeyEnv": "BITHUMAN_API_KEY",
                   "nodeSupport": false, "caveat": "..." } ],
  "count": 1 }

The catalogue reports which providers are available by checking whether a key is set. It never returns the value.

GET /providers/avatar/<id>#

One provider, or 404 with a message naming the id. Validate a choice here before a call is attempted rather than during one — a 404 you can handle, a 401 mid-conversation you cannot.

POST /mcp#

The JSON-RPC surface. MCP tools

Everything else#

404 {"error": "No route for <METHOD> <path>"}. Request bodies are capped at 64 KB.

Up nextMCP tools