Suivre un dossier#
Ce qui se passe après votre validation, documents, signatures, session, facture. Et comment le savoir sans interroger l'API en boucle.
Portées : clients:dossiers:read, clients:apprenants:read, clients:documents:read.
Le journal des événements#
GET /dossiers/{dossier_id}/evenements renvoie, dans l'ordre chronologique, tout ce qui est arrivé au dossier, y compris ce que fait l'organisme après vous.
{
"items": [
{ "id": "…", "type": "dossier.created", "occurred_at": "2026-09-01T10:02:11+02:00", "details": {}, "by_partner": true },
{ "id": "…", "type": "dossier.statut_changed", "occurred_at": "2026-09-02T09:15:40+02:00", "details": { "from": "brouillon", "to": "envoye" }, "by_partner": false },
{ "id": "…", "type": "inscriptions.validated", "occurred_at": "2026-09-03T11:00:00+02:00", "details": {}, "by_partner": true },
{ "id": "…", "type": "documents.sent", "occurred_at": "2026-09-03T11:05:12+02:00", "details": {}, "by_partner": false }
],
"next_since": "2026-09-03T11:05:12+02:00",
"has_more": false
}
Le mécanisme est un curseur : conservez next_since et repassez-le en since au prochain appel pour ne recevoir que la suite. null signifie qu'il n'y a rien de nouveau. Si has_more est vrai, la page était pleine (limit, 100 par défaut) : rappelez tout de suite avec since=next_since.
since = load_cursor(dossier_id) # None au premier appel
r = api.get(f"/dossiers/{dossier_id}/evenements",
params={"since": since} if since else None).json()
for ev in r["items"]:
handle(ev) # ignorer les types inconnus
if r["next_since"]:
save_cursor(dossier_id, r["next_since"])
# si r["has_more"] : rappeler immédiatement avec since=r["next_since"]
Types d'événements#
type |
Signification | details |
|---|---|---|
dossier.created |
Dossier créé | aucun |
analyse_besoin.attached |
Analyse du besoin rattachée | aucun |
dossier.statut_changed |
Changement de statut CRM (brouillon, envoye, accepte, en_cours, facture…) |
from, to |
dossier.confirmed |
Bon de commande enregistré par l'organisme | aucun |
inscriptions.validated |
Inscriptions validées, dossier verrouillé | aucun |
inscriptions.reopened |
Inscriptions rouvertes par l'organisme | aucun |
documents.sent |
Documents envoyés à la signature | aucun |
documents.signed |
Documents signés | aucun |
documents.paper_signature_issued |
Signature papier sur place émise | aucun |
apprenant.moved |
Un apprenant a changé de session (par l'organisme) | session_numero |
apprenant.removed |
Un apprenant a été retiré (par l'organisme) | aucun |
by_partner vaut true quand l'événement vient de votre intégration : pratique pour ne réagir qu'à ce que fait l'organisme. L'énumération est additive : ignorez les types inconnus.
Cadence#
Un dossier évolue à l'échelle de la journée. Une lecture toutes les 15 à 60 minutes par dossier actif est largement suffisante ; n'interrogez pas les dossiers terminés (stage final) plus d'une fois par jour.
L'état à l'instant t#
GET …/dossiers/{dossier_id}/suivi renvoie le dossier avec stage, allowed_actions, montants et lignes : le même objet que la création. Utile pour un affichage, moins pour détecter un changement.
Les documents#
GET …/dossiers/{dossier_id}/documents liste les documents du dossier qu'ELRM a rendus disponibles pour l'API, document par document, depuis son CRM. Le type n'y change rien : c'est un choix par pièce. Selon ce qui a été autorisé, vous pouvez y trouver :
doc_type |
Libellé |
|---|---|
devis_signe |
Devis signé |
convention |
Convention |
convocations |
Convocation |
inscription |
Feuille d'inscription |
emargement |
Émargement |
evaluation |
Évaluation |
satisfaction |
Satisfaction |
cartes_caces |
Carte CACES |
attestations |
Attestation de fin de formation |
factures |
Facture |
autre |
Document |
{
"items": [
{ "id": "…", "file_name": "Convocation_Martin_Lucas.pdf", "doc_type": "convocations", "doc_type_label": "Convocation", "mime_type": "application/pdf", "size_bytes": 61240 },
{ "id": "…", "file_name": "Attestation_Martin_Lucas.pdf", "doc_type": "attestations", "doc_type_label": "Attestation de fin de formation", "mime_type": "application/pdf", "size_bytes": 92110 }
],
"total": 2
}
GET …/documents/{document_id} renvoie le fichier lui-même (Content-Type du document, Content-Disposition: attachment).
docs = api.get(f"/dossiers/{dossier_id}/documents").json()["items"]
for d in docs:
content = api.get(f"/dossiers/{dossier_id}/documents/{d['id']}").content
Path(d["file_name"]).write_bytes(content)
Un événement documents.sent / documents.signed est le bon déclencheur pour relire la liste.
Les apprenants#
GET /apprenants (filtrable par dossier_id) renvoie les apprenants inscrits avec leur session : une entrée par couple apprenant × dossier.
{
"items": [
{ "id": "…", "nom": "Martin", "prenom": "Lucas", "email": "l.martin@exemple.fr", "telephone": "06 12 34 56 78", "date_naissance": "1991-04-12",
"dossier_id": "…", "dossier_numero": "DEV-2026-1400", "session_numero": "S-2026-0412" }
],
"total": 4, "limit": 100, "offset": 0
}
Tous vos dossiers#
GET /dossiers liste vos dossiers, y compris ceux créés hors API (par téléphone, par l'espace client). Chaque entrée porte stage, updated_at, les dates extrêmes, les formations et le nombre de places. Deux filtres évitent de lire …/suivi dossier par dossier :
?stage=inscriptions_ouvertes: les dossiers où vous avez quelque chose à faire ;?updated_since=2026-09-01T00:00:00Z: ce qui a bougé depuis votre dernière synchronisation.