API partenaires

Reliez la plateforme de votre organisme de formation à Conversa : vous inscrivez vos stagiaires, vous leur ouvrez l'accès en un clic, sans mot de passe, et vous recevez chaque séance avec son évaluation. Le paiement reste chez vous.

Principe

Votre plateforme reste la référence pour vos stagiaires, leurs formations et leurs paiements. Conversa ne connaît d'eux que ce que vous lui transmettez, rattaché à votre identifiant (id_externe).

SensCe qui passe
Vous → ConversaInscription et mise à jour du stagiaire, demande d'un lien d'accès, lecture des séances, des évaluations et du solde.
Conversa → vousUn message signé à chaque séance démarrée ou terminée, à chaque évaluation prête, et quand votre solde passe sous le seuil choisi.

Chaque séance terminée par un stagiaire inscrit par l'API est décomptée une fois du solde de votre organisme. Le stagiaire ne paie rien à Conversa.

Parcours type

  1. Dans votre espace Conversa, menu Connexion API : créez une clé et indiquez l'adresse qui recevra nos messages.
  2. À l'inscription d'un stagiaire chez vous : POST /api/v1/apprenants.php.
  3. Quand il clique sur « S'entraîner à l'oral » : POST /api/v1/acces.php, puis redirigez-le vers l'url reçue.
  4. Il fait sa séance sur Conversa, puis consulte son compte rendu.
  5. Vous recevez seance.terminee puis evaluation.prete, et vous enregistrez le résultat dans son dossier.

Authentification

Toutes les adresses commencent par https://conversa.fr/api/v1/, en HTTPS. Chaque requête porte votre clé dans l'en-tête X-Api-Key. L'en-tête Authorization: Bearer … est aussi accepté, mais certains serveurs le suppriment en route : préférez X-Api-Key.

curl https://conversa.fr/api/v1/credits.php \ -H "X-Api-Key: cvs_votre_cle"

La clé s'utilise uniquement depuis votre serveur, jamais dans le navigateur ni dans une application mobile. Limite : 120 requêtes par minute et par clé (au-delà : 429 et l'en-tête Retry-After).

Erreurs

Toute réponse est un objet JSON. En cas d'échec, ok vaut false et erreur donne un code stable et un message lisible.

{ "ok": false, "erreur": { "code": "apprenant_inconnu", "message": "Aucun apprenant avec cet id_externe." } }
HTTPSignification
400 / 422Requête mal formée ou champ invalide : le message dit lequel.
401Clé absente, invalide ou révoquée.
403Organisme suspendu.
404Apprenant ou séance inconnu de votre organisme.
409Action impossible en l'état : apprenant suspendu, droits épuisés.
429Trop de requêtes : réessayez après le délai de Retry-After.
5xxIncident de notre côté : réessayez plus tard.

Apprenants

POST /api/v1/apprenants.php crée l'apprenant s'il n'existe pas, et sinon met à jour seulement les champs envoyés. Rappelez-le autant de fois que nécessaire : le résultat est le même.

