Configuration détaillée
1. Créer une application Server-to-Server OAuth
- https://marketplace.zoom.us > Develop > Build App
- App Type : Server-to-Server OAuth
- App credentials : copiez l'Account ID, le Client ID, le Client Secret
2. Scopes nécessaires
meeting:read:admin— lister les réunionsmeeting:write:admin— créer/mettre à jour/supprimer des réunionsrecording:read:admin— accéder aux enregistrementsuser:read:admin— informations sur les hôtes
3. Event Subscriptions (webhook)
- App > Feature > Event Subscriptions
- Subscription URL :
https://[tenant].studeia.com/api/webhooks/video/zoom - Authentication : Webhook secret token (copiez-le dans Studeia)
- Événements à souscrire :
- Meeting > Meeting Started
- Meeting > Meeting Ended
- Meeting > Participant Joined / Left
- Recording > Recording Completed
- Recording > Recording Transcript Completed
4. Configurer dans Studeia
Settings > Video Provider > Zoom > Add :
- Account ID
- Client ID
- Client Secret
- Webhook Secret Token (de l'étape 3)
- Set as default (optionnel — utilise Zoom pour toutes les LiveClasses sans override)
Studeia stocke tout chiffré en AES-256-GCM.
Fonctionnement
Admin/Enseignant crée une LiveClass dans Studeia (videoProvider=zoom)
↓
Studeia ZoomAdapter.createMeeting()
→ Server-to-Server OAuth token (mis en cache Redis 55 min)
→ POST https://api.zoom.us/v2/users/{userId}/meetings
→ Retourne meetingId + joinUrl + startUrl + password
↓
Studeia enregistre dans LiveClass.providerMeetingId / providerJoinUrl / providerData
↓
L'élève accède via /live-classes/[id] > clic sur "Rejoindre"
→ joinMethod=external (nouvel onglet) — Zoom ne supporte PAS les iframes (X-Frame-Options)
→ Ouvre l'application/web Zoom
↓
Pendant la réunion : les webhooks notifient Studeia
→ meeting.started → LiveClass.actualStartTime
→ participant.joined → LiveClassAttendance
→ meeting.ended → LiveClass.actualEndTime
↓
Après la fin de la réunion (~5-30 min de traitement Zoom) :
→ webhook recording.completed
→ Studeia met à jour LiveClass.recordingUrl
→ webhook recording.transcript_completed
→ Studeia crée LiveClassTranscription avec le VTT parsé
Cron de secours
Les webhooks Zoom sont peu fiables (délais, expiration des souscriptions, pannes réseau). Studeia exécute /api/cron/recording-sync toutes les 15 min :
- Recherche les LiveClasses terminées depuis > 15 min sans recordingUrl
- Pour chacune, appelle
adapter.getRecordings(meetingId)via l'API Zoom - Si trouvé, met à jour recordingUrl + crée LiveClassTranscription
Injection RAG de la transcription
Après approbation de la transcription par l'enseignant :
/institution/courses/[id]/transcriptions/[tid]/approve- Le texte de la transcription est découpé en chunks + embeddings + ContentBlock
- Metadata :
{ source: "live_class_transcript", liveClassId, courseId } - Le tuteur IA cite : "Lors du cours en direct du jour X, la professeure a expliqué que..."
Dépannage
"401 Unauthorized" lors de la création d'une réunion
Token expiré. Vérifier les logs :
- Token Server-to-Server OAuth mis en cache Redis 55 min (renouvellement automatique)
- Si le problème persiste : faire pivoter le Client Secret sur le Zoom Marketplace + le mettre à jour dans Studeia
Webhook non reçu
- Vérifier que l'URL du webhook est accessible publiquement (curl externe)
- Valider la signature HMAC SHA-256 (Studeia enregistre un avertissement en cas de mismatch)
- Zoom effectue 3 tentatives avec backoff — si les 3 échouent, l'événement webhook est perdu (le cron le récupère)
Enregistrement sans VTT
Le VTT n'est généré que si Zoom Cloud Recording est activé (pas l'enregistrement local). Vérifier User > Settings > Recording > Cloud recording activé.
Coûts
- Studeia : aucun coût supplémentaire (inclus dans tous les plans)
- Zoom : facturation directement par Zoom (licence par hôte). Studeia ne revend pas Zoom.