Aller au contenu
API v1 Mes clés API
Documentation · v1

API Visioo

Créez des réunions, suivez vos séances, récupérez les replays et recevez des événements en temps réel. L’API est REST, répond en JSON et utilise les codes HTTP standards. Vous codez avec une IA ? Donnez-lui notre prompt.

Adresse de base
https://api.getvisioo.com/v1
Documentation https://getvisioo.com/docs/api
Disponible avec Solo et Organisme

Authentification

Chaque requête porte une clé API dans l’en-tête Authorization. Créez et révoquez vos clés dans l’espace client, rubrique API : une clé n’est montrée qu’une fois, à sa création.

Les clés vsk_live_ agissent sur vos vraies réunions, au nom du propriétaire du compte. Gardez-les côté serveur, par exemple dans une variable d’environnement : ne placez jamais une clé dans du code exécuté par le navigateur.

En-tête HTTP
Authorization: Bearer vsk_live_4f8Qm…7Qx2

Limites d’appels

Les limites s’appliquent par compte, toutes clés confondues. Chaque réponse indique où vous en êtes (sans limite d’appels, ces en-têtes sont absents). Les appels respectent aussi les limites de votre offre : réunions en même temps, participants, heures d’enregistrement.

Au-delà, l’API répond 429 Too Many Requests avec l’en-tête Retry-After (en secondes). Attendez ce délai avant de réessayer.

Offre Par minute Par jour Webhooks
Solo 60 requêtes 10 000 requêtes 2 points de réception
Organisme 300 requêtes 100 000 requêtes 10 points de réception
Sur devis À définir ensemble À définir ensemble Sur mesure
En-têtes de réponse
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1793613660
Retry-After: 12   (uniquement avec une réponse 429)

Erreurs

Les erreurs renvoient un code HTTP et un objet error avec un code stable et un message en français. param désigne le paramètre en cause ; request_id, repris dans l’en-tête Request-Id, aide notre support à retrouver la requête.

Code HTTP error.code Signification
400 invalid_request Paramètre manquant, inconnu ou mal formé.
401 invalid_api_key Clé absente, révoquée ou erronée.
403 plan_required Fonction non incluse dans votre offre.
404 not_found Ressource ou adresse introuvable.
409 session_ended La séance est déjà terminée.
409 recording_not_ready Le replay n’est pas encore prêt.
409 already_member La personne fait déjà partie de l’équipe.
409 meeting_limit_reached Votre offre ne permet pas d’autre réunion.
409 webhook_limit_reached Tous les points de réception de votre offre sont utilisés.
422 validation_failed Valeur refusée, par exemple un nom de plus de 80 caractères.
429 rate_limited Limite d’appels atteinte.
500 server_error Erreur de notre côté. Réessayez plus tard.
503 storage_unavailable Stockage des replays momentanément indisponible. Réessayez plus tard.
Exemple — 422
{
  "error": {
    "code": "validation_failed",
    "message": "Le nom fait 80 caractères au plus.",
    "param": "name",
    "request_id": "req_Ab12Cd34Ef56"
  }
}

Pagination

Les listes renvoient au plus limit éléments (20 par défaut, 100 au maximum), les plus récents d’abord. Si has_more vaut true, repassez next_cursor dans le paramètre cursor pour obtenir la page suivante.

Idempotence

Pour les POST, ajoutez un en-tête Idempotency-Key unique (255 caractères au plus). Si la requête est rejouée sous 24 heures avec la même clé, vous recevez la même réponse, avec l’en-tête Idempotent-Replayed: true, sans créer de doublon.

En-tête HTTP
Idempotency-Key: 6c1e2b0a-3f7d-4d6e-9b1a-2f4c8e9d0a11

Webhooks : réception et signature

Chaque événement est envoyé en POST JSON aux points de réception qui l’ont choisi. Répondez 2xx en moins de 10 secondes, puis traitez l’événement. Sinon, nous réessayons jusqu’à 6 fois sur 24 heures (1 min, 5 min, 30 min, 2 h, 8 h, 24 h).

Vérifiez l’en-tête Visioo-Signature (t=horodatage,v1=signature) : la signature est un HMAC SHA-256 en hexadécimal de « horodatage.corps brut », calculé avec le secret du point de réception (whsec_…). Les en-têtes Visioo-Event-Id et Visioo-Event-Type reprennent l’id et le type de l’événement : un même id reçu deux fois est un doublon à ignorer.

Événement Quand data.object
session.started La séance commence. Séance
session.ended La séance se termine. Séance
participant.joined Une personne entre dans la séance (une fois par personne). Participant, avec session_id et meeting_id
participant.left Une personne quitte la séance. Participant, avec session_id et meeting_id
recording.ready Le replay est prêt. Enregistrement
recording.expired Le replay arrive en fin de conservation et il est effacé. Enregistrement
Vérifier une signature
// Node.js
import crypto from 'node:crypto';

