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.
/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"
} /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"
} /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.,apiordashboard).
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"
}
] /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.
/v1/meetings/{public_id}/host-link
Generate a secure, single-use, or dynamic host token and corresponding link for a meeting room. Host links generated via this endpoint expire in 2 hours.
Response Example (200 OK)
{
"host_url": "https://meet.covekit.net/join/mtg_7z9k1m2p4q8r?host_token=cvk_host_tok_9a2b...",
"host_token": "cvk_host_tok_9a2b..."
} /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');
}
});