ChampObligatoireDescription
id_externeouiVotre identifiant du stagiaire. 1 à 100 caractères parmi A-Z a-z 0-9 . _ : @ -.
langue_cibleà la créationLangue des séances : en, es, de… (liste dans le message d'erreur si le code est inconnu).
prenomconseilléL'avatar s'adresse au stagiaire par son prénom.
langue_maternelleconseilléLe compte rendu traduit le vocabulaire conseillé dans cette langue.
niveauconseilléA1 à C2.
nb_seancesconseilléNombre de séances accordées. null : sans limite (dans la limite du solde de l'organisme).
acces_jusqu_auconseilléDate de fin, AAAA-MM-JJ. L'accès se ferme le lendemain.
groupenonSession ou cohorte, pour vos statistiques.
scenariosnonListe d'identifiants de scénarios autorisés (voir Scénarios). Absent ou vide : tous.
statutnonactive ou suspended.
nom, emailnonInutiles au fonctionnement. Ne les envoyez que si vous en avez besoin.
curl -X POST https://conversa.fr/api/v1/apprenants.php \ -H "X-Api-Key: cvs_votre_cle" -H "Content-Type: application/json" \ -d '{ "id_externe": "STG-2026-0142", "prenom": "Camille", "langue_cible": "en", "langue_maternelle": "fr", "niveau": "B1", "nb_seances": 10, "acces_jusqu_au": "2026-12-31", "groupe": "Anglais pro - nov. 2026" }'

Réponse 201 à la création, 200 à la mise à jour :

{ "ok": true, "cree": true, "apprenant": { "id_externe": "STG-2026-0142", "prenom": "Camille", "nom": "", "email": null, "langue_cible": "en", "langue_maternelle": "fr", "niveau": "B1", "nb_seances": 10, "seances_faites": 0, "seances_restantes": 10, "acces_jusqu_au": "2026-12-31", "groupe": "Anglais pro - nov. 2026", "scenarios": null, "statut": "active", "cree_le": "2026-10-03T17:42:10+02:00" } }

GET /api/v1/apprenants.php?id_externe=STG-2026-0142 relit l'apprenant et ses compteurs.
DELETE /api/v1/apprenants.php?id_externe=STG-2026-0142 l'efface définitivement, avec ses séances, ses évaluations et ses enregistrements audio.

Lien d'accès

POST /api/v1/acces.php renvoie un lien qui connecte le stagiaire à Conversa, sans mot de passe. Le lien sert une seule fois et expire au bout de 5 minutes : demandez-le au moment du clic, jamais à l'avance, et ne l'envoyez pas par email.

curl -X POST https://conversa.fr/api/v1/acces.php \ -H "X-Api-Key: cvs_votre_cle" -H "Content-Type: application/json" \ -d '{ "id_externe": "STG-2026-0142", "scenario_id": 3 }' { "ok": true, "url": "https://conversa.fr/acces?t=…", "expire_le": "2026-10-03T17:47:10+02:00" }

scenario_id est facultatif : il présélectionne un scénario. Si le stagiaire n'a plus de droits (solde de l'organisme épuisé, séances utilisées, date dépassée, scénario non autorisé), la réponse est 409 droits_epuises avec un message que vous pouvez lui afficher.

Lien signé, sans appel d'API

Pour proposer seulement les conversations avec l'avatar IA (ou la voix), votre serveur peut fabriquer lui-même le lien, sans créer le stagiaire au préalable. Le secret et les domaines autorisés se règlent dans l'espace organisme, rubrique Avatar intégré. Le stagiaire est créé à sa première venue, puis mis à jour à chaque lien ; il ne voit que la séance, son résultat et un bouton de retour vers votre plateforme.

https://conversa.fr/avatar?o=ORG&e=STG-2026-0142&p=Lea&n=Martin&l=en&m=fr&niv=B1&s=3 &ref=inscription-881&retour=https%3A%2F%2Fformation.exemple.fr%2Fconversa%2Fretour &t=1760090000&nonce=9f2c4e6a8b1d3f50&sig=…

o votre numéro d'organisme, e l'identifiant du stagiaire chez vous (obligatoire), p/n prénom et nom, l la langue apprise, m la langue maternelle, niv A1 à C2, s le scénario, ref votre référence (100 caractères), retour une adresse HTTPS sur un domaine déclaré, t l'horodatage Unix (5 minutes de tolérance), nonce 16 à 64 caractères hexadécimaux, jamais réutilisé.

Signature : sig = HMAC-SHA256 en hexadécimal, avec votre secret de lien, de la chaîne formée de tous les autres paramètres triés par nom, encodés en RFC 3986 (%20 pour l'espace) et joints par &. En PHP : ksort($p); hash_hmac('sha256', http_build_query($p, '', '&', PHP_QUERY_RFC3986), $secret). Le secret ne doit jamais apparaître dans une page web : le lien se fabrique sur votre serveur, au moment du clic.

Retour : sur la page de résultat, le stagiaire revient vers retour avec ref, e, seance, statut (termine, en_cours, aucune), score, niveau, t et sig, signés de la même façon. Le détail complet (critères, synthèse) part par message signé : seance.terminee puis evaluation.prete, qui portent la même reference.

Séances et évaluations

GET /api/v1/seances.php?id_externe=STG-2026-0142 : les 100 dernières séances du stagiaire.
GET /api/v1/seances.php?id=… : une séance, avec l'évaluation complète. Ajoutez &transcription=1 pour le texte de la conversation.

{ "ok": true, "seance": { "id": "0ac40e64128e9f14191b09f80676d8af", "id_externe": "STG-2026-0142", "statut": "completed", "scenario": { "id": 3, "titre": "Au restaurant" }, "langue": "en", "debut": "2026-10-03T18:01:12+02:00", "fin": "2026-10-03T18:11:40+02:00", "duree_sec": 628, "decomptee": true, "evaluation": { "score_global": 68.5, "niveau_estime": "B1", "criteres": { "comprehension": 75, "fluency": 62, "grammar": 66, "vocabulary": 70, "pronunciation": 71 }, "synthese": "…", "points_forts": ["…"], "axes_progres": ["…"], "evaluee_le": "2026-10-03T18:12:05+02:00", "detail": { "…": "grille complète, uniquement sur une séance demandée par son id" } } } }

evaluation vaut null tant que le compte rendu n'est pas produit : il l'est quand le stagiaire ouvre la page de résultat, à la fin de sa séance.

Crédits

GET /api/v1/credits.php : { "ok": true, "credits_restants": 42, "seuil_alerte": 5 }. Un crédit correspond à une séance terminée. Le rechargement se fait dans votre espace Conversa (menu Acheter des crédits).

Demandes de séances

Un stagiaire ne paie rien sur Conversa. Quand il veut d'autres séances, il les demande depuis son espace (menu Commander des séances). Vous recevez le message seances.demandees, vous validez sur votre plateforme (paiement, accord du responsable…), puis vous répondez :

POST /api/v1/demandes.php { "id": 42, "decision": "acceptee", "nb_seances": 5 } // nb_seances facultatif : par défaut, le nombre demandé { "id": 42, "decision": "refusee", "motif": "Budget formation épuisé" }

Acceptée, la demande ajoute nb_seances au droit du stagiaire (nb_seances de sa fiche) : il peut pratiquer aussitôt. Le motif d'un refus s'affiche dans son espace. Une demande ne se traite qu'une fois : une seconde réponse renvoie 409 deja_traitee.

GET /api/v1/demandes.php : les demandes en attente (?statut=toutes pour les 200 dernières, ?id=42 pour une seule).

{ "ok": true, "demande": { "id": 42, "statut": "en_attente", "nb_seances": 5, "message": "Préparer un entretien en anglais", "seances_accordees": null, "motif": null, "traitee_par": null, "cree_le": "2026-10-04T10:12:00+02:00", "traitee_le": null, "apprenant": { "id_externe": "STG-2026-0142", "prenom": "Léa", "nom": "Martin", "email": "lea.martin@exemple.fr" } } }

Sans plateforme reliée, ou si vous préférez, la même demande se traite dans votre espace Conversa (menu Demandes de séances) ; vous recevez alors demande.traitee.

Visio et présences

Les créneaux en Visio Conversa (visio intégrée, avec un intervenant) mesurent le temps de présence de chacun. À la clôture, 15 minutes après la fin, chaque réservation est décomptée selon une règle fixe :

decompteSituationSéance décomptée
debitePrésence cumulée d'au moins 50 % de la durée (les reconnexions s'additionnent).Oui
partiellePrésence inférieure à 50 %.Non
absent / absent_debiteAucune présence ; décomptée ou non selon votre réglage (menu Créneaux).Selon réglage
serviceL'intervenant n'est pas venu (moins d'une minute).Non

GET /api/v1/visios.php?id_externe=STG-2026-0142 : les visios du stagiaire. GET /api/v1/visios.php?creneau=12 : un créneau et tous ses participants. Chaque réservation porte presence_sec, decompte, decomptee et le détail des passages (entree, sortie, source : serveur_video fait foi, navigateur sert de secours) : de quoi répondre à une réclamation.

Une séance décomptée compte dans seances_faites du stagiaire et consomme un crédit de votre organisme, comme une séance avec le tuteur IA.

Formateurs et comptes rendus

GET /api/v1/formateurs.php (ou ?langue=en, ?id=12) : les formateurs que vous pouvez placer sur vos créneaux en visio, les vôtres et ceux de la bourse partagée de Conversa. L’email et le téléphone ne sont jamais transmis.

{ "ok": true, "formateur": { "id": 12, "prenom": "Anne", "nom": "Martin", "photo": "https://conversa.fr/_formateurs/f-12-3a9c….jpg", "localisation": "Lyon, France", "langues": [ { "code": "en", "libelle": "Anglais" } ], "accent": "Anglais britannique", "niveaux": ["B1", "B2", "C1"], "specialites": "Entretien d’embauche", "presentation": "…", "origine": "bourse_conversa", "statut": "actif", "tarifs": { "10_min": 9.9, "20_min": 17.9, "30_min": 24.9, "60_min": 45 } } }

Chaque fiche porte aussi id_externe (le vôtre, si vous l’avez créée) et gere_par : votre_plateforme, organisme ou conversa. Une fiche se lit aussi par ?id_externe=F-42.

Gérer vos formateurs depuis votre plateforme

POST /api/v1/formateurs.php crée le formateur, ou le met à jour s’il existe déjà avec ce id_externe (réponse 201 à la création, 200 à la mise à jour). La fiche envoyée remplace la précédente ; seuls email et telephone, s’ils sont absents, sont conservés. Un formateur créé ainsi est en lecture seule dans Conversa : votre plateforme le tient à jour, vos administrateurs le voient sans pouvoir le modifier. Il n’a pas de tarif public : c’est vous qui le rémunérez.

POST /api/v1/formateurs.php { "id_externe": "F-42", "prenom": "Nadia", "nom": "Benali", "email": "nadia.benali@votre-domaine.fr", "langues": ["en", "fr"], "accent": "britannique", "niveaux": ["B1", "B2"], "specialites": "Anglais des affaires", "presentation": "…", "ville": "Marseille", "pays": "France", "photo_url": "https://votre-domaine.fr/photos/f-42.jpg", "statut": "actif" }

photo_url : une adresse https publique (JPG, PNG ou WEBP, 2 Mo au plus) ; l’image est téléchargée puis recadrée en 400 × 400. En cas d’échec, le formateur est quand même enregistré et la réponse porte avertissement_photo. email sert à lui ouvrir son espace formateur (planning, visio, comptes rendus) : jamais transmis aux apprenants. statut : actif ou suspendu.

DELETE /api/v1/formateurs.php?id_externe=F-42 le retire : supprimé s’il n’a jamais eu de créneau, sinon suspendu (son historique et ses comptes rendus restent).

Dans GET /api/v1/visios.php, chaque créneau porte formateur (même fiche, sans les tarifs) et chaque réservation porte compte_rendu : niveau_observe, points_forts, a_travailler, devoirs, commentaire, redige_le (null tant que le formateur ne l’a pas rempli). Le formateur le remplit après la séance ; vous recevez alors visio.compte_rendu.

Scénarios

GET /api/v1/scenarios.php (ou ?langue=en) : les scénarios disponibles, avec id, titre, langue, cecrl (niveau A1 à C2), difficulte (beginner, intermediate ou advanced, déduite du niveau) et duree_min. Leurs identifiants servent dans scenarios (apprenant) et scenario_id (lien d'accès).

Cours : importer, exporter, SCORM

GET /api/v1/cours.php : les cours que vos apprenants peuvent suivre, c'est-à-dire ceux de la bibliothèque Conversa et les vôtres (proprietaire : conversa ou organisme), avec id, titre, langue, cecrl, theme, statut et le nombre de lecons.

POST /api/v1/cours.php importe un cours. Il vous appartient, seuls vos apprenants le voient, et vous pouvez le récupérer à tout moment avec GET ?id=. Un cours par appel, 2 Mo au plus. Chaque bloc passe par les mêmes contrôles que l'éditeur : un bloc mal formé est écarté et signalé dans rejets, le reste est enregistré. Le format natif :

curl -X POST https://conversa.fr/api/v1/cours.php -H "X-Api-Key: VOTRE_CLE" -H "Content-Type: application/json" -d '{ "titre": "Accueillir un client", "langue": "en", "cecrl": "A2", "statut": "publie", "lecons": [{ "titre": "Saluer", "objectif": "Saluer selon l heure", "blocs": [ {"type": "regle", "texte": "On dit **Good morning** jusqu a midi..."}, {"type": "exemple", "texte": "Good morning! (Bonjour !)"}, {"type": "qcm", "consigne": "Il est 9 h.", "question": "You say:", "choix": "* Good morning Good night", "explication": "..."}, {"type": "trous", "texte": "Good {afternoon}! How can I {help} you?"}, {"type": "ordre", "phrase": "Can / I / help / you?"}, {"type": "appariement", "paires": "morning = matin evening = soir"}, {"type": "vrai_faux", "affirmation": "Good night se dit en arrivant.", "vrai": "0"}, {"type": "traduction", "phrase": "Bonjour, je peux vous aider ?", "reponses": "Hello, can I help you?"}, {"type": "redaction", "sujet": "Accueillez un client par écrit.", "mots_min": "20"}, {"type": "dictee", "phrase": "Welcome to our shop."}, {"type": "comprehension", "texte": "Hello, I am Anna...", "question": "Who is Anna?", "choix": "* a nurse a doctor"}, {"type": "oral_repeter", "phrase": "How can I help you?"}, {"type": "oral_repondre", "question": "What is your job?", "attendu": "I am a ..."} ] }] }'

Les champs de chaque type sont ceux de l'éditeur : choix donne une proposition par ligne, avec une étoile devant chaque bonne réponse ; dans texte, les accolades marquent les trous, et | sépare plusieurs réponses acceptées ; phrase découpe les morceaux par / ; paires donne une paire par ligne, sous la forme gauche = droite. Les sons de la dictée, de la compréhension et de l'oral sont produits à l'import. Tout bloc accepte consigne, explication et points.

Questions Moodle (GIFT) : envoyez {"format": "gift", "titre": "...", "langue": "en", "cecrl": "A2", "gift": "…le texte GIFT…"}. Les choix uniques et multiples, les vrai ou faux, les réponses courtes (qui deviennent des textes à trous) et les associations deviennent une leçon d'exercices.

Tableur (CSV) : {"format": "csv", "titre": "...", "langue": "en", "cecrl": "A2", "csv": "…"}. Une ligne par exercice ; la première ligne porte les en-têtes type;enonce;reponse;autres;explication (séparateur point-virgule, virgule ou tabulation). Types : qcm (reponse = bonnes réponses, autres = mauvaises, séparées par |), vrai_faux (reponse = vrai ou faux), trous (enonce avec ___, reponse = réponses acceptées séparées par |), ordre (morceaux séparés par /), appariement (reponse = gauche = droite | gauche = droite).

QTI : {"format": "qti", "titre": "...", "langue": "en", "cecrl": "A2", "qti": "<?xml …"}, un document XML QTI 2.x (assessmentItem ou assessmentTest avec ses questions) ou QTI 1.2 (questestinterop, export Canvas ou Blackboard). Choix, textes à trous, associations et ordres sont repris ; les autres interactions sont signalées dans rejets. Un paquet .zip s'importe depuis votre espace, rubrique Cours > Importer.

GET /api/v1/cours.php?id=12 renvoie un de vos cours au même format natif (format : conversa-cours-1), réimportable tel quel. Les cours de la bibliothèque Conversa ne s'exportent qu'en SCORM.

GET /api/v1/cours.php?id=12&format=scorm renvoie un paquet SCORM 1.2 (zip) à déposer dans votre LMS (Moodle, etc.). Dans le LMS, l'apprenant clique sur « Ouvrir le cours » : Conversa s'ouvre dans une fenêtre, l'apprenant est créé dans votre organisme à sa première venue (id_externe : scorm-<paquet>-<son identifiant dans le LMS>), et sa progression remonte au LMS (score sur 100, statut incomplete ou completed). Le paquet ne contient pas le cours mais un lanceur : le contenu reste à jour, et la correction par l'IA comme l'oral fonctionnent. Il donne accès à ce seul cours, pour vos seuls apprenants, avec 300 nouveaux apprenants par jour au plus.

DELETE /api/v1/cours.php?id=12 supprime un de vos cours, avec ses leçons et les réponses de vos apprenants.

Devoirs

POST /api/v1/devoirs.php assigne des leçons, à un apprenant ({"apprenant": "ID", "lecons": [4, 5], "echeance": "2026-11-01"}) ou à tout un groupe ({"groupe": "Anglais pro", "lecons": [4]}). La liste envoyée remplace les leçons que vous aviez déjà assignées ; une liste vide les retire. Les leçons recommandées après une conversation ou par un formateur restent. Une leçon que l'apprenant ne peut pas suivre est ignorée et rendue dans lecons_ignorees.

GET /api/v1/devoirs.php?apprenant=ID : tous ses devoirs, avec source (conversation, formateur ou organisme), raison, echeance et fait (leçon terminée).

Résultats des cours

GET /api/v1/resultats.php : par apprenant, lecons_terminees, score_moyen, xp, niveau (1 à 10), serie_jours (jours de suite au défi du jour) et derniere_activite. ?depuis=AAAA-MM-JJ limite le compte des leçons terminées.

GET /api/v1/resultats.php?apprenant=ID : le détail, avec chaque leçon commencée ou terminée, son statut, son score et ses dates. Quand un apprenant termine une leçon pour la première fois, vous recevez lecon.terminee.

Messages signés

Conversa envoie un POST JSON à l'adresse réglée dans votre espace (menu Connexion API). Répondez par un code 2xx en moins de 10 secondes. Sinon, le message est renvoyé 8 fois en environ deux jours (1, 5, 15, 60 minutes, puis 3, 6, 12 et 24 heures).

TypeQuanddonnees
seance.demarreeLe stagiaire commence une séance.seance
seance.termineeLa séance est finie et décomptée.seance
evaluation.preteLe compte rendu est produit.seance, évaluation comprise
seances.demandeesUn stagiaire demande des séances supplémentaires.demande
demande.traiteeUne demande est acceptée ou refusée depuis votre espace Conversa.demande
visio.termineeUne visio Conversa est clôturée : une fois par stagiaire inscrit.visio : creneau, id_externe, presence_sec, decompte, decomptee
lecon.termineeUn apprenant a terminé une leçon pour la première fois.lecon : id, titre, cours_id, cours, id_externe, score
visio.compte_renduLe formateur a rempli (ou corrigé) le compte rendu d’un stagiaire.compte_rendu : creneau, id_externe, formateur_id, niveau_observe, points_forts, a_travailler, devoirs, commentaire
credits.basLe solde atteint le seuil choisi, puis zéro.credits_restants, seuil_alerte
testBouton « Envoyer un message de test ».message
POST https://votre-plateforme.fr/conversa/messages Content-Type: application/json; charset=utf-8 X-Conversa-Event: evaluation.prete X-Conversa-Id: 9f2c4e… X-Conversa-Signature: t=1791040325,v1=5b1f… { "id": "9f2c4e…", "type": "evaluation.prete", "cree_le": "2026-10-03T18:12:05+02:00", "donnees": { "seance": { … même format que GET /api/v1/seances.php … } } }

Un même message peut arriver plus d'une fois (par exemple si votre réponse s'est perdue). Enregistrez son id et ignorez un id déjà traité.

Vérifier la signature

Le secret de signature s'affiche une fois, dans votre espace, quand vous enregistrez l'adresse de réception. La signature est un HMAC-SHA256 du texte t + "." + corps brut. Refusez un message dont la signature ne correspond pas, ou dont t a plus de 5 minutes d'écart avec votre horloge.

<?php $secret = getenv('CONVERSA_WEBHOOK_SECRET'); $corps = file_get_contents('php://input'); // le corps BRUT, avant json_decode preg_match('/t=(\d+),v1=([a-f0-9]{64})/', $_SERVER['HTTP_X_CONVERSA_SIGNATURE'] ?? '', $m); $attendu = hash_hmac('sha256', ($m[1] ?? '') . '.' . $corps, $secret); if (!$m || !hash_equals($attendu, $m[2]) || abs(time() - (int)$m[1]) > 300) { http_response_code(401); exit; } $message = json_decode($corps, true); // … ignorer si $message['id'] est déjà enregistré, sinon traiter … http_response_code(204);

Données personnelles

Conversa traite pour votre compte la voix de vos stagiaires et leurs évaluations : un contrat de sous-traitance (article 28 du RGPD) s'impose entre votre organisme et Conversa. Seuls id_externe et langue_cible sont nécessaires : n'envoyez ni nom ni email si vous n'en avez pas l'usage. DELETE /api/v1/apprenants.php efface un stagiaire et tout ce qui le concerne, enregistrements audio compris.