function verifier(corpsBrut, entete, secret) {
  const [t, v1 = ''] = entete.split(',').map(p => p.split('=')[1]);
  const attendu = crypto.createHmac('sha256', secret)
    .update(t + '.' + corpsBrut).digest('hex');
  const recent = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return recent && v1.length === attendu.length
    && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(attendu));
}

Exemple d’événement

recording.ready
{
  "id": "evt_5b1f0c7e9a2d4e6f8a0b1c2d",
  "object": "event",
  "type": "recording.ready",
  "created_at": "2026-10-28T10:12:03Z",
  "data": {
    "object": {
      "id": "rec_71dz",
      "object": "recording",
      "meeting_id": "mtg_8f2k",
      "session_id": "ses_3lq9",
      "title": "Groupe du mardi",
      "duration_seconds": 3920,
      "size_bytes": 912000000,
      "status": "ready",
      "created_at": "2026-10-28T09:00:30Z",
      "expires_at": "2027-01-28T10:05:40Z",
      "share_url": null,
      "share_expires_at": null
    }
  }
}

Versions et changements

La version est dans l’adresse (/v1). Les ajouts compatibles (nouveaux champs, nouveaux événements) arrivent sans changement de version : ignorez les champs inconnus. Toute rupture passera par /v2, annoncée 6 mois à l’avance.

v1.0 : réunions, séances, liste de présence, enregistrements, webhooks, équipe.

Avec votre IA

Vous développez avec un assistant IA ? Copiez ce texte dans la conversation et complétez la ligne « Mon application » : l’assistant aura toute la documentation sous la main pour écrire le branchement, de la clé à la vérification des webhooks.

Prompt pour votre IA
Tu es un développeur expérimenté. Aide-moi à brancher l’API Visioo (visioconférence pour formateurs et coachs) dans mon application.

Mon application : [décrivez-la ici : langage, framework, hébergement, ce que vous voulez automatiser avec Visioo]

Méthode :
1. Pose-moi d’abord les questions utiles s’il manque des informations, puis avance une étape à la fois.
2. Installation : aucune bibliothèque Visioo n’est nécessaire. L’API se parle en HTTPS et en JSON avec le client HTTP habituel de mon langage.
3. Clé API : je la crée dans mon espace Visioo, rubrique API (elle n’est montrée qu’une fois). Elle reste côté serveur, dans une variable d’environnement VISIOO_API_KEY, jamais dans le navigateur, une application mobile ni dans Git.
4. Écris un petit client réutilisable : en-tête Authorization, erreurs au format de l’API, réponse 429 (attendre Retry-After), Idempotency-Key sur chaque POST, pagination par curseur.
5. Écris les appels dont j’ai besoin, parmi les opérations ci-dessous.
6. Si j’ai besoin d’être prévenu (séance terminée, replay prêt…) : un récepteur de webhooks qui vérifie la signature sur le corps brut, répond 2xx en moins de 10 secondes, traite ensuite l’événement et ignore les doublons (même id).
7. Termine par des tests et la façon de tout essayer.
N’invente aucune adresse, aucun champ ni aucun événement : utilise seulement la documentation ci-dessous, et ignore les champs inconnus dans les réponses.

# Documentation de l’API Visioo (v1)
Source : https://getvisioo.com/docs/api
Adresse de base : https://api.getvisioo.com/v1
Disponible avec les offres Solo et Organisme. REST, réponses en JSON (UTF-8), codes HTTP standards, dates ISO 8601 en UTC. Identifiants préfixés : mtg_ (réunion), ses_ (séance), rec_ (enregistrement), mem_ (membre), inv_ (invitation), whe_ (point de réception), evt_ (événement).

## Authentification
Chaque requête porte une clé API dans l’en-tête Authorization. Créez et révoquez vos clés dans l’espace client, rubrique API : une clé n’est montrée qu’une fois, à sa création.
Les clés vsk_live_ agissent sur vos vraies réunions, au nom du propriétaire du compte. Gardez-les côté serveur, par exemple dans une variable d’environnement : ne placez jamais une clé dans du code exécuté par le navigateur.
En-tête HTTP :
```
Authorization: Bearer vsk_live_4f8Qm…7Qx2
```

## Limites d’appels
Les limites s’appliquent par compte, toutes clés confondues. Chaque réponse indique où vous en êtes (sans limite d’appels, ces en-têtes sont absents). Les appels respectent aussi les limites de votre offre : réunions en même temps, participants, heures d’enregistrement.
Au-delà, l’API répond 429 Too Many Requests avec l’en-tête Retry-After (en secondes). Attendez ce délai avant de réessayer.
| Offre | Par minute | Par jour | Webhooks |
| --- | --- | --- | --- |
| Solo | 60 requêtes | 10 000 requêtes | 2 points de réception |
| Organisme | 300 requêtes | 100 000 requêtes | 10 points de réception |
| Sur devis | À définir ensemble | À définir ensemble | Sur mesure |
En-têtes de réponse :
```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1793613660
Retry-After: 12   (uniquement avec une réponse 429)
```

