CoveKit

API & Integration Developer Guide

CoveKit provides a secure, developer-friendly WebRTC media plane infrastructure designed to route low-latency video and audio streams, manage lobby states, and transcribe spoken content automatically in real-time.

This guide walks you through programmatically creating, retrieving, ending, and fetching transcripts for CoveKit meeting rooms.


Authentication

Authenticate API requests by including your project's secret API key as the value of the X-API-Key header:

X-API-Key: cvk_development_yourkeyhere...

API keys are generated and revoked directly in the Developer Console.


POST

/v1/meetings

Call this endpoint from your backend server to create meeting rooms on demand.

Request JSON Body Parameters

Parameter Type Required Description
title string Optional Friendly title for the meeting room.
max_participants number Optional Max peak concurrent peers allowed (default is 15).
passcode string Optional If specified, locks the meeting room so peers must provide a matching passcode to join. Masks public lookups.
reusable boolean Optional If true, allows joining the room repeatedly even after sessions end (default false).
join_mode string Optional Specifies the join mode. Must be either 'open' (peers join immediately) or 'host_approval' (peers wait in lobby until admitted). Defaults to 'host_approval'.
meeting_mode string Optional Specifies the meeting mode. Must be either 'normal' (both audio and video permitted) or 'audio_only' (camera disabled, screen share permitted). Defaults to 'audio_only'.
auto_record boolean Optional If true, the meeting automatically starts recording as soon as the first participant joins. Hides manual recording controls in the UI. Defaults to false.
starts_at string Optional ISO 8601 UTC datetime string representing when the meeting starts. If set, participants are blocked from joining earlier than 15 minutes before this start time. Ignored if reusable is true.
ends_at string Optional ISO 8601 UTC datetime string representing when the meeting expires. Once this time has passed, new participants will be blocked from joining, though active participants inside are not booted. Ignored if reusable is true.
metadata object Optional Key-value pair map (JSON object) of up to 10 strings for your own custom indexing and usage.

Request Example

{
  "title": "Design Alignment Sync",
  "max_participants": 15,
  "reusable": false,
  "join_mode": "host_approval",
  "meeting_mode": "normal",
  "auto_record": true
}

Response Example (201 Created)

{
  "id": "8f8bde4f-2df3-4c91-9cb6-26dfd287bc6e",
  "public_id": "mtg_7z9k1m2p4q8r",
  "join_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r",
  "host_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r?host_token=cvk_host_tok_4f7e...",
  "title": "Design Alignment Sync",
  "status": "active",
  "max_participants": 15,
  "starts_at": null,
  "ends_at": null,
  "reusable": false,
  "join_mode": "host_approval",
  "meeting_mode": "normal",
  "created_at": "2026-07-07T17:26:42Z"
}

GET

/v1/meetings/{public_id}

Retrieve details, status, and join URLs of a specific meeting using its unique public_id.

Response Example (200 OK)

{
  "id": "8f8bde4f-2df3-4c91-9cb6-26dfd287bc6e",
  "public_id": "mtg_7z9k1m2p4q8r",
  "join_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r",
  "host_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r?host_token=cvk_host_tok_4f7e...",
  "title": "Design Alignment Sync",
  "status": "active",
  "max_participants": 50,
  "starts_at": null,
  "ends_at": null,
  "reusable": false,
  "join_mode": "host_approval",
  "meeting_mode": "normal",
  "created_at": "2026-07-07T17:26:42Z"
}

GET

/v1/meetings

Retrieve a list of all current and historical meetings associated with the active project.

Query Parameters

  • limit (optional) — Maximum number of meetings to return (default: 100, max: 100).
  • offset (optional) — Number of meetings to skip before returning (default: 0).
  • source (optional) — Filter by source (e.g., api or dashboard).

Response Example (200 OK)

[
  {
    "id": "8f8bde4f-2df3-4c91-9cb6-26dfd287bc6e",
    "public_id": "mtg_7z9k1m2p4q8r",
    "join_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r",
    "host_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r?host_token=cvk_host_tok_4f7e...",
    "title": "Design Alignment Sync",
    "status": "active",
    "max_participants": 50,
    "starts_at": null,
    "ends_at": null,
    "reusable": false,
    "join_mode": "host_approval",
    "meeting_mode": "normal",
    "created_at": "2026-07-07T17:26:42Z"
  }
]

