Version 1 · 6 octobre 2026. Réservée aux centres partenaires ; les clés se créent dans l’espace partenaire (Mon profil → API).
Si vous gérez vos stages dans un logiciel de planning ou sur votre site, l’API permet à ce logiciel de nous envoyer lui-même vos stages (dates, prix, places), de les mettre à jour et de les annuler, sans que personne ne les retape dans l’espace partenaire. Cette page s’adresse à la personne qui s’occupe de votre informatique ; le § 2 explique aussi, pour vous, où trouver les informations qu’elle vous demandera.
Dans les adresses techniques ci-dessous, le mot anglais sessions désigne vos stages.
Chaque appel porte votre clé dans l’en-tête Authorization. Une clé commence par csp_live_, n’est affichée qu’une fois à sa création et se révoque à tout moment depuis votre espace. Cinq clés actives au maximum. Limite : 600 appels par 10 minutes et par clé.
Authorization: Bearer csp_live_… Content-Type: application/json
Un stage a lieu dans une salle déjà déclarée chez nous, sous l’agrément préfectoral de son département (menu Mes agréments et salles de votre espace : un agrément par département, et les salles qu’il couvre). Pour nous dire dans quelle salle a lieu un stage, votre logiciel donne, dans cet ordre de préférence :
venue_code : votre propre code de salle, celui de votre logiciel, que vous avez donné à la salle dans Mes agréments et salles (ou dans votre import de salles). C’est le plus sûr : il ne change pas et ne dépend pas de nous.centre_id : l’identifiant de la salle chez nous.agrement_number : le numéro d’agrément (celui de l’arrêté, de la forme R150640005), seulement s’il ne couvre qu’une seule de vos salles. S’il en couvre plusieurs, le stage est refusé (400) : donnez alors venue_code ou centre_id.Pour un logiciel, le même tableau s’obtient par l’API :
GET https://centrestagepermis.fr/api/v1/partner/centres
{
"centres": [ { "id": "…", "name": "…", "city": "Pau", "dept_code": "64", "agrement_number": "R150640005",
"agrement_expiry": "2031-03-12", "publishable": true, "status": "actif",
"venue_code": "PAU-1", "agrement_id": "…" } ],
"agrements": [ { "id": "…", "number": "R150640005", "dept_code": "64", "raison_sociale": "…",
"expiry": "2031-03-12", "status": "valide", "status_label": "validé", "validated": true,
"salles": [ { "id": "…", "venue_code": "PAU-1", "name": "…", "address": "…",
"postal_code": "64000", "city": "Pau", "capacity": 20,
"status": "on_arrete", "status_label": "sur l’arrêté", "validated": true,
"sellable": true, "sellable_status": "actif" } ] } ]
}centres est la liste à plat de vos salles (inchangée depuis la version 1, avec en plus venue_code et agrement_id). publishable vaut true quand la salle est activée et son agrément validé par notre équipe, non refusé et en cours de validité : ses stages passent alors directement en ligne. Sinon status dit ce qui manque.
agrements regroupe les mêmes salles sous leur agrément. Pour chaque salle, status dit où elle en est par rapport à l’arrêté : on_arrete (inscrite sur l’arrêté), declared (ajoutée depuis et déclarée au préfet) ou to_check (à vérifier par notre équipe) ; sellable applique la même règle que publishable.
Vous choisissez l’identifiant du stage (external_id) : celui de votre propre système, par exemple sa référence dans votre planning. Renvoyer le même identifiant met le stage à jour au lieu d’en créer un second. La salle se désigne par venue_code, centre_id ou agrement_number (§ 2).
PUT https://centrestagepermis.fr/api/v1/partner/sessions/{external_id}
{
"venue_code": "PAU-1", // votre code de salle ; ou "centre_id": "…" ; ou "agrement_number" s'il ne couvre qu'une salle
"day1": "2026-11-16", "day2": "2026-11-17",
"start_time": "08:30", "end_time": "16:30",
"price_cents": 20000, // ou "price_euros": 200
"spots_available": 12, // places que vous nous laissez (voir § 5) ; ou "spots_total": 12
"status": "open", // ou "cancelled"
"notes": "Parking gratuit, apportez votre permis", // facultatif, visible du stagiaire
"stage_number": "…" // obligatoire pour la mise en vente : n° d'identification du stage donné par la préfecture / l'ANTS
}
201 Created / 200 OK
{ "ok": true, "created": true, "session": { "id": "…", "external_id": "…", "status": "open",
"day1": "2026-11-16", "day2": "2026-11-17", "price_cents": 20000, "spots_total": 12,
"spots_booked_here": 0, "spots_available": 12, "url": "https://centrestagepermis.fr/reserver/…" } }Si une condition de publication manque (compte non validé, contrat non signé, établissement ou agrément non validé), le stage est enregistré en brouillon et la réponse liste les raisons dans blockers. Rien n’est jamais créé à moitié : une erreur de champ renvoie 400 avec le champ en cause et aucun enregistrement. Un stage sans stage_number est refusé (400) : toute annonce d’un stage doit afficher son numéro d’identification (arrêté du 26 juin 2012, art. 3 IV).
PATCH /api/v1/partner/sessions/{external_id} // seulement les champs envoyés (places, prix, horaires, status)
GET /api/v1/partner/sessions/{external_id}
GET /api/v1/partner/sessions?from=2026-11-01&to=2026-11-30
DELETE /api/v1/partner/sessions/{external_id} // = annulation du stageTant qu’aucun stagiaire n’a réservé chez nous, tout se modifie et s’annule par l’API.
Dès qu’un stagiaire est inscrit chez nous, une annulation (DELETE ou "status": "cancelled") ou un changement de dates n’annule rien : le stage est fermé à la vente (plus personne ne peut le réserver), les inscriptions sont conservées, et la réponse le dit :
200 OK
{ "ok": true, "result": "sales_closed", "result_label": "fermé à la vente (2 inscrits)",
"already_closed": false, "trainees_booked_here": 2, "payments_in_progress": 0,
"message": "Fermé à la vente (2 inscrits chez nous) : ce stage est annulé dans votre système …",
"session": { …, "sales_closed": { "closed_at": "…", "reason": "cancelled", "source": "api",
"trainees_at_close": 2, "label": "fermé à la vente" } } }reason vaut cancelled (annulé), removed (retiré) ou dates_changed (dates modifiées). Le champ sales_closed apparaît aussi dans GET /sessions tant que le stage reste fermé.
Vous décidez ensuite depuis la fiche du stage dans votre espace (déplacer les stagiaires, annuler le stage, ce qui les rembourse et les prévient). Si le stage avait été retiré par erreur, renvoyez-le ouvert ("status": "open") : il est remis en vente. Un stage qui disparaît de votre flux d’import suit la même règle. Nous n’annulons jamais un stage à votre place quand des stagiaires y sont inscrits.
spots_available est le nombre de places que vous nous laissez à vendre sur ce stage. Nos propres réservations restent comptées chez nous : la capacité enregistrée vaut nos réservations + vos places disponibles. Quand vous vendez une place de votre côté, renvoyez le nouveau spots_available (PATCH) et nous ne vendrons jamais au-delà. À 0, le stage est affiché « Complet » et ne se vend plus ; il repasse en vente dès que vous renvoyez des places. GET vous rend à tout moment spots_booked_here, le nombre de stagiaires inscrits par notre intermédiaire. Et nous vous prévenons de chaque changement (section 6).
Dans votre espace, Profil › Prévenir votre système de nos réservations, indiquez l’adresse HTTPS de votre système. Chaque fois que les places d’un de vos stages changent chez nous (réservation payée, place retenue pendant un paiement, annulation, rétractation, changement de stage, action de notre équipe), nous envoyons aussitôt à cette adresse un POST avec l’état du stage, au même format que GET :
POST https://votre-systeme.fr/…
Content-Type: application/json
X-CSP-Event: stage.spots_updated
X-CSP-Delivery: dlv_1234
X-CSP-Signature: t=1792610000,v1=5f2b…(hex)
{ "event": "stage.spots_updated", "delivery_id": "dlv_1234",
"sent_at": "2026-10-22T09:14:03.120Z",
"stage": { "id": "…", "external_id": "VOTRE-ID-123", "status": "open",
"spots_total": 8, "spots_booked_here": 3, "spots_available": 5, … } }spots_booked_here = places prises chez nous (y compris un paiement en cours), spots_available = places qu’il nous reste à vendre. Plusieurs changements rapprochés donnent une seule notification ; un état identique au dernier envoyé n’est pas renvoyé.HMAC-SHA256(secret, t + "." + corps brut) en hexadécimal et comparez-le à v1 ; refusez un t de plus de 5 minutes. Le secret (whsec_…) est affiché une seule fois quand vous enregistrez l’adresse ; « Nouveau secret » le remplace."event": "test", signé de la même façon.day2 suit day1 (par défaut le lendemain).