## Erreurs
Les erreurs renvoient un code HTTP et un objet error avec un code stable et un message en français. param désigne le paramètre en cause ; request_id, repris dans l’en-tête Request-Id, aide notre support à retrouver la requête.
| Code HTTP | error.code | Signification |
| --- | --- | --- |
| 400 | invalid_request | Paramètre manquant, inconnu ou mal formé. |
| 401 | invalid_api_key | Clé absente, révoquée ou erronée. |
| 403 | plan_required | Fonction non incluse dans votre offre. |
| 404 | not_found | Ressource ou adresse introuvable. |
| 409 | session_ended | La séance est déjà terminée. |
| 409 | recording_not_ready | Le replay n’est pas encore prêt. |
| 409 | already_member | La personne fait déjà partie de l’équipe. |
| 409 | meeting_limit_reached | Votre offre ne permet pas d’autre réunion. |
| 409 | webhook_limit_reached | Tous les points de réception de votre offre sont utilisés. |
| 422 | validation_failed | Valeur refusée, par exemple un nom de plus de 80 caractères. |
| 429 | rate_limited | Limite d’appels atteinte. |
| 500 | server_error | Erreur de notre côté. Réessayez plus tard. |
| 503 | storage_unavailable | Stockage des replays momentanément indisponible. Réessayez plus tard. |
Exemple — 422 :
```
{
  "error": {
    "code": "validation_failed",
    "message": "Le nom fait 80 caractères au plus.",
    "param": "name",
    "request_id": "req_Ab12Cd34Ef56"
  }
}
```

## Pagination
Les listes renvoient au plus limit éléments (20 par défaut, 100 au maximum), les plus récents d’abord. Si has_more vaut true, repassez next_cursor dans le paramètre cursor pour obtenir la page suivante.

## Idempotence
Pour les POST, ajoutez un en-tête Idempotency-Key unique (255 caractères au plus). Si la requête est rejouée sous 24 heures avec la même clé, vous recevez la même réponse, avec l’en-tête Idempotent-Replayed: true, sans créer de doublon.
En-tête HTTP :
```
Idempotency-Key: 6c1e2b0a-3f7d-4d6e-9b1a-2f4c8e9d0a11
```

## Webhooks : réception et signature
Chaque événement est envoyé en POST JSON aux points de réception qui l’ont choisi. Répondez 2xx en moins de 10 secondes, puis traitez l’événement. Sinon, nous réessayons jusqu’à 6 fois sur 24 heures (1 min, 5 min, 30 min, 2 h, 8 h, 24 h).
Vérifiez l’en-tête Visioo-Signature (t=horodatage,v1=signature) : la signature est un HMAC SHA-256 en hexadécimal de « horodatage.corps brut », calculé avec le secret du point de réception (whsec_…). Les en-têtes Visioo-Event-Id et Visioo-Event-Type reprennent l’id et le type de l’événement : un même id reçu deux fois est un doublon à ignorer.
| Événement | Quand | data.object |
| --- | --- | --- |
| session.started | La séance commence. | Séance |
| session.ended | La séance se termine. | Séance |
| participant.joined | Une personne entre dans la séance (une fois par personne). | Participant, avec session_id et meeting_id |
| participant.left | Une personne quitte la séance. | Participant, avec session_id et meeting_id |
| recording.ready | Le replay est prêt. | Enregistrement |
| recording.expired | Le replay arrive en fin de conservation et il est effacé. | Enregistrement |
Vérifier une signature :
```
// Node.js
import crypto from 'node:crypto';

function verifier(corpsBrut, entete, secret) {
  const [t, v1 = ''] = entete.split(',').map(p => p.split('=')[1]);
  const attendu = crypto.createHmac('sha256', secret)
    .update(t + '.' + corpsBrut).digest('hex');
  const recent = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return recent && v1.length === attendu.length
    && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(attendu));
}
```

## Exemple d’événement
recording.ready :
```
{
  "id": "evt_5b1f0c7e9a2d4e6f8a0b1c2d",
  "object": "event",
  "type": "recording.ready",
  "created_at": "2026-10-28T10:12:03Z",
  "data": {
    "object": {
      "id": "rec_71dz",
      "object": "recording",
      "meeting_id": "mtg_8f2k",
      "session_id": "ses_3lq9",
      "title": "Groupe du mardi",
      "duration_seconds": 3920,
      "size_bytes": 912000000,
      "status": "ready",
      "created_at": "2026-10-28T09:00:30Z",
      "expires_at": "2027-01-28T10:05:40Z",
      "share_url": null,
      "share_expires_at": null
    }
  }
}
```

## Versions et changements
La version est dans l’adresse (/v1). Les ajouts compatibles (nouveaux champs, nouveaux événements) arrivent sans changement de version : ignorez les champs inconnus. Toute rupture passera par /v2, annoncée 6 mois à l’avance.
v1.0 : réunions, séances, liste de présence, enregistrements, webhooks, équipe.