POST

/v1/meetings/{public_id}/end

End an ongoing meeting room immediately. This marks the meeting status as ended and closes all active participant sessions.

Response Format (200 OK)

Returns a status code 200 OK with an empty response body.



GET

/v1/meetings/{public_id}/transcripts

Retrieve all raw transcripts saved for this meeting. Since recurring meetings can be recorded multiple times, this returns a list of all occurrences ordered by creation time.

Response Example (200 OK)

[
  {
    "id": "76161405-b006-444a-a30f-b118dbb29849",
    "meeting_id": "4d161d99-ca91-4cbf-82cb-23df40cc1112",
    "raw_transcript": "[00:03] Alice: Hello everyone\n[00:07] Bob: Let's start the sync\n",
    "created_at": "2026-07-07T20:00:00.000Z"
  }
]

Iframe Embed (Complete UI)

The simplest way to integrate CoveKit video rooms is by embedding our pre-built responsive UI widget inside an iframe. Simply direct the iframe to your meeting room URL and pass configuration options as query parameters.

<iframe
  src="https://meet.covekit.com/m/lobby-room?embed=true&autoJoin=true&displayName=Satoshi&mic=on&cam=off"
  allow="camera; microphone; display-capture; fullscreen"
  style="width: 100%; height: 600px; border: none; border-radius: 8px;"
></iframe>

Supported Query Parameters

Parameter Type Description
embed boolean Required. Sets full-bleed mode and hides outer headers/menus.
autoJoin boolean Bypasses the lobby setup screen and enters the meeting automatically.
displayName string Prepopulates user name (required if autoJoin is true).
mic on | off Default microphone starting toggle.
cam on | off Default camera starting toggle.

Client-Side SDK (Custom UI)

For complete layout flexibility, install the headless covekit package from npm and connect directly to the WebRTC media plane using our programmatic client.

1. Install Package

npm install covekit

2. Sync Media Streams & Handshakes

import { CoveKitClient, CoveKitRoom } from 'covekit';

const client = new CoveKitClient();

// 1. Join public meeting session to get join token
const session = await client.joinPublicMeeting('lobby-room', 'Alice');

// 2. Negotiate WebRTC media transports
const room = new CoveKitRoom(client, {
  onConnected: (info) => {
    room.publishLocalMedia(true, true);
  },
  onLocalStream: (stream) => {
    document.getElementById('local-video').srcObject = stream;
  },
  onRemoteTrack: (track, peerId, kind) => {
    const stream = new MediaStream([track]);
    document.getElementById(`peer-${peerId}`).srcObject = stream;
  }
});

await room.join(session.token, session.ice_servers);

Webhook Event Structure

When events occur in your meetings, CoveKit sends an HTTP POST request to your configured Webhook URL. The payload contains the event type and its associated data, including any custom metadata you provided when creating the meeting.

{
  "event_id": "evt_abc123",
  "created_at": "2026-06-21T10:00:00Z",
  "event": {
    "type": "room_ended",
    "payload": {
      "meeting_id": "8f8bde4f-2df3-4c91...",
      "duration_seconds": 3600
    }
  },
  "metadata": {
    "student_id": "usr_9921"
  }
}

Verifying Webhook Signatures

To ensure requests are authentically from CoveKit and prevent replay attacks or spoofing, every webhook payload is cryptographically signed. The signature is computed using HMAC-SHA256 with your project's Webhook Secret and is passed in the X-CoveKit-Signature header.

const crypto = require('crypto');

app.post('/api/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const payload = req.body.toString();
  const signatureHeader = req.headers['x-covekit-signature'];
  const webhookSecret = process.env.COVEKIT_WEBHOOK_SECRET;

  // Compute the HMAC digest
  const hmac = crypto.createHmac('sha256', webhookSecret);
  const digest = hmac.update(payload).digest('hex');

  // Verify the signature matches securely
  if (crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(signatureHeader))) {
    console.log("Webhook verified!", JSON.parse(payload));
    res.status(200).send('OK');
  } else {
    console.error("Invalid signature!");
    res.status(401).send('Unauthorized');
  }
});