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.partialResultsboolean—Emit partial segments
options.punctuationboolean—Add punctuation
options.profanityFilterboolean—Filter 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"
}