## Opérations

### Réunions
Chaque réunion a un lien unique, de la forme getvisioo.com/votre-espace/r/482-193-776, et un code à 9 chiffres. Vos participants la rejoignent sans compte. max_participants indique le plafond de votre offre (null : sans limite).

#### GET /meetings — Lister les réunions
Renvoie les réunions du compte, les plus récentes d’abord.
Paramètres de requête :
- limit (entier) : Entre 1 et 100. 20 par défaut.
- cursor (chaîne) : Valeur next_cursor de la page précédente.
Réponse 200 OK : {"object":"list","data":[{"id":"mtg_8f2k","object":"meeting","name":"Groupe du mardi","url":"https://getvisioo.com/institut-horizon/r/482-193-776/","code":"482-193-776","auto_record":false,"max_participants":100,"status":"idle","created_at":"2026-10-31T09:12:00Z"}],"has_more":false,"next_cursor":null}

#### POST /meetings — Créer une réunion
Crée une réunion et renvoie son lien à partager.
Corps de la requête :
- name (chaîne, obligatoire) : Nom affiché aux participants. 80 caractères max.
- auto_record (booléen) : Démarre l’enregistrement avec la séance. false par défaut.
Exemple de corps : {"name":"Groupe du mardi"}
Réponse 201 Created : {"id":"mtg_8f2k","object":"meeting","name":"Groupe du mardi","url":"https://getvisioo.com/institut-horizon/r/482-193-776/","code":"482-193-776","auto_record":false,"max_participants":100,"status":"idle","created_at":"2026-10-31T09:12:00Z"}

#### GET /meetings/{id} — Récupérer une réunion
Renvoie une réunion et son statut actuel : idle, ou live pendant une séance.
Réponse 200 OK : {"id":"mtg_8f2k","object":"meeting","name":"Groupe du mardi","url":"https://getvisioo.com/institut-horizon/r/482-193-776/","code":"482-193-776","auto_record":false,"max_participants":100,"status":"live","created_at":"2026-10-31T09:12:00Z"}

#### PATCH /meetings/{id} — Modifier une réunion
Seuls les champs envoyés sont modifiés. Le lien ne change pas.
Corps de la requête :
- name (chaîne) : Nouveau nom. 80 caractères max.
- auto_record (booléen) : Enregistrer automatiquement les prochaines séances.
Exemple de corps : {"auto_record":true}
Réponse 200 OK : {"id":"mtg_8f2k","object":"meeting","name":"Groupe du mardi","url":"https://getvisioo.com/institut-horizon/r/482-193-776/","code":"482-193-776","auto_record":true,"max_participants":100,"status":"idle","created_at":"2026-10-31T09:12:00Z"}

#### DELETE /meetings/{id} — Supprimer une réunion
Le lien cesse de fonctionner. Les enregistrements existants sont conservés.
Réponse 200 OK : {"id":"mtg_8f2k","object":"meeting","deleted":true}

### Séances
Une séance commence quand l’animateur entre dans la réunion et se termine quand il la ferme. Ses salles de sous-groupe en font partie.

#### GET /sessions — Lister les séances
Les plus récentes d’abord, filtrables par réunion et par période (heure de début).
Paramètres de requête :
- meeting_id (chaîne) : Limiter à une réunion.
- from (date ISO 8601) : Début de période, par exemple 2026-11-02 ou 2026-11-02T09:00:00Z.
- to (date ISO 8601) : Fin de période.
- limit (entier) : Entre 1 et 100. 20 par défaut.
- cursor (chaîne) : Valeur next_cursor de la page précédente.
Réponse 200 OK : {"object":"list","data":[{"id":"ses_3lq9","object":"session","meeting_id":"mtg_8f2k","status":"ended","started_at":"2026-10-28T09:00:12Z","ended_at":"2026-10-28T10:05:40Z","participants_count":14,"recorded":true}],"has_more":false,"next_cursor":null}

#### GET /sessions/{session_id} — Récupérer une séance
Statut live pendant la séance, ended ensuite.
Réponse 200 OK : {"id":"ses_3lq9","object":"session","meeting_id":"mtg_8f2k","status":"live","started_at":"2026-10-28T09:00:12Z","ended_at":null,"participants_count":14,"recorded":false}

#### GET /sessions/{session_id}/participants — Liste de présence
Une ligne par entrée dans la séance, avec les heures d’arrivée et de départ. Rôles : host (animateur), cohost (co-animateur), participant.
Réponse 200 OK : {"object":"list","data":[{"object":"participant","display_name":"Awa Diallo","role":"participant","joined_at":"2026-10-28T09:01:03Z","left_at":"2026-10-28T10:05:10Z","duration_seconds":3847}],"has_more":false,"next_cursor":null}

