Desarrolladores
API y webhooks de VOS
Las cuentas del plan Company pueden integrar las sesiones de VOS en una mesa de ayuda, un CRM o un flujo de tickets, crear sesiones desde sus sistemas y recibir avisos cuando termina una sesión o una grabación está lista.
Autenticación
Genera un token de API desde Configuración > API (solo para propietarios del plan Company). Los tokens tienen el formato vos_live_… y solo se muestran una vez, al crearlos; guárdalos en un lugar seguro.
Envíalo como token de portador (bearer) en cada solicitud:
Authorization: Bearer vos_live_xxxxxxxxxxxxxxxxxxxxxxxxLas solicitudes sin un token válido y vigente reciben un 401 con { "error": "Missing or invalid API token." }. Cada token está limitado a una sola organización: no hay acceso entre cuentas.
Listar sesiones
GET /api/v1/sessionscurl https://vos.live/api/v1/sessions \
-H "Authorization: Bearer vos_live_xxxxxxxxxxxxxxxxxxxxxxxx"{
"sessions": [
{
"id": "session_8f2c1a90b6d4e123",
"organizationId": "org_123",
"name": "Front lobby printer",
"status": "ended",
"pin": "VO4829",
"minutesUsed": 12,
"startedAt": "2026-06-17T18:42:00.000Z",
"endedAt": "2026-06-17T18:54:12.000Z",
"recordingEnabled": true,
"hostOnly": false,
"hostCameraShare": false,
"hasRecording": true,
"hasScreenshots": true,
"hasNotes": false,
"host": {
"userId": "user_123",
"displayName": "Morgan Lee",
"email": "morgan@example.com"
},
"hostUrl": "https://vos.live/session/session_8f2c1a90b6d4e123",
"joinUrl": "https://vos.live/join/VO4829"
}
]
}Crear una sesión
Es útil para iniciar una sesión de soporte directamente desde un ticket o un WorkFlow: coloca el joinUrl que recibes en el ticket o mensaje del cliente, y el hostUrl en el del técnico.
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}'Todos los campos son opcionales:
{
"name": "Ticket #4821", // defaults to a timestamp-based name
"recordingEnabled": true, // defaults to false
"hostOnly": false, // defaults to false
"hostCameraShare": false, // host publishes video; guest joins audio-only
"workflowTemplateId": "workflow_123" // optional Team/Trial WorkFlow
}Devuelve 201 con la misma estructura de sesión que el endpoint de lista.
Obtener una sesión
GET /api/v1/sessions/:idDevuelve el paquete completo de la sesión guardada: metadatos de la sesión, notas, grabaciones, capturas, anotaciones, avance del WorkFlow, recursos de objetivos, metadatos del enlace de revisión activo y un arreglo plano assets para descargas. Devuelve 404 si la sesión no existe o pertenece a otra organización.
{
"session": {
"id": "session_8f2c1a90b6d4e123",
"organizationId": "org_123",
"name": "Front lobby printer",
"status": "ended",
"pin": "VO4829",
"minutesUsed": 12,
"startedAt": "2026-06-17T18:42:00.000Z",
"endedAt": "2026-06-17T18:54:12.000Z",
"recordingEnabled": true,
"hostOnly": false,
"hostCameraShare": false,
"hasRecording": true,
"hasScreenshots": true,
"hasNotes": true,
"notesText": "Replaced tray sensor.",
"hostUrl": "https://vos.live/session/session_8f2c1a90b6d4e123",
"joinUrl": "https://vos.live/join/VO4829"
},
"notes": ["Replaced tray sensor.", "Showed cracked guide tab."],
"recordings": [
{
"id": "recording_rec_123",
"title": "Front lobby printer",
"durationLabel": "11m 52s",
"playbackUrl": "https://vos.live/recordings/front-lobby.mp4",
"downloadUrl": "https://vos.live/recordings/front-lobby.mp4"
}
],
"snapshots": [
{
"id": "snapshot_123",
"title": "Tray assembly",
"noteText": "Cracked guide tab",
"imageUrl": "https://vos.live/api/session/session_8f2c1a90b6d4e123/assets/snapshot-1.png?sig=...",
"rawImageUrl": "https://vos.live/api/session/session_8f2c1a90b6d4e123/assets/snapshot-raw.png?sig=...",
"annotatedImageUrl": "https://vos.live/api/session/session_8f2c1a90b6d4e123/assets/snapshot-1.png?sig=..."
}
],
"annotations": [
{
"id": "annotation_123",
"targetId": "target_123",
"revision": 3,
"status": "active",
"payload": {
"targetId": "target_123",
"strokes": [],
"markers": [],
"notes": "Showed cracked guide tab."
}
}
],
"targets": [
{
"id": "target_123",
"label": "Printer tray",
"status": "ready",
"sourceSnapshotUrl": "https://vos.live/api/session/session_8f2c1a90b6d4e123/assets/target.png?sig=...",
"compiledTargetUrl": "https://vos.live/api/session/session_8f2c1a90b6d4e123/assets/bundle-abcd.mind?sig=..."
}
],
"workflowRun": {
"id": "session_workflow_123",
"title": "Printer intake",
"status": "completed",
"steps": []
},
"reviewShare": {
"id": "review_123",
"reviewUrl": "https://vos.live/review/abc123",
"expiresAt": "2026-07-17T18:54:12.000Z",
"passwordProtected": true
},
"assets": [
{
"id": "recording:recording_rec_123",
"type": "recording",
"label": "Front lobby printer",
"url": "https://vos.live/recordings/front-lobby.mp4",
"downloadUrl": "https://vos.live/recordings/front-lobby.mp4",
"filename": "front-lobby.mp4",
"contentType": "video/mp4",
"relatedId": "recording_rec_123"
}
]
}Las URL de capturas y objetivos son URL firmadas porque esos archivos se guardan fuera de la raíz web pública. Trátalas como datos privados de tus clientes y guarda solo lo que tu integración necesite.
Webhooks
Registra un endpoint desde Configuración > API en el plan Company. Le enviaremos por POST un payload JSON firmado para estos eventos:
session.ended: se envía cuando termina una sesión, ya sea porque la finalizó un técnico o automáticamente al cerrarse la sala.recording.ready: se envía cuando una grabación termina de procesarse y está disponible para reproducir.
Estructura del payload:
{
"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
}
}Los endpoints deben usar https://. Los envíos fallidos se reintentan automáticamente con espera progresiva, y los propietarios de la cuenta pueden reenviar los envíos recientes desde la configuración de la API. Los payloads de los webhooks son ligeros; usa GET /api/v1/sessions/:id con el sessionId del evento cuando tu integración necesite el paquete completo de la sesión guardada o las URL de descarga de los archivos.
Verificar las firmas de los webhooks
Cada envío incluye un encabezado X-VOS-Signature: un HMAC-SHA256 del cuerpo sin procesar de la solicitud, codificado en hexadecimal, con el secreto de firma que se mostró al crear el endpoint. El tipo de evento también se envía en 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),
);
}Calcula el HMAC sobre los bytes exactos que recibiste: si vuelves a serializar el JSON ya procesado antes de verificarlo, obtendrás una firma distinta.
¿Necesitas algo que la API todavía no cubre?
El SSO empresarial ya está disponible. SAML, el aprovisionamiento con SCIM y permisos más amplios para la API siguen en nuestro plan de desarrollo empresarial. Cuéntanos qué estás construyendo y te ayudamos a lograrlo.
