Docs/Sessions

Sessions

Créez une session de visionnage en direct, envoyez une invitation au client et interrogez son statut. Les horodatages sont en ISO-8601 UTC (…Z).

Deux modes d'authentification
Créer une session, vérifier son statut, récupérer une session et émettre un jeton d'agent acceptent un JWT de tableau de bord, une clé API d'équipe, ou un jeton OAuth avec la portée correspondante. Lister les sessions reste réservé au tableau de bord (JWT).

Créer une session

POST/sessions

Crée une session et son invitation, puis transmet le lien d'invitation via le channel choisi. Passez teamId avec un JWT de tableau de bord ; une clé API implique sa propre équipe.

ChampDescription
teamIdL'UUID de l'équipe. Requis lors de l'authentification avec un JWT de tableau de bord ; déduit automatiquement d'une clé API.
channelComment l'invitation est délivrée : sms, email, ou link (rien n'est envoyé — vous distribuez l'URL vous-même).
recipientPhoneLe numéro de téléphone du client au format E.164 (ex. +15555550123). Requis quand channel vaut sms.
recipientEmailL'adresse e-mail du client. Requise quand channel vaut email — le message inclut le lien ainsi qu'un QR code intégré.
noteUn libellé interne optionnel, jusqu'à 500 caractères (ex. un numéro de ticket), affiché à côté de la session dans le tableau de bord.
ttlMinutesLa durée de validité de l'invitation, en minutes (11440). Par défaut 30.
smsConsentObligatoire lorsque channel vaut sms : doit être true pour confirmer que le destinataire a accepté de recevoir un SMS de seeitlive.io. Des frais d'opérateur peuvent s'appliquer.
metadataPaires clé/valeur personnalisées facultatives (un dictionnaire plat de chaînes, par exemple votre propre identifiant d'agent externe ou une référence de ticket). Stockées telles quelles et renvoyées en lecture. Jusqu'à 30 clés ; clés jusqu'à 64 caractères, valeurs jusqu'à 500.
shortLinkOptionnel. Si vrai, génère un lien court sitl.cc/s/code pour l'URL invité, renvoyé sous inviteShortUrl. Par défaut à false. Les invitations par SMS utilisent toujours un lien court.
protectionFacultatif. password ou totp. Oblige le client à saisir un secret avant de pouvoir partager sa caméra. Omettez ce champ pour un lien non protégé.
protectionSecretFacultatif. Le mot de passe, ou une graine TOTP en base32. Si vous ne le fournissez pas, nous en générons un et le renvoyons une seule fois dans la réponse.
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 est un alias court sitl.cc/s/code de l'inviteUrl invité, ou null si aucun lien court n'a été généré. Les agents intègrent toujours l'agentViewUrl complet.

json
{
  "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"
}
Affiché une seule fois
inviteUrl et agentViewUrl transportent les jetons de session en clair dans le fragment de leur URL. Ils ne sont renvoyés qu'à la création — enregistrez-les immédiatement.

Récupérer une session

GET/sessions/:id

Renvoie une session, y compris ses metadata et son invitation (code, expiration, heure d'ouverture, canal, destinataire) — jamais un hachage de jeton ni le secret invité. Nécessite la permission view_sessions sur un JWT de tableau de bord, ou un jeton API/OAuth avec la portée sessions:read. Renvoie 404 si la session n'existe pas.

curl https://api.seeitlive.io/v1/sessions/f74f1305-2222-4a11-8b1e-1234567890ab \
  -H "Authorization: Bearer $SEEITLIVE_KEY"
json
{
  "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"
  }
}

Statut de la session

GET/sessions/:id/status

Interrogez ce point de terminaison pour savoir quand le client est devant sa caméra.

status évolue de pendingringingliveended au fur et à mesure que le client rejoint puis quitte, ou passe directement à expired (l'invitation n'a jamais été ouverte) ou cancelled.

json
{
  "id": "f74f1305-2222-4a11-8b1e-1234567890ab",
  "status": "live",
  "startedAt": "2026-07-07T09:14:03.000Z",
  "endedAt": null,
  "producerCount": 1,
  "hasVideo": true
}

Protéger une session

Une session protégée demande au client un secret que vous lui transmettez par un autre canal — en général, l'agent le lui dicte au téléphone. Avec password, le secret reste fixe pendant toute la durée de l'invitation. Avec totp, il change toutes les 30 secondes ; fournissez votre propre graine base32 pour afficher le code courant dans vos propres outils, ou laissez-nous en générer une.

La comparaison des mots de passe est volontairement souple
Un mot de passe dicté ne doit pas échouer sur une majuscule : la comparaison ignore la casse et les espaces autour. Les mots de passe générés font 8 caractères, sans I, O, 0 ni 1.

Lire le secret courant

GET/sessions/:id/protection

Renvoie ce que l'agent doit dicter : le mot de passe, ou le code du moment avec le nombre de secondes restantes. La graine TOTP elle-même est renvoyée une seule fois, à la création de la session.

json
{
  "type": "totp",
  "password": null,
  "code": "418205",
  "secondsRemaining": 17,
  "locked": false,
  "failedAttempts": 0
}

Définir la protection

PUT/sessions/:id/protection

Modifie le défi invité d’une session après sa création. Omettez protectionSecret et il est généré pour vous — un mot de passe de 8 caractères, ou une graine TOTP base32. Renvoie la même structure que le GET ci-dessus.

json
{
  "protection": "password",
  "protectionSecret": "K7QMX2RT"
}

Envoyer {"protection": "none"} retire le défi, et efface tout verrouillage avec lui. Chaque changement remet à zéro le compteur d’échecs, car le client va se faire communiquer un secret différent.

Lever un verrouillage

POST/sessions/:id/protection/reset

Cinq mauvaises réponses verrouillent l’invitation. Ceci lève le verrouillage ; passez rotate: true pour générer aussi un nouveau secret. La rotation est optionnelle car la cause habituelle est une faute de frappe, et un nouveau secret oblige simplement à le redicter.

json
{
  "rotate": true
}

Déverrouillage du client

POST/invitations/unlock

La page invité échange la réponse contre un jeton de déverrouillage éphémère, ensuite exigé lors de la connexion de signalisation. Cinq réponses erronées verrouillent l'invitation et renvoient 403 avec code: "invitation_locked" jusqu'à ce qu'un agent la débloque.

Envoyez le code de l'invitation, son token (le fragment de l'URL d'invitation) et la réponse du client dans answer : le mot de passe, ou le code à 6 chiffres du moment. Omettez answer pour une invitation non protégée.

json
{
  "code": "aZ3kQ9",
  "token": "3n9F1Qk7xY2zR8vB5tW6uL0mC4pD1sA...",
  "answer": "418205"
}

En cas de succès, vous recevez une preuve éphémère. Elle expire au bout de 60 minutes, ou avec l'invitation si celle-ci expire avant, et cesse d'être acceptée dès que le secret est renouvelé.

json
{
  "unlockToken": "sil_gu_eyJpIjoiOWQ4YzdiNmEiLCJlIjoxNzg1...",
  "expiresAt": "2026-08-05T10:42:00.000Z"
}

Réclamer l'invitation

POST/invitations/claim

La page invité appelle cet endpoint pour s'authentifier et faire sonner la session sur l'écran de l'agent. Une invitation protégée doit également présenter le jeton unlock obtenu à l'étape précédente.

json
{
  "code": "aZ3kQ9",
  "token": "3n9F1Qk7xY2zR8vB5tW6uL0mC4pD1sA...",
  "unlock": "sil_gu_eyJpIjoiOWQ4YzdiNmEiLCJlIjoxNzg1..."
}

Sans ce jeton — ou avec une preuve émise pour une autre invitation, ou contre un secret renouvelé entre-temps — l'appel est refusé avec 403 et code: "protection_required", sans rien changer à la session.

json
{
  "statusCode": 403,
  "error": "ForbiddenError",
  "message": "This session is protected — enter the password or code first",
  "code": "protection_required"
}

Émettre un jeton d'agent

POST/sessions/:id/agent-token

Émet un nouveau jeton agent-view, valide 120 minutes, pour une session à laquelle l'appelant a déjà accès — utilisez-le pour réintégrer la visionneuse, par exemple après l'expiration de l’agentViewUrl d'origine. Accepte un label optionnel (1 à 64 caractères) affiché dans la liste des visionneuses du tableau de bord ; omis, un appelant clé API ou OAuth obtient "Integration viewer", un JWT de tableau de bord obtient "Dashboard viewer". Nécessite la permission view_sessions sur un JWT de tableau de bord, ou un jeton API/OAuth avec la portée 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" }'
json
{
  "code": "qR7mZ2",
  "token": "5aQ1nD8vC3xF6yK9bH2wS7pM4dJ0uT1gN...",
  "agentViewUrl": "https://seeitlive.io/a/qR7mZ2#5aQ1nD8vC3xF6yK9bH2wS7pM4dJ0uT1gN..."
}

Résoudre une invitation (public)

GET/u/:code

Le point de terminaison public que la page invité appelle pour résoudre un code d'invitation en sa session et sa marque — aucun jeton ni clé requis. Rejoindre le flux s'authentifie séparément, avec le jeton intégré dans le fragment de l'URL d'invitation.

json
{
  "sessionId": "f74f1305-2222-4a11-8b1e-1234567890ab",
  "brand": {
    "name": "Acme Support",
    "brandLogoUrl": null,
    "brandColor": "#1a2b3c"
  },
  "status": "pending",
  "protection": "totp",
  "locked": false
}
Limité en débit
Limité à 20 requêtes par minute et par IP, car ce point de terminaison est non authentifié et accessible depuis n'importe où.
Sessions