#### POST /sessions/{session_id}/end — Terminer une séance
Ferme la séance pour tous les participants.
Réponse 200 OK : {"id":"ses_3lq9","object":"session","meeting_id":"mtg_8f2k","status":"ended","started_at":"2026-10-28T09:00:12Z","ended_at":"2026-10-31T10:30:00Z","participants_count":14,"recorded":true}

### Enregistrements
Les replays sont disponibles quelques minutes après la fin de la séance. Conservation : 3 mois en Solo, 6 mois en Organisme. Chaque enregistrement consomme les heures du quota mensuel (10 h en Solo, 40 h en Organisme).

#### GET /recordings — Lister les enregistrements
Les plus récents d’abord.
Paramètres de requête :
- meeting_id (chaîne) : Limiter à une réunion.
- status (chaîne) : recording, processing, ready, failed ou expired. Les replays expirés ne sont listés qu’avec expired.
- limit (entier) : Entre 1 et 100. 20 par défaut.
- cursor (chaîne) : Valeur next_cursor de la page précédente.
Réponse 200 OK : {"object":"list","data":[{"id":"rec_71dz","object":"recording","meeting_id":"mtg_8f2k","session_id":"ses_3lq9","title":"Groupe du mardi","duration_seconds":3920,"size_bytes":912000000,"status":"ready","created_at":"2026-10-28T09:00:30Z","expires_at":"2027-01-28T10:05:40Z","share_url":null,"share_expires_at":null}],"has_more":false,"next_cursor":null}

#### GET /recordings/{recording_id} — Récupérer un enregistrement
Statuts : recording (en cours), processing (en préparation), ready, failed.
Réponse 200 OK : {"id":"rec_71dz","object":"recording","meeting_id":"mtg_8f2k","session_id":"ses_3lq9","title":"Groupe du mardi","duration_seconds":3920,"size_bytes":912000000,"status":"ready","created_at":"2026-10-28T09:00:30Z","expires_at":"2027-01-28T10:05:40Z","share_url":null,"share_expires_at":null}

#### POST /recordings/{recording_id}/share_link — Créer un lien de partage
Renvoie une adresse publique pour regarder le replay, sans le télécharger. Le lien reste le même : un nouvel appel change seulement sa durée.
Corps de la requête :
- expires_in_days (entier) : De 1 à la fin de conservation. Sans valeur : jusqu’à l’expiration du replay.
Exemple de corps : {"expires_in_days":30}
Réponse 201 Created : {"id":"rec_71dz","object":"recording","meeting_id":"mtg_8f2k","session_id":"ses_3lq9","title":"Groupe du mardi","duration_seconds":3920,"size_bytes":912000000,"status":"ready","created_at":"2026-10-28T09:00:30Z","expires_at":"2027-01-28T10:05:40Z","share_url":"https://getvisioo.com/institut-horizon/replay/9f2c41d07be35a86c1e4f02b7d9a6e13/","share_expires_at":"2026-11-30T09:00:00Z"}

#### GET /recordings/{recording_id}/download — Télécharger
Redirige (302) vers le fichier MP4, par un lien valable 1 heure. Le corps JSON donne aussi ce lien (url) et sa fin de validité (expires_at).
Réponse 302 Found : HTTP/1.1 302 Found ; Location: https://…/replay.mp4?X-Amz-Signature=…

#### DELETE /recordings/{recording_id} — Supprimer un enregistrement
Suppression définitive : le fichier est effacé et le lien de partage cesse de fonctionner.
Réponse 200 OK : {"id":"rec_71dz","object":"recording","deleted":true}

### Webhooks
Recevez un POST sur votre serveur à chaque événement. Signature à vérifier : voir le guide Webhooks plus haut. 2 points de réception en Solo, 10 en Organisme ; celui réglé dans l’espace client, rubrique API, en fait partie.

#### POST /webhook_endpoints — Créer un point de réception
Renvoie le secret de signature, une seule fois : gardez-le côté serveur.
Corps de la requête :
- url (chaîne, obligatoire) : Adresse HTTPS, 255 caractères au plus.
- events (tableau, obligatoire) : session.started, session.ended, participant.joined, participant.left, recording.ready, recording.expired.
Exemple de corps : {"url":"https://lms.exemple.fr/hooks/visioo","events":["session.ended","recording.ready"]}
Réponse 201 Created : {"id":"whe_5xa1","object":"webhook_endpoint","url":"https://lms.exemple.fr/hooks/visioo","events":["session.ended","recording.ready"],"status":"enabled","created_at":"2026-10-31T09:20:00Z","secret":"whsec_…"}

#### GET /webhook_endpoints — Lister les points de réception
Réponse 200 OK : {"object":"list","data":[{"id":"whe_5xa1","object":"webhook_endpoint","url":"https://lms.exemple.fr/hooks/visioo","events":["session.ended","recording.ready"],"status":"enabled","created_at":"2026-10-31T09:20:00Z"}],"has_more":false,"next_cursor":null}

