API publique
Une API pour brancher Cadanse au reste de vos outils — tableur, comptabilité, infolettre, automatisation. Tout ce qui sort se lit ; ce qui entre s'écrit avec une clé d'idempotence. Une clé par studio, un en-tête, du JSON.
Le contrat
Le document OpenAPI 3.0 est servi sans clé et engendré depuis le code qui répond : il ne peut pas décrire autre chose que ce que l'API rend réellement. C'est lui qu'il faut donner à un générateur de client.
Ouvrir openapi.json
Commencer
Fabriquez une clé au tableau de bord, dans Configuration. Son secret n'est montré qu'une fois — recopiez-le tout de suite, Cadanse n'en conserve qu'une empreinte et ne peut pas vous le redonner.
Vérifiez-la sur la route d'identité, qui n'exige aucune portée et rend votre studio, vos portées et votre quota restant :
curl -H "Authorization: Bearer cad_..." \
https://cadanse.app/api/v1/moi
Puis lisez une collection. Chaque réponse porte « data » et « next » ; repassez « next » en « apres » jusqu'à ce qu'il soit nul.
curl -H "Authorization: Bearer cad_..." \
"https://cadanse.app/api/v1/familles?limite=100"
120 requêtes par minute et 20000 par jour, par clé. Un dépassement rend 429 avec l'en-tête « Retry-After ». Le compteur est fermé par défaut : injoignable, il refuse plutôt que de laisser passer.
Pagination et filtre
Les trois paramètres acceptés par chaque collection.
| Paramètre | Type | Défaut |
|---|
| apresCurseur exclusif : le dernier identifiant reçu à la page précédente, c'est-à-dire la valeur de « next ». Absent, la lecture commence au début. | string | — |
|---|
| limiteNombre de lignes par page. Une valeur supérieure à 200 est ramenée à 200 sans erreur ; une valeur non entière ou nulle est refusée. | integer | 50 |
|---|
| modifieDepuisNe rend que les lignes dont « updatedAt » est postérieur ou égal à cet instant ISO 8601. Une date invalide est REFUSÉE, jamais ignorée : un filtre qui disparaît en silence fait relire toute la collection à chaque sondage. | string | — |
|---|
Collections
Chacune demande la portée « <ressource>:lecture » (par exemple « familles:lecture » ; cours, camps, événements et représentations n'exposent aucune coordonnée de famille). Les champs listés sont exhaustifs : ce qui n'y figure pas ne sort pas de Cadanse.
/api/v1/familles
Demande la portée « familles:lecture ».
/api/v1/familles| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| lastName | string | non |
|---|
| contactFirstName | string | oui |
|---|
| contactEmail | string | non |
|---|
| contactPhone | string | oui |
|---|
| address | string | oui |
|---|
| parent2FirstName | string | oui |
|---|
| parent2LastName | string | oui |
|---|
| parent2Email | string | oui |
|---|
| parent2Phone | string | oui |
|---|
| emailOptIn | boolean | non |
|---|
| smsOptIn | boolean | non |
|---|
| emailCommercialOptOutAt | string | oui |
|---|
| smsOptOutAt | string | oui |
|---|
| archivedAt | string | oui |
|---|
| mergedIntoId | string | oui |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/eleves
Demande la portée « eleves:lecture ».
/api/v1/eleves| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| familyId | string | non |
|---|
| firstName | string | non |
|---|
| lastName | string | non |
|---|
| birthDate | string | oui |
|---|
| isAdult | boolean | non |
|---|
| competitive | boolean | non |
|---|
| photoConsentAt | string | oui |
|---|
| photoConsentWithdrawnAt | string | oui |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/cours
Demande la portée « cours:lecture ».
/api/v1/cours| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| sessionId | string | non |
|---|
| name | string | non |
|---|
| description | string | oui |
|---|
| registrationEmailNote | string | oui |
|---|
| styleId | string | non |
|---|
| levelId | string | oui |
|---|
| stream | "RECREATIONAL" | "COMPETITIVE" | "BOTH" | "ADULT_RECREATIONAL" | "ADULT_COMPETITIVE" | "ADULT_BOTH" | non |
|---|
| minAge | number | oui |
|---|
| maxAge | number | oui |
|---|
| ageCutoffMonth | number | oui |
|---|
| ageCutoffDay | number | oui |
|---|
| capacity | number | non |
|---|
| price | string | non |
|---|
| taxExempt | boolean | non |
|---|
| instructorId | string | oui |
|---|
| assistantIds | string[] | non |
|---|
| coInstructorIds | string[] | non |
|---|
| roomId | string | oui |
|---|
| trialsOpen | boolean | non |
|---|
| approvalRequired | boolean | non |
|---|
| slots | object[] | non |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/inscriptions
Demande la portée « inscriptions:lecture ».
/api/v1/inscriptions| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| studentId | string | non |
|---|
| classId | string | non |
|---|
| status | "ENROLLED" | "WAITLISTED" | "CANCELLED" | "CART" | non |
|---|
| enrolledAt | string | non |
|---|
| paymentId | string | oui |
|---|
| ageOverride | boolean | non |
|---|
| prereqOverride | boolean | non |
|---|
| offeredAt | string | oui |
|---|
| offerExpiresAt | string | oui |
|---|
| updatedAt | string | non |
|---|
/api/v1/presences
Demande la portée « presences:lecture ».
/api/v1/presences| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| enrollmentId | string | non |
|---|
| date | string | non |
|---|
| status | "PRESENT" | "ABSENT" | "LATE" | "EXCUSED" | non |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/paiements
Demande la portée « paiements:lecture ».
/api/v1/paiements| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| familyId | string | non |
|---|
| invoiceNumber | string | oui |
|---|
| description | string | oui |
|---|
| amount | string | non |
|---|
| status | "PENDING" | "PAID" | "REFUNDED" | "FAILED" | non |
|---|
| method | "CASH" | "INTERAC" | "CARD" | "CHEQUE" | "OTHER" | "CHEQUE_VACANCES" | "COUPON_SPORT" | "PASS_SPORT" | "PASS_CULTURE" | "CREDIT" | "BANK" | oui |
|---|
| dueDate | string | oui |
|---|
| paidAt | string | oui |
|---|
| processingSince | string | oui |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/evenements
Demande la portée « evenements:lecture » ET la capacité « EVENEMENTS » en plus de l'API publique.
/api/v1/evenements| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| sessionId | string | non |
|---|
| roomId | string | oui |
|---|
| name | string | non |
|---|
| description | string | oui |
|---|
| startDate | string | non |
|---|
| endDate | string | non |
|---|
| jours | string[] | non |
|---|
| dailyStartTime | string | oui |
|---|
| dailyEndTime | string | oui |
|---|
| minAge | number | oui |
|---|
| maxAge | number | oui |
|---|
| capacity | number | non |
|---|
| price | string | non |
|---|
| typesBillets | object[] | non |
|---|
| priceIncludesTax | boolean | non |
|---|
| registrationOpen | boolean | non |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/camps
Demande la portée « camps:lecture » ET la capacité « CAMPS » en plus de l'API publique.
/api/v1/camps| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| sessionId | string | non |
|---|
| roomId | string | oui |
|---|
| name | string | non |
|---|
| description | string | oui |
|---|
| startDate | string | non |
|---|
| endDate | string | non |
|---|
| dailyStartTime | string | oui |
|---|
| dailyEndTime | string | oui |
|---|
| minAge | number | oui |
|---|
| maxAge | number | oui |
|---|
| capacity | number | non |
|---|
| price | string | non |
|---|
| taxExempt | boolean | non |
|---|
| registrationOpen | boolean | non |
|---|
| createdAt | string | non |
|---|
| updatedAt | string | non |
|---|
/api/v1/representations
Demande la portée « representations:lecture » ET la capacité « BILLETTERIE » en plus de l'API publique.
/api/v1/representations| Champ | Type | Nul possible |
|---|
| id | string | non |
|---|
| showId | string | non |
|---|
| date | string | non |
|---|
| venue | string | oui |
|---|
| venueRoomId | string | oui |
|---|
| venueMapId | string | oui |
|---|
| ticketPrice | string | oui |
|---|
| ticketsOnSale | boolean | non |
|---|
| ticketsOnSaleAt | string | oui |
|---|
| earlyTicketsOnSaleAt | string | oui |
|---|
| maxTicketsPerFamily | number | oui |
|---|
| updatedAt | string | non |
|---|
Écrire
Chaque écriture demande la portée « <ressource>:ecriture » (par exemple « inscriptions:ecriture »), et l'enregistrement d'un paiement sa propre portée « paiements:ecriture », à cocher séparément. Chacune passe par la même règle que l'écran correspondant du tableau de bord : une inscription refusée à l'écran est refusée ici, et le code d'erreur nomme la règle qui a refusé. Les champs listés sont les seuls acceptés ; un champ inconnu, ou un champ que l'API ne lit pas, fait 400.
L'en-tête « Idempotency-Key » est obligatoire : une valeur à vous, unique par écriture. Réessayer avec la même clé rend la réponse d'origine pendant 24 heures, avec l'en-tête « Idempotent-Replayed: true » — c'est ce qui vous laisse réessayer sans risquer une deuxième inscription. La même clé sur un corps différent fait 409 ; une écriture refusée, elle, libère la clé, pour que vous puissiez corriger votre envoi et réessayer avec la même.
Une création, et la même relancée :
curl -X POST -H "Authorization: Bearer cad_..." \
-H "Idempotency-Key: 8f1c-..." \
-H "Content-Type: application/json" \
-d '{"lastName":"…","contactEmail":"…"}' \
https://cadanse.app/api/v1/familles
POST /api/v1/familles
Demande la portée « familles:ecriture » et l'en-tête « Idempotency-Key ». La famille est créée sans élève : un élève se crée par sa propre écriture. La réponse porte la ligne au même format qu'en lecture.
POST /api/v1/familles| Champ | Type | Requis |
|---|
| lastName | string | oui |
|---|
| contactEmail | string | oui |
|---|
| contactFirstName | string | non |
|---|
| contactPhone | string | non |
|---|
| address | string | non |
|---|
| parent2FirstName | string | non |
|---|
| parent2LastName | string | non |
|---|
| parent2Email | object | non |
|---|
| parent2Phone | string | non |
|---|
POST /api/v1/eleves
Demande la portée « eleves:ecriture » et l'en-tête « Idempotency-Key ». L'élève est rattaché à une famille existante. Ni note médicale ni note interne : aucune des deux ne se lit par l'API, et ce qui ne se lit pas ne s'écrit pas.
POST /api/v1/eleves| Champ | Type | Requis |
|---|
| familyId | string | oui |
|---|
| firstName | string | oui |
|---|
| lastName | string | oui |
|---|
| birthDate | string | non |
|---|
| isAdult | boolean | non |
|---|
| competitive | boolean | non |
|---|
POST /api/v1/inscriptions
Demande la portée « inscriptions:ecriture » et l'en-tête « Idempotency-Key ». Passe par la même fonction de domaine que le tableau de bord : capacité, conflits d'horaire, limites par participant et inscriptibilité de la session peuvent la refuser, et l'erreur nomme alors la règle. Un cours complet met l'élève en LISTE D'ATTENTE — c'est un succès, et le champ « status » de la réponse le dit. La facture de la session est émise comme elle le serait au tableau de bord.
POST /api/v1/inscriptions| Champ | Type | Requis |
|---|
| studentId | string | oui |
|---|
| classId | string | oui |
|---|
POST /api/v1/presences
Demande la portée « presences:ecriture » et l'en-tête « Idempotency-Key ». Marque une séance d'une inscription, aux mêmes conditions que la feuille du tableau de bord : jamais d'avance, jamais un jour de fermeture, jamais une séance annulée ou déplacée. Un statut « EXCUSED » émet un crédit de reprise quand le studio en accorde ; une transition vers « ABSENT » prévient la famille et émet l'événement « absence.signalee ». Remarquer la même séance met la marque à jour sans rien réémettre.
POST /api/v1/presences| Champ | Type | Requis |
|---|
| enrollmentId | string | oui |
|---|
| date | string | oui |
|---|
| status | "PRESENT" | "ABSENT" | "LATE" | "EXCUSED" | oui |
|---|
POST /api/v1/paiements
Demande la portée « paiements:ecriture » et l'en-tête « Idempotency-Key ». Le montant envoyé EST le total, taxes comprises : c'est la saisie de comptoir, pas un encaissement par processeur. La facture reçoit son numéro et son empreinte fiscale, et la famille en est avertie au portail — relance courriel comprise si elle reste due.
POST /api/v1/paiements| Champ | Type | Requis |
|---|
| familyId | string | oui |
|---|
| amount | number | oui |
|---|
| method | "CASH" | "INTERAC" | "CARD" | "CHEQUE" | "OTHER" | "CHEQUE_VACANCES" | "COUPON_SPORT" | "PASS_SPORT" | "PASS_CULTURE" | non |
|---|
| description | string | non |
|---|
| status | "PENDING" | "PAID" | non |
|---|
| dueDate | string | non |
|---|
Erreurs
Toute erreur rend la même forme : « error.code » et « error.message ». Le code est contractuel, le message peut être reformulé.
| Code | Statut | Quand |
|---|
| MISSING_KEY | 401 | Aucun en-tête « Authorization: Bearer … » n'accompagne la requête. |
|---|
| INVALID_KEY | 401 | La clé est inconnue ou révoquée. Les deux cas rendent le même message. |
|---|
| STUDIO_SUSPENDED | 403 | Le compte du studio est suspendu. |
|---|
| STUDIO_ONBOARDING | 403 | La configuration initiale du studio n'est pas terminée. |
|---|
| PLAN_REQUIRED | 403 | Le palier du studio n'inclut pas l'API publique, ou pas la capacité que demande la collection visée. |
|---|
| QUOTA_UNAVAILABLE | 503 | Le compteur de quota est momentanément injoignable ; la requête est refusée plutôt que laissée passer. Réessayez après le délai de « Retry-After ». |
|---|
| RATE_LIMITED | 429 | Quota par minute ou quotidien dépassé. L'en-tête « Retry-After » donne le délai en secondes. |
|---|
| SCOPE_REQUIRED | 403 | La clé est valide mais ne porte pas la portée qu'exige la route. |
|---|
| INVALID_PARAMETER | 400 | Un paramètre de requête est mal formé — « limite » non entière ou nulle, « modifieDepuis » qui n'est pas une date ISO 8601. |
|---|
| IDEMPOTENCY_KEY_REQUIRED | 400 | L'en-tête « Idempotency-Key » manque, est vide, ou dépasse 255 caractères. Il est obligatoire sur toute écriture : un connecteur qui réessaie est le cas normal, pas l'exception. |
|---|
| IDEMPOTENCY_KEY_REUSED | 409 | Cette clé a déjà servi, pour une requête DIFFÉRENTE. Rendre la réponse d'origine ferait croire à l'appelant qu'il vient de créer ce que décrit une réponse qui parle d'autre chose. Une clé vaut pour une écriture et une seule. |
|---|
| IDEMPOTENCY_IN_PROGRESS | 409 | Une écriture portant cette clé court encore. Réessayez après le délai de « Retry-After » : la réponse d'origine sera alors rendue. |
|---|
| INVALID_BODY | 400 | Le corps n'est pas du JSON valide, ou un champ ne satisfait pas le schéma de l'écriture. Le message nomme le champ fautif. Le refus ne consomme PAS la clé d'idempotence : corrigez et réessayez avec la même. |
|---|
| PAYLOAD_TOO_LARGE | 413 | Le corps de la requête dépasse la taille permise ; il est refusé avant tout décodage. Réduisez-le (par lots plus petits) avant de réessayer. |
|---|
| FAMILY_NOT_FOUND | 404 | Le « familyId » visé n'existe pas dans ce studio. |
|---|
| STUDENT_NOT_FOUND | 404 | Le « studentId » visé n'existe pas dans ce studio. |
|---|
| CLASS_NOT_FOUND | 404 | Le « classId » visé n'existe pas dans ce studio. |
|---|
| ENROLLMENT_NOT_FOUND | 404 | L'« enrollmentId » visé n'existe pas dans ce studio. |
|---|
| ALREADY_ENROLLED | 409 | Cet élève est déjà inscrit à ce cours. Réinscrire ne crée pas de seconde ligne — le refus est ce qui empêche une double facturation. |
|---|
| SESSION_NOT_ENROLLABLE | 409 | La session du cours n'accepte pas d'inscription : inactive, terminée, ou dont la période est passée. |
|---|
| SCHEDULE_CONFLICT | 409 | L'élève a déjà un cours qui chevauche celui-ci. Seul le studio peut assumer un conflit d'horaire, depuis son tableau de bord : l'API ne porte pas cette dérogation. |
|---|
| PARTICIPANT_LIMIT | 409 | L'inscription dépasse une limite fixée par le studio — nombre de cours par élève, ou un seul cours par discipline. |
|---|
| ATTENDANCE_DATE_IN_FUTURE | 409 | La date de la présence est encore à venir. Une présence ne se prend pas d'avance : elle nourrit le décompte de séances tenues et l'avis d'absence à la famille. |
|---|
| STUDIO_CLOSED | 409 | Le studio est fermé ce jour-là : aucune séance n'y a lieu. |
|---|
| SESSION_NOT_HELD | 409 | La séance de ce cours a été annulée ou déplacée : elle n'a pas eu lieu à la date demandée. Le message dit lequel des deux. |
|---|
| METHOD_NOT_OFFERED | 422 | Le moyen de paiement n'existe pas dans le pays du studio : `INTERAC` est propre au Canada, et `BANK` (compte bancaire débité) au Canada (débit préautorisé), aux États-Unis (ACH) et en France (SEPA) ; les Chèques-Vacances, coupons sport, Pass'Sport et Pass Culture sont propres à la France. |
|---|
| INTERNAL_ERROR | 500 | Erreur interne. Le détail est consigné côté Cadanse, jamais rendu à l'appelant. |
|---|
Webhooks sortants
L'API se lit et s'écrit à votre initiative ; les webhooks, eux, viennent à vous. Une destination se branche au tableau de bord, dans Configuration : une adresse HTTPS, les événements souscrits, et un secret de signature montré une fois. Cadanse y envoie un POST « application/json » à chaque événement.
Vérifier la signature
Chaque envoi porte l'en-tête « Cadanse-Signature », de la forme « t=<millisecondes>,v1=<hex> » : « v1 » est le HMAC-SHA256 du texte « <t>.<corps brut> », avec votre secret comme clé. Vérifiez le corps BRUT, avant toute désérialisation. Vérifiez la signature d'ABORD et l'horodatage ensuite : refuser sur l'âge avant d'avoir prouvé l'authenticité apprend à qui vous écrit quelle heure vous acceptez. Au-delà de 5 minutes, refusez — c'est ce qui empêche de rejouer chez vous un corps capté une fois. L'en-tête « Cadanse-Event » nomme l'événement, pour router sans lire le corps.
Cadanse-Signature: t=1776171600000,v1=<hex>
Cadanse-Event: inscription.creee
L'enveloppe
Toujours la même forme : « id », « type », « createdAt », « studioId » et « data ». « id » est celui de la LIVRAISON, pas de l'objet : les reprises d'un même envoi le répètent — c'est ce qui vous permet de dédoublonner — et un rejeu demandé à la main en porte un nouveau. « createdAt » est l'instant de l'événement ; aucune charge ne porte un second horodatage. Les champs de « data » sont des identifiants : les fiches complètes se lisent aux collections ci-dessus.
Reprises
Une réponse 2xx conclut la livraison. Sinon, 3 reprises, à 1 h, 6 h, 24 h, puis plus rien : un événement livré trois jours trop tard n'informe plus personne. La fenêtre totale est de 48 h. Répondez vite — un appel est abandonné au-delà de 2 secondes — et faites votre travail après avoir répondu. Le tableau de bord montre chaque livraison, son code de réponse et le message d'erreur de votre serveur ; une livraison épuisée s'y rejoue à la main.
Les événements
Souscrire un événement qui n'envoie encore rien est permis, et la colonne de droite le dit : c'est l'état réel, lu dans le code qui émet.
Les événements| Événement | Champs de « data » | État |
|---|
| inscription.creee | inscriptionId, eleveId, coursId, familleId, statut, paiementId | envoyé |
|---|
| paiement.recu | paiementId, familleId, montant, moyen, numeroFacture, payeLe | envoyé |
|---|
| absence.signalee | inscriptionId, eleveId, coursId, date, statut | envoyé |
|---|
| famille.creee | familleId, nom, courriel | envoyé |
|---|
| billet.vendu | commandeId, representationId, familleId, quantite, surLesGenoux, paiementId, venduLe | envoyé |
|---|
Connecteurs
Zapier, Make et les assistants qui parlent MCP se branchent sur tout ce qui précède, et sur rien d'autre : la même clé, les mêmes portées, le même quota, le même journal. Un connecteur n'ouvre pas une porte de plus — il emprunte une porte que vous avez déjà ouverte, et la clé se révoque au tableau de bord.
Zapier et Make
Rien à installer : créez une connexion « API par clé » avec l'en-tête « Authorization » et, pour valeur, « Bearer » suivi de votre clé. Testez-la sur https://cadanse.app/api/v1/moi — cette route répond quelles que soient les portées de la clé et vous rend le nom du studio et la liste de ce qu'elle permet.
Vos déclencheurs sont les webhooks ci-dessus. Zapier comme Make vous donnent une URL d'écoute : collez-la au tableau de bord et cochez les événements voulus. Ni l'un ni l'autre ne vérifie la signature pour vous — faites-la vérifier par une étape de code avant d'agir sur une charge, avec la recette donnée plus haut.
Vos actions sont les écritures ci-dessus, appelées par une étape « requête HTTP ». Renseignez toujours « Idempotency-Key » : un scénario que la plateforme rejoue après une panne recréerait sinon la même fiche deux fois.
Serveur MCP
Un assistant qui parle MCP se branche sur https://cadanse.app/api/v1/mcp — transport HTTP, requêtes POST, même en-tête « Authorization ». C'est votre studio qui décide : brancher un assistant fait sortir des données vers un outil que vous choisissez, sous une clé que vous créez et que vous pouvez révoquer.
{
"mcpServers": {
"cadanse": {
"type": "http",
"url": "https://cadanse.app/api/v1/mcp",
"headers": {
"Authorization": "Bearer cad_..."
}
}
}
}
Le serveur expose 9 outils de lecture et 5 outils d'écriture — exactement les collections et les écritures documentées ci-dessus, aucune autre. Le nom d'un outil est celui de son opération, en minuscules soulignées :
lister_familles, lister_eleves, lister_cours, lister_inscriptions, lister_presences, lister_paiements, lister_evenements, lister_camps, lister_representations, creer_famille, creer_eleve, creer_inscription, marquer_presence, creer_paiement
Le catalogue dépend de la clé : « tools/list » ne rend que les outils couverts par ses portées. Un outil hors portée n'existe pas pour cette clé — l'appeler répond « outil inconnu », ce qui évite d'apprendre à un curieux quelles portées existent.
Les lots JSON-RPC sont refusés : un appel est une requête, et une requête est une unité de quota. Les lectures faites par MCP sont consignées comme les autres — une fenêtre par clé, par collection et par jour — au même journal que le studio peut relire.
Les outils d'écriture agissent immédiatement, et ce qu'ils écrivent est visible du personnel et des familles. Chacun accepte un argument « cleIdempotence » facultatif : sans lui, deux appels identiques font deux écritures — c'est voulu, deux paiements comptant du même montant le même samedi sont deux paiements. Le journal d'audit garde la trace de chaque écriture, qu'elle vienne d'un assistant ou d'un appel HTTP.
Pourquoi cette page ne peut pas mentir
Elle est rendue depuis le même document que openapi.json, lui-même engendré depuis les sérialiseurs qui écrivent les réponses. Un champ retiré du code disparaît d'ici sans que personne y pense ; un champ documenté qui ne serait pas servi est impossible à écrire.