Sessions
Create a live-view session, send the customer an invite, and poll its status. Timestamps are ISO-8601 UTC (…Z).
Create a session
Creates a session and its invitation, then dispatches the invite link over the chosen channel. Pass teamId with a dashboard JWT; an API key implies its own team.
| Field | Description |
|---|---|
teamId | The team's UUID. Required when authenticating with a dashboard JWT; inferred automatically from an API key. |
channel | How the invite is delivered: sms, email, or link (nothing is sent — you distribute the URL yourself). |
recipientPhone | The customer's phone number in E.164 format (e.g. +15555550123). Required when channel is sms. |
recipientEmail | The customer's email address. Required when channel is email — the message includes the link plus an inline QR code. |
note | An optional internal label, up to 500 characters (e.g. a ticket number), shown alongside the session in the dashboard. |
ttlMinutes | How long the invite stays valid, in minutes (1–1440). Defaults to 30. |
smsConsent | Required when channel is sms: must be true to confirm the recipient agreed to receive a text from seeitlive.io. Carrier fees may apply. |
metadata | Optional custom key/value pairs (a flat map of strings, e.g. your own external agent id or ticket reference). Stored opaquely and returned on reads. Up to 30 keys; keys up to 64 characters, values up to 500. |
shortLink | Optional. When true, mints a short sitl.cc/s/code link for the guest URL, returned as inviteShortUrl. Defaults to false. SMS invites always use a short link. |
protection | Optional. password or totp. Requires the guest to enter a secret before their camera can be shared. Omit for an unprotected link. |
protectionSecret | Optional. The password, or a base32 TOTP seed. Omit it and we generate one and return it once in the response. |
curl -X POST https://api.seeitlive.io/v1/sessions \
-H "Authorization: Bearer sil_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "channel": "sms", "recipientPhone": "+15555550123", "smsConsent": true, "note": "Ticket #4821" }'inviteShortUrl is a short sitl.cc/s/code alias of the guest inviteUrl, or null when no short link was minted. Agents always embed the full agentViewUrl.
{
"id": "f74f1305-2222-4a11-8b1e-1234567890ab",
"status": "pending",
"inviteCode": "aZ3kQ9",
"inviteUrl": "https://seeitlive.io/u/aZ3kQ9#3n9F1Qk7xY2zR8vB5tW6uL0mC4pD1sA...",
"inviteShortUrl": "https://sitl.cc/s/aB3xK9p2",
"agentViewUrl": "https://seeitlive.io/a/pL2mN8#7dR2Xa4Wq9Kj6bV3nF1yT8sH5cE0uZ...",
"protection": "totp",
"protectionSecret": "JBSWY3DPEHPK3PXP",
"protectionOtpauthUrl": "otpauth://totp/SeeItLive:session-aZ3kQ9?secret=JBSWY3DPEHPK3PXP&issuer=SeeItLive",
"expiresAt": "2026-07-07T09:42:00.000Z"
}inviteUrl and agentViewUrl carry the plaintext session tokens in their URL fragment. They're returned only on creation — store them immediately.Get a session
Returns a session, including its metadata and its invitation (code, expiry, opened time, channel, recipient) — never a token hash or guest secret. Requires the view_sessions permission on a dashboard JWT, or an API key/OAuth token scoped sessions:read. Returns 404 if the session doesn't exist.
curl https://api.seeitlive.io/v1/sessions/f74f1305-2222-4a11-8b1e-1234567890ab \
-H "Authorization: Bearer $SEEITLIVE_KEY"{
"id": "f74f1305-2222-4a11-8b1e-1234567890ab",
"teamId": "b5a2b2b0-6c7a-4e2f-9f2a-1234567890ab",
"env": "live",
"status": "live",
"createdByClientId": "9d8c7b6a-5f4e-3d2c-1b0a-abcdef123456",
"createdByApiKeyId": null,
"note": "Ticket #4821",
"metadata": { "ticketId": "4821" },
"startedAt": "2026-07-07T09:14:03.000Z",
"endedAt": null,
"createdAt": "2026-07-07T09:12:00.000Z",
"invitation": {
"code": "aZ3kQ9",
"expiresAt": "2026-07-07T09:42:00.000Z",
"openedAt": "2026-07-07T09:13:41.000Z",
"channel": "sms",
"recipient": "+15555550123"
}
}Session status
Poll this to know when the customer is on camera.
status moves through pending → ringing → live → ended as the customer joins and leaves, or short-circuits to expired (the invite was never opened) or cancelled.
{
"id": "f74f1305-2222-4a11-8b1e-1234567890ab",
"status": "live",
"startedAt": "2026-07-07T09:14:03.000Z",
"endedAt": null,
"producerCount": 1,
"hasVideo": true
}Protecting a session
A protected session asks the guest for a secret you communicate out of band — typically the agent reads it out on the phone. With password the secret is static for the life of the invitation. With totp it is a 6-digit code that rotates every 30 seconds; supply your own base32 seed to render the current code in your own agent tooling, or let us generate one.
I, O, 0 or 1.Reading the current secret
Returns what the agent should read out: the password, or the code of the moment with the seconds left before it rotates. The TOTP seed itself is returned only once, when the session is created.
{
"type": "totp",
"password": null,
"code": "418205",
"secondsRemaining": 17,
"locked": false,
"failedAttempts": 0
}Set the protection
Change a session’s guest challenge after it was created. Omit protectionSecret and one is generated for you — an 8-character password, or a base32 TOTP seed. Returns the same shape as the GET above.
{
"protection": "password",
"protectionSecret": "K7QMX2RT"
}Sending {"protection": "none"} removes the challenge, and clears any lockout with it. Every change resets the failed-attempt counter, because the customer is about to be told a different secret.
Clear a lockout
Five wrong answers lock the invitation. This clears the lockout; pass rotate: true to also generate a new secret. Rotation is opt-in because the usual cause is a mistyped code, and a new secret just means reading it out again.
{
"rotate": true
}Guest unlock
The guest page exchanges the answer for a short-lived unlock token, which the signaling handshake then requires. Five wrong answers lock the invitation and return 403 with code: "invitation_locked" until an agent resets it.
Post the invitation code, its token (the fragment of the invite URL) and the customer's answer — the password, or the 6-digit code of the moment. Omit answer for an unprotected invitation.
{
"code": "aZ3kQ9",
"token": "3n9F1Qk7xY2zR8vB5tW6uL0mC4pD1sA...",
"answer": "418205"
}On success you get a short-lived proof. It expires after 60 minutes, or with the invitation if that comes first, and stops being accepted the moment the secret is rotated.
{
"unlockToken": "sil_gu_eyJpIjoiOWQ4YzdiNmEiLCJlIjoxNzg1...",
"expiresAt": "2026-08-05T10:42:00.000Z"
}Claiming the invitation
The guest page calls this to authenticate and make the session ring on the agent's screen. A protected invitation must also present the unlock token from the previous step.
{
"code": "aZ3kQ9",
"token": "3n9F1Qk7xY2zR8vB5tW6uL0mC4pD1sA...",
"unlock": "sil_gu_eyJpIjoiOWQ4YzdiNmEiLCJlIjoxNzg1..."
}Without it — or with a proof issued for another invitation, or against a secret that has since been rotated — the call is refused with 403 and code: "protection_required", leaving the session untouched.
{
"statusCode": 403,
"error": "ForbiddenError",
"message": "This session is protected — enter the password or code first",
"code": "protection_required"
}Mint an agent token
Issues a fresh agent-view token, valid for 120 minutes, for a session the caller already has access to — use it to re-embed the viewer, e.g. after the original agentViewUrl expired. Accepts an optional label (1–64 characters) shown in the dashboard's viewer list; omit it and an API key or OAuth caller gets "Integration viewer", a dashboard JWT gets "Dashboard viewer". Requires the view_sessions permission on a dashboard JWT, or an API key/OAuth token scoped sessions:write.
curl -X POST https://api.seeitlive.io/v1/sessions/f74f1305-2222-4a11-8b1e-1234567890ab/agent-token \
-H "Authorization: Bearer $SEEITLIVE_KEY" \
-H "Content-Type: application/json" \
-d '{ "label": "Odoo — crm.lead 42" }'{
"code": "qR7mZ2",
"token": "5aQ1nD8vC3xF6yK9bH2wS7pM4dJ0uT1gN...",
"agentViewUrl": "https://seeitlive.io/a/qR7mZ2#5aQ1nD8vC3xF6yK9bH2wS7pM4dJ0uT1gN..."
}Resolve an invite (public)
The public endpoint the guest page calls to resolve an invite code into its session and brand — no token or key required. Joining the stream is authenticated separately, with the token embedded in the invite URL's fragment.
{
"sessionId": "f74f1305-2222-4a11-8b1e-1234567890ab",
"brand": {
"name": "Acme Support",
"brandLogoUrl": null,
"brandColor": "#1a2b3c"
},
"status": "pending",
"protection": "totp",
"locked": false
}