#### GET /webhook_endpoints/{endpoint_id} — Récupérer un point de réception
Réponse 200 OK : {"id":"whe_5xa1","object":"webhook_endpoint","url":"https://lms.exemple.fr/hooks/visioo","events":["session.ended","recording.ready"],"status":"enabled","created_at":"2026-10-31T09:20:00Z"}

#### DELETE /webhook_endpoints/{endpoint_id} — Supprimer un point de réception
Les envois en attente vers lui sont abandonnés.
Réponse 200 OK : {"id":"whe_5xa1","object":"webhook_endpoint","deleted":true}

### Équipe (Offre Organisme)
Gérer les utilisateurs du compte.

#### GET /members — Lister les utilisateurs
Utilisateurs de l’espace, administrateurs compris ; owner désigne le propriétaire du compte.
Réponse 200 OK : {"object":"list","data":[{"id":"mem_k2p0","object":"member","name":"Mehdi Benali","email":"mehdi@exemple.fr","role":"user","owner":false,"status":"active"}],"has_more":false,"next_cursor":null}

#### POST /members/invitations — Inviter un utilisateur
Envoie un e-mail d’invitation, valable 7 jours.
Corps de la requête :
- email (chaîne, obligatoire) : Adresse e-mail de la personne.
- role (chaîne) : admin ou user. user par défaut.
Exemple de corps : {"email":"julien@exemple.fr","role":"user"}
Réponse 201 Created : {"id":"inv_9wqe","object":"invitation","email":"julien@exemple.fr","role":"user","status":"pending","email_sent":true,"expires_at":"2026-11-07T09:00:00Z"}

Réunions

Chaque réunion a un lien unique, de la forme getvisioo.com/votre-espace/r/482-193-776, et un code à 9 chiffres. Vos participants la rejoignent sans compte. max_participants indique le plafond de votre offre (null : sans limite).

Lister les réunions

GET /meetings

Renvoie les réunions du compte, les plus récentes d’abord.

Paramètres de requête
limit entier
Entre 1 et 100. 20 par défaut.
cursor chaîne
Valeur next_cursor de la page précédente.
curl -X GET https://api.getvisioo.com/v1/meetings \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "id": "mtg_8f2k",
      "object": "meeting",
      "name": "Groupe du mardi",
      "url": "https://getvisioo.com/institut-horizon/r/482-193-776/",
      "code": "482-193-776",
      "auto_record": false,
      "max_participants": 100,
      "status": "idle",
      "created_at": "2026-10-31T09:12:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Créer une réunion

POST /meetings

Crée une réunion et renvoie son lien à partager.

Corps de la requête
name chaîne obligatoire
Nom affiché aux participants. 80 caractères max.
auto_record booléen
Démarre l’enregistrement avec la séance. false par défaut.
curl -X POST https://api.getvisioo.com/v1/meetings \
  -H "Authorization: Bearer $VISIOO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Groupe du mardi"}'
201 Created Réponse
{
  "id": "mtg_8f2k",
  "object": "meeting",
  "name": "Groupe du mardi",
  "url": "https://getvisioo.com/institut-horizon/r/482-193-776/",
  "code": "482-193-776",
  "auto_record": false,
  "max_participants": 100,
  "status": "idle",
  "created_at": "2026-10-31T09:12:00Z"
}

Récupérer une réunion

GET /meetings/{id}

Renvoie une réunion et son statut actuel : idle, ou live pendant une séance.

curl -X GET https://api.getvisioo.com/v1/meetings/mtg_8f2k \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "mtg_8f2k",
  "object": "meeting",
  "name": "Groupe du mardi",
  "url": "https://getvisioo.com/institut-horizon/r/482-193-776/",
  "code": "482-193-776",
  "auto_record": false,
  "max_participants": 100,
  "status": "live",
  "created_at": "2026-10-31T09:12:00Z"
}

Modifier une réunion

PATCH /meetings/{id}

Seuls les champs envoyés sont modifiés. Le lien ne change pas.

Corps de la requête
name chaîne
Nouveau nom. 80 caractères max.
auto_record booléen
Enregistrer automatiquement les prochaines séances.
curl -X PATCH https://api.getvisioo.com/v1/meetings/mtg_8f2k \
  -H "Authorization: Bearer $VISIOO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"auto_record":true}'
200 OK Réponse
{
  "id": "mtg_8f2k",
  "object": "meeting",
  "name": "Groupe du mardi",
  "url": "https://getvisioo.com/institut-horizon/r/482-193-776/",
  "code": "482-193-776",
  "auto_record": true,
  "max_participants": 100,
  "status": "idle",
  "created_at": "2026-10-31T09:12:00Z"
}

Supprimer une réunion

DELETE /meetings/{id}

Le lien cesse de fonctionner. Les enregistrements existants sont conservés.

curl -X DELETE https://api.getvisioo.com/v1/meetings/mtg_8f2k \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "mtg_8f2k",
  "object": "meeting",
  "deleted": true
}

