V

VOS

Virtually OnSite Remote Support

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_xxxxxxxxxxxxxxxxxxxxxxxx

Requests 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/sessions
curl 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/sessions
curl 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/:id

Same 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.