ELRM developer Bac à sable

Inscrire et répartir les apprenants#

Une fois le dossier créé, deux étapes : la liste des apprenants, puis leur répartition dans des sessions. Les mêmes que dans l'espace client.

Toutes les routes de ce guide sont sous /dossiers/{dossier_id}/inscriptions. Portées : clients:apprenants:write et clients:dossiers:read. Le dossier doit être à l'étape inscriptions_ouvertes.

Ni numéro de sécurité sociale ni situation de handicap ne transitent par l'API : l'apprenant renseigne ces informations lui-même dans son espace, après l'inscription. Vous fournissez une identité minimale.

L'état des inscriptions#

GET …/inscriptions renvoie tout ce dont vous avez besoin, et le renvoie après chaque écriture :

{
  "dossier_id": "…", "numero": "DEV-2026-1400",
  "stage": "inscriptions_ouvertes", "allowed_actions": ["set_apprenants", "validate_inscriptions"],
  "step": "step1", "locked": false, "total_places": 4,
  "lignes": [
    { "id": "L1…", "formation_label": "R482, 3 catégories, expérimenté", "caces_recommendation": "R482", "categories": ["A", "C1"], "nb_apprenants": 4 }
  ],
  "apprenants": [],
  "sessions_candidates": [
    { "numero": "S-2026-0412", "formation_label": "…", "date_debut": "2026-10-05", "date_fin": "2026-10-09", "horaires": "8h30 – 17h00",
      "centre_label": "Centre de Gennevilliers", "caces_recommendation": "R482", "caces_categories": ["A", "C1"],
      "capacite_max": 8, "inscrits_count": 3, "places_restantes": 5, "can_add_apprenant": true }
  ]
}
  • step : step1 (liste et lignes), step2 (répartition), done (verrouillé).
  • lignes : les lignes du devis ; chaque apprenant doit être rattaché à une ou plusieurs lignes.
  • sessions_candidates : les sessions compatibles avec les lignes du dossier, avec leurs places. Vous choisissez parmi elles.
  • La réponse porte un en-tête ETag : conservez-le, il est exigé sur les écritures (voir Idempotence et concurrence).

Étape 1 : La liste des apprenants#

PUT …/inscriptions/apprenants remplace la liste. Chaque apprenant indique les lignes qu'il suit.

ETAG=$(curl -s -D - -o /dev/null "https://developer.elrm.app/sandbox/v1/dossiers/{dossier_id}/inscriptions" \
  -H "Authorization: Bearer pk_test_…" | grep -i '^etag:' | cut -d' ' -f2 | tr -d '\r')

curl -X PUT "https://developer.elrm.app/sandbox/v1/dossiers/{dossier_id}/inscriptions/apprenants" \
  -H "Authorization: Bearer pk_test_…" \
  -H "If-Match: $ETAG" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "apprenants": [
      { "nom": "Martin", "prenom": "Lucas", "email": "l.martin@exemple.fr", "telephone": "06 12 34 56 78", "date_naissance": "1991-04-12", "ligne_ids": ["L1…"] },
      { "nom": "Bernard", "prenom": "Inès", "email": "i.bernard@exemple.fr", "telephone": "", "date_naissance": "1988-09-30", "ligne_ids": ["L1…"] }
    ]
  }'
base = f"/dossiers/{dossier_id}/inscriptions"
state = api.get(base)
etag = state.headers["ETag"]
ligne_id = state.json()["lignes"][0]["id"]

r = api.put(f"{base}/apprenants", json={"apprenants": [
    {"nom": "Martin", "prenom": "Lucas", "email": "l.martin@exemple.fr",
     "telephone": "06 12 34 56 78", "date_naissance": "1991-04-12", "ligne_ids": [ligne_id]},
    {"nom": "Bernard", "prenom": "Inès", "email": "i.bernard@exemple.fr",
     "date_naissance": "1988-09-30", "ligne_ids": [ligne_id]},
]}, headers={"If-Match": etag, "Idempotency-Key": str(uuid.uuid4())})
r.raise_for_status()
etag = r.headers["ETag"]                # nouvel ETag pour la suite
apprenants = r.json()["apprenants"]     # chacun a maintenant un id
  • Pour modifier un apprenant existant, renvoyez-le avec son id ; sans id, c'est une création. Un apprenant absent de la liste est retiré, sauf s'il est déjà engagé sur une session (can_delete: false).
  • Carnet du client : à l'ouverture, la liste peut déjà contenir des personnes connues d'un dossier précédent, marquées carnet: true. Elles ne sont inscrites que si vous les gardez dans votre PUT ; les omettre les détache de ce dossier, sans rien supprimer ailleurs. Relisez donc GET …/inscriptions avant votre premier PUT plutôt que d'envoyer une liste construite à l'aveugle.
  • date_naissance au format YYYY-MM-DD.
  • Sans If-Match : 428. If-Match périmé : 412, relisez et recommencez.

Quand la liste est complète : POST …/inscriptions/etape-1/valider → step = step2.

Étape 2 : La répartition#

Pour chaque apprenant et chaque ligne, choisissez une session parmi sessions_candidates :

curl -X PUT "https://developer.elrm.app/sandbox/v1/dossiers/{dossier_id}/inscriptions/apprenants/{apprenant_id}/session" \
  -H "Authorization: Bearer pk_test_…" \
  -H "Content-Type: application/json" \
  -d '{ "ligne_id": "L1…", "session_numero": "S-2026-0412" }'
for a in apprenants:
    for lid in a["ligne_ids"]:
        api.put(f"{base}/apprenants/{a['id']}/session",
                json={"ligne_id": lid, "session_numero": "S-2026-0412"}).raise_for_status()

La réponse est l'état complet, sessions_candidates[].places_restantes mis à jour. Une session pleine a can_add_apprenant: false.

Pour retirer un placement : DELETE …/apprenants/{apprenant_id}/session/{ligne_id}.

Besoin de revenir à la liste ? POST …/inscriptions/etape-1/rouvrir ramène à step1 (tant que la validation finale n'a pas eu lieu).

Validation finale#

curl -X POST "https://developer.elrm.app/sandbox/v1/dossiers/{dossier_id}/inscriptions/valider" \
  -H "Authorization: Bearer pk_test_…" \
  -H "Idempotency-Key: $(uuidgen)"

Tous les apprenants doivent être placés sur toutes leurs lignes. La validation crée les inscriptions, verrouille le dossier (locked: true, step: done, stage: inscriptions_validees) et passe la main à l'organisme : convocations, convention, documents d'entrée en formation. À partir de là, plus aucune écriture n'est possible par l'API, une modification passe par ELRM.

Résumé du flux#

GET  …/inscriptions                       → ETag, lignes, sessions_candidates
PUT  …/inscriptions/apprenants            (If-Match)      → apprenants[].id
POST …/inscriptions/etape-1/valider                       → step2
PUT  …/apprenants/{id}/session  × N                       → placements
POST …/inscriptions/valider                               → done, dossier verrouillé

Anciennes routes#

POST /inscriptions et GET /inscriptions (« demandes d'inscription » à examiner par l'organisme) sont dépréciées et ne sont plus attribuées aux nouvelles clés. Les intégrations existantes continuent de fonctionner ; vous serez prévenus par email avant tout retrait.