Séances

Une séance commence quand l’animateur entre dans la réunion et se termine quand il la ferme. Ses salles de sous-groupe en font partie.

Lister les séances

GET /sessions

Les plus récentes d’abord, filtrables par réunion et par période (heure de début).

Paramètres de requête
meeting_id chaîne
Limiter à une réunion.
from date ISO 8601
Début de période, par exemple 2026-11-02 ou 2026-11-02T09:00:00Z.
to date ISO 8601
Fin de période.
limit entier
Entre 1 et 100. 20 par défaut.
cursor chaîne
Valeur next_cursor de la page précédente.
curl -X GET https://api.getvisioo.com/v1/sessions \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "id": "ses_3lq9",
      "object": "session",
      "meeting_id": "mtg_8f2k",
      "status": "ended",
      "started_at": "2026-10-28T09:00:12Z",
      "ended_at": "2026-10-28T10:05:40Z",
      "participants_count": 14,
      "recorded": true
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Récupérer une séance

GET /sessions/{session_id}

Statut live pendant la séance, ended ensuite.

curl -X GET https://api.getvisioo.com/v1/sessions/ses_3lq9 \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "ses_3lq9",
  "object": "session",
  "meeting_id": "mtg_8f2k",
  "status": "live",
  "started_at": "2026-10-28T09:00:12Z",
  "ended_at": null,
  "participants_count": 14,
  "recorded": false
}

Liste de présence

GET /sessions/{session_id}/participants

Une ligne par entrée dans la séance, avec les heures d’arrivée et de départ. Rôles : host (animateur), cohost (co-animateur), participant.

curl -X GET https://api.getvisioo.com/v1/sessions/ses_3lq9/participants \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "object": "participant",
      "display_name": "Awa Diallo",
      "role": "participant",
      "joined_at": "2026-10-28T09:01:03Z",
      "left_at": "2026-10-28T10:05:10Z",
      "duration_seconds": 3847
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Terminer une séance

POST /sessions/{session_id}/end

Ferme la séance pour tous les participants.

curl -X POST https://api.getvisioo.com/v1/sessions/ses_3lq9/end \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "ses_3lq9",
  "object": "session",
  "meeting_id": "mtg_8f2k",
  "status": "ended",
  "started_at": "2026-10-28T09:00:12Z",
  "ended_at": "2026-10-31T10:30:00Z",
  "participants_count": 14,
  "recorded": true
}

Enregistrements

Les replays sont disponibles quelques minutes après la fin de la séance. Conservation : 3 mois en Solo, 6 mois en Organisme. Chaque enregistrement consomme les heures du quota mensuel (10 h en Solo, 40 h en Organisme).

Lister les enregistrements

GET /recordings

Les plus récents d’abord.

Paramètres de requête
meeting_id chaîne
Limiter à une réunion.
status chaîne
recording, processing, ready, failed ou expired. Les replays expirés ne sont listés qu’avec expired.
limit entier
Entre 1 et 100. 20 par défaut.
cursor chaîne
Valeur next_cursor de la page précédente.
curl -X GET https://api.getvisioo.com/v1/recordings \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "id": "rec_71dz",
      "object": "recording",
      "meeting_id": "mtg_8f2k",
      "session_id": "ses_3lq9",
      "title": "Groupe du mardi",
      "duration_seconds": 3920,
      "size_bytes": 912000000,
      "status": "ready",
      "created_at": "2026-10-28T09:00:30Z",
      "expires_at": "2027-01-28T10:05:40Z",
      "share_url": null,
      "share_expires_at": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Récupérer un enregistrement

GET /recordings/{recording_id}

Statuts : recording (en cours), processing (en préparation), ready, failed.

curl -X GET https://api.getvisioo.com/v1/recordings/rec_71dz \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "rec_71dz",
  "object": "recording",
  "meeting_id": "mtg_8f2k",
  "session_id": "ses_3lq9",
  "title": "Groupe du mardi",
  "duration_seconds": 3920,
  "size_bytes": 912000000,
  "status": "ready",
  "created_at": "2026-10-28T09:00:30Z",
  "expires_at": "2027-01-28T10:05:40Z",
  "share_url": null,
  "share_expires_at": null
}

Créer un lien de partage

POST /recordings/{recording_id}/share_link

Renvoie une adresse publique pour regarder le replay, sans le télécharger. Le lien reste le même : un nouvel appel change seulement sa durée.

Corps de la requête
expires_in_days entier
De 1 à la fin de conservation. Sans valeur : jusqu’à l’expiration du replay.
curl -X POST https://api.getvisioo.com/v1/recordings/rec_71dz/share_link \
  -H "Authorization: Bearer $VISIOO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expires_in_days":30}'
