Endpoint
POST/api/public/v1/meeting-agent/rooms
Two things happen server-side: livekit/create-room mints the room with a Google-Meet-style short code, then livekit/join-agent dispatches Vikash. If Vikash fails to join the response is a 502 with the partial room_url echoed so you can retry without leaking a half-provisioned room.
Request
Body (JSON, optional)
| Field | Type | Notes |
|---|---|---|
title | string | Display name for the room. Defaults to "Public API Meeting". |
max_participants | integer (1–50) | Hard cap on simultaneous attendees. Default 20, clamped to [1, 50]. |
flow_id | string | Optional. Conversation flow Vikash should follow. Omit for free-form. |
Response · 200
JSON
| Field | Type | Notes |
|---|---|---|
room_url | string | Google-Meet-style share URL: https://vaanilabs.in/meet/xxx-xxxx-xxx. Hand this to participants. |
room_name | string | The internal LiveKit room name. You only need this for server-side LiveKit SDK calls. |
host_token | string | Short-TTL JWT for the host seat. Gives mod controls (kick, mute) when used to connect to LiveKit directly. |
session_token | string | HMAC-signed surface token tying the room back to your api_key_id and usage row. Treat as opaque. |
expires_at | ISO 8601 string | When the host_token + session_token stop being accepted. |
surface | "meeting-agent" | Echoes the surface for client-side switching. |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Standard auth failure — see auth docs. |
| 402 | insufficient_balance | Wallet at zero, no autopay. |
| 403 | scope_denied | Key missing the meeting-agent scope. |
| 429 | rate_limited | Per-key budget exceeded. |
| 502 | upstream_error | LiveKit room creation OR Vikash dispatch failed. Body includes room_url if the room was created before dispatch failed. |
Examples
curl -X POST https://www.vaanilabs.in/api/public/v1/meeting-agent/rooms \
-H "Authorization: Bearer $VAANI_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "title": "Weekly standup", "max_participants": 10, "flow_id": null }'
# Response 200
# {
# "room_url": "https://vaanilabs.in/meet/abc-defg-hij",
# "room_name": "<livekit room name>",
# "host_token": "<short-lived JWT for the host seat>",
# "session_token": "<HMAC-signed surface token>",
# "expires_at": "2026-04-25T13:00:00.000Z",
# "surface": "meeting-agent"
# }const res = await fetch(
"https://www.vaanilabs.in/api/public/v1/meeting-agent/rooms",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VAANI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Weekly standup",
max_participants: 10,
}),
},
);
const { room_url, host_token } = await res.json();
// Send room_url to your participants. Use host_token to mint
// per-attendee tokens server-side, or just hand them the URL.
console.log("join here:", room_url);r = requests.post(
"https://www.vaanilabs.in/api/public/v1/meeting-agent/rooms",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"title": "Weekly standup", "max_participants": 10},
timeout=12,
)
r.raise_for_status()
data = r.json()
print("share:", data["room_url"]) # vaanilabs.in/meet/abc-defg-hij