Skip to content

API Reference

All endpoints are prefixed with /v1. Requests require the X-API-Key header (your API_SECRET).

Authentication

HeaderValue
X-API-KeyYour server-side API_SECRET

Health

GET /v1/health

Returns server status and enabled capabilities.

Response 200

json
{
  "status": "ok",
  "version": "0.1.0",
  "capabilities": {
    "transcriptionLive": false,
    "transcriptionPost": false
  }
}

Token

POST /v1/token

Issue a LiveKit access token for a participant.

Body

FieldTypeRequiredDescription
roomIdstringYesTarget room name
userIdstringYesUnique participant identity
namestringYesDisplay name
rolehost | moderator | participant | viewerYesDetermines grants
metadataobjectNoArbitrary JSON attached to the participant

Role grants

RolePublishSubscribeMute othersRoom admin
hostYesYesYesYes
moderatorYesYesYesNo
participantYesYesNoNo
viewerNoYesNoNo

Response 200

json
{
  "token": "<jwt>",
  "url": "wss://your-livekit-host",
  "expiresAt": "2025-01-01T12:30:00.000Z"
}

POST /v1/token/refresh

Re-issue a token with the same body schema as POST /v1/token. Use this to extend a session before expiry.


Rooms

POST /v1/rooms

Create a new room.

Body

FieldTypeRequiredDescription
namestringYesRoom name / ID
maxParticipantsintegerNoHard cap on participants
emptyTimeoutintegerNoSeconds before empty room is closed
metadatastringNoArbitrary string stored on the room

Response 201 — LiveKit Room object.


GET /v1/rooms

List all active rooms.

Response 200

json
{ "rooms": [ /* LiveKit Room objects */ ] }

GET /v1/rooms/:roomId

Get a single room. Returns 404 if not found.


DELETE /v1/rooms/:roomId

Close and delete a room. Returns 204.


Participants

GET /v1/rooms/:roomId/participants

List all participants in a room.

Response 200

json
{ "participants": [ /* LiveKit ParticipantInfo objects */ ] }

DELETE /v1/rooms/:roomId/participants/:participantId

Remove (kick) a participant. Returns 204.


POST /v1/rooms/:roomId/participants/:participantId/mute

Server-side mute a participant's track.

Body

FieldTypeRequiredDescription
trackSidstringYesSID of the track to mute

Response 204


Recording

Recordings are stored as MP4 files in MinIO under the MINIO_BUCKET bucket.

POST /v1/rooms/:roomId/recording/start

Start a room composite recording. Idempotent — returns 200 with status: "already_recording" if already active.

Response 201

json
{
  "egressId": "EG_xxx",
  "roomId": "my-room",
  "status": "recording",
  "startedAt": "2025-01-01T12:00:00.000Z"
}

POST /v1/rooms/:roomId/recording/stop

Stop the active recording. Returns 404 if no recording is running.

Response 200

json
{ "status": "stopped", "stoppedAt": "2025-01-01T12:30:00.000Z" }

GET /v1/rooms/:roomId/recording

Get current recording status.

Response 200

json
{
  "isRecording": true,
  "egressId": "EG_xxx",
  "startedAt": "2025-01-01T12:00:00.000Z"
}

Ingress

Ingress lets external streams (RTMP / WHIP) publish into a room.

POST /v1/rooms/:roomId/ingress

Create an ingress endpoint.

Body

FieldTypeDefaultDescription
typertmp | whiprtmpIngress protocol
participantNamestring"Ingress Stream"Display name in room
participantIdentitystringautoUnique identity

Response 201 — LiveKit IngressInfo object (includes url and streamKey).


GET /v1/rooms/:roomId/ingress

List active ingress endpoints for a room.

Response 200

json
{ "ingress": [ /* IngressInfo objects */ ] }

DELETE /v1/rooms/:roomId/ingress/:ingressId

Delete an ingress endpoint. Returns 204.


Transcription (Live)

Requires the stt-live Docker Compose profile. Endpoints return 503 when the add-on is not running.

POST /v1/rooms/:roomId/transcription/start

Start live transcription for a room. Idempotent.

Body

FieldTypeDefaultDescription
languagestring"en-US"BCP-47 language code
participantsRecord<sid, name>Speaker identity map
options.partialResultsbooleanEmit partial segments
options.punctuationbooleanAdd punctuation
options.profanityFilterbooleanFilter profanity

Response 201

json
{
  "transcriptionId": "tr_abc123",
  "roomId": "my-room",
  "status": "active",
  "language": "en-US",
  "startedAt": "2025-01-01T12:00:00.000Z"
}

POST /v1/rooms/:roomId/transcription/stop

Stop live transcription.

Response 200

json
{
  "transcriptionId": "tr_abc123",
  "status": "stopped",
  "stoppedAt": "2025-01-01T12:30:00.000Z",
  "segmentCount": 42
}

GET /v1/rooms/:roomId/transcription

Retrieve transcription segments.

Query params

ParamDescription
sinceISO timestamp — only return segments after this time
formatSet to text for a plain-text formatted transcript

PATCH /v1/rooms/:roomId/transcription/speakers

Update the speaker identity map mid-session.

Body

json
{ "participants": { "<trackSid>": "Alice" } }

Response 204


Transcription (Post-call)

Requires the stt-post Docker Compose profile.

POST /v1/recordings/:recordingId/transcribe

Queue a post-call transcription job.

Body

FieldTypeDefaultDescription
languagestring"en-US"BCP-47 language code
participantsRecord<sid, name>Speaker map

Response 202

json
{
  "transcriptionId": "tr_abc123",
  "recordingId": "EG_xxx",
  "status": "queued",
  "queuedAt": "2025-01-01T12:00:00.000Z"
}

GET /v1/transcriptions

List all post-call transcriptions.


GET /v1/transcriptions/:transcriptionId

Get a single transcription by ID. Returns 404 if not found.


DELETE /v1/transcriptions/:transcriptionId

Delete a transcription and all its segments. Returns 204.


Webhooks

GET /v1/webhooks

List all registered webhooks. Secrets are masked as ***.


POST /v1/webhooks

Register a new webhook.

Body

FieldTypeRequiredDescription
urlstring (URI)YesDelivery endpoint
eventsstring[]NoEvent filter (defaults to ["*"])
secretstringNoHMAC signing secret (auto-generated if omitted)

Available events

room_created room_closed participant_joined participant_left track_published recording_started recording_stopped ingress_started ingress_stopped transcription_completed *

Response 201 — Webhook config including the plaintext secret (only returned once).


GET /v1/webhooks/:webhookId

Get a single webhook. Secret masked.


PATCH /v1/webhooks/:webhookId

Update url and/or events.


DELETE /v1/webhooks/:webhookId

Delete a webhook. Returns 204.


POST /v1/webhooks/:webhookId/test

Send a test delivery to the webhook URL.

Response 200

json
{ "delivered": true, "statusCode": 200 }

Error format

All error responses use RFC 9457 Problem Details:

json
{
  "type": "https://rtcstack.dev/errors/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Room not found"
}