201 Created Réponse
{
  "id": "rec_71dz",
  "object": "recording",
  "meeting_id": "mtg_8f2k",
  "session_id": "ses_3lq9",
  "title": "Groupe du mardi",
  "duration_seconds": 3920,
  "size_bytes": 912000000,
  "status": "ready",
  "created_at": "2026-10-28T09:00:30Z",
  "expires_at": "2027-01-28T10:05:40Z",
  "share_url": "https://getvisioo.com/institut-horizon/replay/9f2c41d07be35a86c1e4f02b7d9a6e13/",
  "share_expires_at": "2026-11-30T09:00:00Z"
}

Télécharger

GET /recordings/{recording_id}/download

Redirige (302) vers le fichier MP4, par un lien valable 1 heure. Le corps JSON donne aussi ce lien (url) et sa fin de validité (expires_at).

curl -X GET https://api.getvisioo.com/v1/recordings/rec_71dz/download \
  -H "Authorization: Bearer $VISIOO_API_KEY"
302 Found Réponse
HTTP/1.1 302 Found
Location: https://…/replay.mp4?X-Amz-Signature=…

Supprimer un enregistrement

DELETE /recordings/{recording_id}

Suppression définitive : le fichier est effacé et le lien de partage cesse de fonctionner.

curl -X DELETE https://api.getvisioo.com/v1/recordings/rec_71dz \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "rec_71dz",
  "object": "recording",
  "deleted": true
}

Webhooks

Recevez un POST sur votre serveur à chaque événement. Signature à vérifier : voir le guide Webhooks plus haut. 2 points de réception en Solo, 10 en Organisme ; celui réglé dans l’espace client, rubrique API, en fait partie.

Créer un point de réception

POST /webhook_endpoints

Renvoie le secret de signature, une seule fois : gardez-le côté serveur.

Corps de la requête
url chaîne obligatoire
Adresse HTTPS, 255 caractères au plus.
events tableau obligatoire
session.started, session.ended, participant.joined, participant.left, recording.ready, recording.expired.
curl -X POST https://api.getvisioo.com/v1/webhook_endpoints \
  -H "Authorization: Bearer $VISIOO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://lms.exemple.fr/hooks/visioo","events":["session.ended","recording.ready"]}'
201 Created Réponse
{
  "id": "whe_5xa1",
  "object": "webhook_endpoint",
  "url": "https://lms.exemple.fr/hooks/visioo",
  "events": [
    "session.ended",
    "recording.ready"
  ],
  "status": "enabled",
  "created_at": "2026-10-31T09:20:00Z",
  "secret": "whsec_…"
}

Lister les points de réception

GET /webhook_endpoints
curl -X GET https://api.getvisioo.com/v1/webhook_endpoints \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "id": "whe_5xa1",
      "object": "webhook_endpoint",
      "url": "https://lms.exemple.fr/hooks/visioo",
      "events": [
        "session.ended",
        "recording.ready"
      ],
      "status": "enabled",
      "created_at": "2026-10-31T09:20:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Récupérer un point de réception

GET /webhook_endpoints/{endpoint_id}
curl -X GET https://api.getvisioo.com/v1/webhook_endpoints/whe_5xa1 \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "whe_5xa1",
  "object": "webhook_endpoint",
  "url": "https://lms.exemple.fr/hooks/visioo",
  "events": [
    "session.ended",
    "recording.ready"
  ],
  "status": "enabled",
  "created_at": "2026-10-31T09:20:00Z"
}

Supprimer un point de réception

DELETE /webhook_endpoints/{endpoint_id}

Les envois en attente vers lui sont abandonnés.

curl -X DELETE https://api.getvisioo.com/v1/webhook_endpoints/whe_5xa1 \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "id": "whe_5xa1",
  "object": "webhook_endpoint",
  "deleted": true
}

Équipe

Gérer les utilisateurs du compte.

Offre Organisme

Lister les utilisateurs

GET /members

Utilisateurs de l’espace, administrateurs compris ; owner désigne le propriétaire du compte.

curl -X GET https://api.getvisioo.com/v1/members \
  -H "Authorization: Bearer $VISIOO_API_KEY"
200 OK Réponse
{
  "object": "list",
  "data": [
    {
      "id": "mem_k2p0",
      "object": "member",
      "name": "Mehdi Benali",
      "email": "mehdi@exemple.fr",
      "role": "user",
      "owner": false,
      "status": "active"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Inviter un utilisateur

POST /members/invitations

Envoie un e-mail d’invitation, valable 7 jours.

Corps de la requête
email chaîne obligatoire
Adresse e-mail de la personne.
role chaîne
admin ou user. user par défaut.
curl -X POST https://api.getvisioo.com/v1/members/invitations \
  -H "Authorization: Bearer $VISIOO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"julien@exemple.fr","role":"user"}'
201 Created Réponse
{
  "id": "inv_9wqe",
  "object": "invitation",
  "email": "julien@exemple.fr",
  "role": "user",
  "status": "pending",
  "email_sent": true,
  "expires_at": "2026-11-07T09:00:00Z"
}