Developers
VOS API & Webhooks
Integrate VOS sessions into your own helpdesk, CRM, or ticketing workflow. Create sessions from your systems, and get notified the moment one ends or a recording is ready.
Authentication
Generate an API token from Settings → API & webhooks (owners only). Tokens look like vos_live_… and are shown once at creation — store it somewhere safe.
Send it as a bearer token on every request:
Authorization: Bearer vos_live_xxxxxxxxxxxxxxxxxxxxxxxxRequests without a valid, unrevoked token get a 401 with { "error": "Missing or invalid API token." }. Every token is scoped to one organization — there is no cross-account access.
List sessions
GET /api/v1/sessionscurl https://vos.live/api/v1/sessions \
-H "Authorization: Bearer vos_live_xxxxxxxxxxxxxxxxxxxxxxxx"{
"sessions": [
{
"id": "session_8f2c1a90b6d4e123",
"name": "Front lobby printer",
"status": "ended",
"pin": "482917",
"minutesUsed": 12,
"startedAt": "2026-06-17T18:42:00.000Z",
"recordingEnabled": true,
"hasRecording": true,
"hasScreenshots": true,
"hasNotes": false,
"hostUrl": "https://vos.live/session/session_8f2c1a90b6d4e123",
"joinUrl": "https://vos.live/join/482917"
}
]
}Create a session
Useful for launching a support session directly from a ticket — drop the returned joinUrl into the customer's ticket or message, and the hostUrl into the technician's.
POST /api/v1/sessionscurl https://vos.live/api/v1/sessions \
-X POST \
-H "Authorization: Bearer vos_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"name": "Ticket #4821", "recordingEnabled": true}'All fields are optional:
{
"name": "Ticket #4821", // defaults to a timestamp-based name
"recordingEnabled": true, // defaults to false
"hostOnly": false // defaults to false
}Returns 201 with the same session shape as the list endpoint.
Get a session
GET /api/v1/sessions/:idSame shape as the list endpoint, plus notesText. Returns 404 if the session doesn't exist or belongs to a different organization.
Webhooks
Register an endpoint from Settings → API & webhooks. We'll POST a signed JSON payload to it for these events:
session.ended— fired when a session is ended, by a technician or automatically when the room closes.recording.ready— fired once a recording finishes processing and is available to play back.
Payload shape:
{
"type": "session.ended",
"createdAt": "2026-06-17T18:54:12.000Z",
"data": {
"sessionId": "session_8f2c1a90b6d4e123",
"sessionName": "Front lobby printer",
"minutesUsed": 12
}
}{
"type": "recording.ready",
"createdAt": "2026-06-17T18:54:20.000Z",
"data": {
"sessionId": "session_8f2c1a90b6d4e123",
"sessionName": "Front lobby printer",
"durationSeconds": 712
}
}Endpoints must be https://. We retry nothing — log delivery failures on your end and treat webhooks as best-effort notifications, not a guaranteed queue. Use the API to confirm session state if a delivery is ever missed.
Verifying webhook signatures
Every delivery includes an X-VOS-Signature header: an HMAC-SHA256 of the raw request body, hex-encoded, using the signing secret shown when you created the endpoint. The event type is also sent as X-VOS-Event.
const crypto = require("crypto");
function isValidVosWebhook(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader),
);
}Compute the HMAC over the exact raw bytes received — re-serializing parsed JSON before verifying will produce a different signature.
Need something the API doesn't cover yet?
SSO/SAML and broader API scopes are on our enterprise roadmap. Tell us what you're building and we'll help you get there.