ReCoDanse · version 1.0.0 du contrat
ReCoDanse pour les développeurs
API ReCoDanse pour les applications tierces — branche ton site, le logiciel de ton studio ou ton assistant sur ReCoDanse, sans jamais toucher aux vidéos ni aux données d'une autre personne.
Ce que tu peux construire
Démarrer
- Ouvre un compte sur https://recodanse.fr et confirme ton adresse e-mail.
- Déclare ton application. Choisis son espèce :
connexion(un site ou une app qui authentifie les ReCoDanseurs·euses) ouservice(un logiciel sans humain derrière, qui publie pour toi). - Garde le
client_secret: il ne se montre qu'une fois. - Pose un webhook
https://abonné àautorisation.retireeet àcompte.efface, qui vérifie la signature : c'est par lui que tu apprends qu'il faut effacer, et la revue l'éprouve (voir « Essai et revue »). - Pour l'ouvrir aux autres, soumets-la à la revue (
POST /v0/tiers/applications/{id}/revue) en acceptant la version2026-10-30des conditions des développeurs (accepte_les_conditions).
Tu déclares ton application dans l'app, à https://recodanse.fr/developpeur (« Mes applications »), ou en code, avec un jeton de développeur. Le même appel, depuis la console de ton navigateur connecté à https://recodanse.fr :
await fetch('/v0/tiers/applications', {
method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nom: 'Billetterie de Nadia', categorie: 'service',
portees: ['evenements.publier'], site_web: 'https://nadia.example'
})
}).then(r => r.json())
Pour une application connexion, ajoute redirections (des adresses https://, une boucle locale http://127.0.0.1:…, ou un schéma d'app native) et, pour une app native ou une page web sans serveur, publique: true (pas de secret, PKCE obligatoire).
Les jetons
La porte d'autorisation est https://connexion.recodanse.fr (OAuth 2.0 / OpenID Connect, découverte standard). L'API est https://api.recodanse.fr ; chaque appel porte Authorization: Bearer <jeton>.
Une personne se connecte (code d'autorisation + PKCE)
GET https://connexion.recodanse.fr/oauth2/auth?response_type=code
&client_id=<client_id>&redirect_uri=<ta redirection>
&scope=openid%20profile&state=<aléa>
&code_challenge=<S256(verifier)>&code_challenge_method=S256
POST https://connexion.recodanse.fr/oauth2/token
grant_type=authorization_code&code=…&redirect_uri=…&code_verifier=…
La personne voit une page de ReCoDanse qui nomme ton application et dit, en phrases, ce qu'elle t'accorde ; elle peut décocher. Le sub que tu reçois est un pseudonyme stable et propre à ton application.
Ton logiciel agit pour toi (compte de service)
curl -u "$CLIENT_ID:$CLIENT_SECRET" \ -d grant_type=client_credentials -d scope=evenements.publier \ https://connexion.recodanse.fr/oauth2/token
curl -X PUT https://api.recodanse.fr/v1/evenements/soiree-2026-11-07 \
-H "Authorization: Bearer $JETON" -H 'Content-Type: application/json' \
-d '{"espece":"social","titre":"Social bachata","danses":["bachata"],
"debut":"2026-11-07T20:00:00+01:00","fin":"2026-11-08T01:00:00+01:00",
"lieu":{"nom":"La Halle","ville":"Lyon","latitude":45.7769,"longitude":4.8273},
"prix_indicatif":"12 €","lien_billetterie":"https://www.helloasso.com/…"}'
La référence (soiree-2026-11-07) est ta clé : republier la même référence corrige l'événement au lieu de le dupliquer.
Publier un agenda
Tu tiens un agenda régional de soirées, et des organisateurs te proposent les leurs ? Ton agenda devient une source parmi d'autres de ReCoDanse : chaque soirée y paraît sous ton nom, à côté de celles des autres agendas. Ce qui compte :
- Une référence stable par soirée — l'
UIDde ton iCal, l'identifiant de ta base. Republier la même référence corrige ; en changer duplique. - Ne pousse que ce qui change. Garde une empreinte de ce que tu as envoyé ; une soirée identique n'a pas besoin d'un second
PUT. Les 30 prochains jours suffisent : le passé ne se publie pas. - Une soirée annulée s'annule, elle ne se retire pas :
"annule": truegarde la fiche et dit « annulée » aux personnes qui comptaient venir.DELETEest pour une fiche qui n'aurait jamais dû exister — et sa référence ne se republie plus. - Une soirée qui disparaît de ta liste n'est pas forcément annulée : ne l'annonce pas annulée sur une absence.
- Savoir qui propose. Branche « Se connecter avec ReCoDanse » sur ton formulaire de proposition : tu sais qui propose, sans recréer de vérification.
Pas encore là, et dit tel quel : ReCoDanse ne lit pas encore un flux iCal ou JSON que tu déclarerais (pour l'instant, tu pousses) ; une soirée ne peut pas encore nommer la personne qui l'a proposée ; et l'application ne lit pas encore si un compte est vérifié. Tout le reste de cette page marche aujourd'hui.
Les portées
| Portée | Ce que la personne lit | Pour toi | Webhook d'effacement |
|---|---|---|---|
openid | Te connecter avec ton compte ReCoDanse (un identifiant propre à cette application, sans ton nom) | Identifiant OpenID Connect : `sub` est un pseudonyme STABLE et PROPRE à l'application. | — |
profile | Ton prénom public (« Léa D. ») et ton @nom, si tu en as un | Revendications `name` (prénom et initiale publics) et `preferred_username` (le @nom, sans arobase). | exigé |
email | Ton adresse e-mail | Revendications `email` et `email_verified` (vrai seulement si ReCoDanse a vérifié l'adresse). | exigé |
offline_access | Garder cet accès quand tu n'es pas là, jusqu'à ce que tu le retires | Délivre un jeton de rafraîchissement ; retiré dès que la personne retire l'application. | exigé |
videos.lire | Voir la liste de tes vidéos et ce que tu en as noté (danse, prof, lieu, étiquettes) — jamais les films eux-mêmes | Lecture des MÉTADONNÉES des vidéos du compte (galerie, qualification, carnets). Aucun octet vidéo, aucune adresse de lecture. | exigé |
videos.ranger | Ranger tes vidéos : noter le prof, le lieu, l'événement, le niveau et les étiquettes | Écriture de la qualification des vidéos du compte (carnets de profs, de lieux, d'événements ; étiquettes). Ne supprime rien, ne partage rien, ne rattache à aucun cours. | — |
videos.deposer | Déposer dans ta bibliothèque les vidéos que tu lui confies — jamais en lire, en effacer ni en partager | Dépôt de fichiers vidéo dans la bibliothèque du compte, par la même porte que l'app : fiche, dépôt signé (en parts au-delà de 8 Mio), confirmation. Mêmes bornes, même quota, même revue ; aucune adresse de lecture ne revient. | — |
videos.annoter | Poser des passages et marquer les explications sur tes vidéos — jamais en effacer | Fusion du travail d'une vidéo du compte (séquences, explications, passages nommés) : additive, rien ne s'efface. | — |
programmes.poser | Ajouter des programmes à tes entraînements — jamais changer les tiens | Pose d'un programme au carnet du compte, relu comme celui de l'app, marqué « posé par » l'application ; elle ne remplace que le sien, tant qu'aucun jour n'est fini. | — |
evenements.proposer | Proposer à l'agenda, en ton nom, les événements que tu ajoutes — relus par ReCoDanse avant d'être publiés | Jeton délégué : proposer un événement (`PUT /v1/evenements/propositions/{reference}`), au nom de la personne qui l'a autorisé. Toujours au statut `a_verifier` : un humain le relit avant qu'il paraisse. Plafond par jour selon la confiance du compte ; adresse confirmée exigée. | — |
evenements.publier | Publier les événements de ton organisation | Compte de service : publier, corriger et retirer les événements de SON propriétaire. | — |
creneaux.publier | Publier les créneaux et les tarifs de ton studio | Compte de service : publier, corriger et retirer les créneaux de SON propriétaire. | — |
Une application connexion peut demander openid, profile, email, offline_access, videos.lire, videos.ranger, videos.deposer, videos.annoter, programmes.poser, evenements.proposer ; un compte de service : evenements.publier, creneaux.publier. Une portée ne suffit jamais : ReCoDanse vérifie aussi, à chaque appel, que ton application est déclarée, qu'elle n'est pas suspendue, et que la personne ne t'a pas retiré son accord.
Sans webhook d'effacement, des portées limitées. Une app de téléphone ou une page sans serveur n'a pas d'adresse où apprendre qu'un compte s'est effacé : elle ne demande alors que openid et des écritures vers ReCoDanse (ce qui est écrit chez nous s'efface avec le compte). Une portée marquée « exigé » donne quelque chose que tu garderais chez toi : la revue la refuse en 409 portee_sans_webhook_d_effacement tant qu'aucun webhook d'effacement n'est déclaré, et le message nomme les portées à retirer.
Les mots
Nos clés sont en français. Voici ce qu'elles veulent dire en anglais, le terme Schema.org qui y répond, et ce que disent les billetteries et les logiciels de studio que tu connais peut-être.
Pour un programme, ou un LLM, la même table en contexte JSON-LD : appliqué à nos objets, il les fait lire comme des objets Schema.org. Une clé sans équivalent direct n'y est pas.
| Chez nous | En anglais | Schema.org | Chez les voisins |
|---|---|---|---|
evenement | event | DanceEvent | event (Billetweb, Eventbrite, Weezevent) |
espece | event type | @type (+ rc:espece) | category |
titre | title | name | name |
debut | start | startDate | start / date_start |
fin | end | endDate | end / date_end |
lieu | venue | location → Place · SportsActivityLocation | venue |
danses | dance styles | about → DefinedTerm | tags |
prix_indicatif | indicative price | offers.description | price |
lien_billetterie | ticket link | offers.url | ticket url |
annule | cancelled | eventStatus = EventCancelled | status: canceled |
creneau | class slot | CourseInstance + Offer | session / class (bsport, Mindbody) |
capacite | capacity | maximumAttendeeCapacity | capacity |
niveau | level | rc:niveauVise | level |
tranche | price tier | UnitPriceSpecification | ticket class / tarif |
video | video | VideoObject | — |
duree_s | duration (seconds) | duration | — |
application | app | SoftwareApplication | app |
portees | scopes | — | scopes |
webhook | webhook | — | webhook / notification |
espace | course | Course | — |
CoDanse | social dance event | DanceEvent + rc:CoDanse | — |
inscrit | attendee | EventReservation | attendee / participant |
Essai et revue
Une application naît en développement : seul ton compte peut l'autoriser, et ce qu'elle publie reste un essai que ton compte seul voit (essai: true). Quand elle est prête, soumets-la à la revue (POST /v0/tiers/applications/{id}/revue) : ReCoDanse la publie, et elle s'ouvre à tous les ReCoDanseurs·euses. Une application suspendue s'arrête à la requête suivante.
L'épreuve du webhook d'effacement. Une application connexion qui demande une portée marquée « exigé » ne se soumet, et ne se publie, que si l'un de ses webhooks actifs, abonné à autorisation.retiree et à compte.efface, passe une épreuve jouée à l'instant : un essai signé doit recevoir une réponse 2xx, et le même essai mal signé une réponse 4xx. Sinon, la revue refuse en 409 (portee_sans_webhook_d_effacement s'il n'y en a aucun, webhook_d_effacement_injoignable, webhook_d_effacement_sans_verification) et le message dit le statut reçu ; webhook_d_effacement_retenu dit que le débit des envois a retenu l'essai, et dans combien de secondes réessayer.
Créneaux : publication suspendue. ReCoDanse range, valide et te rend tes créneaux, mais ne les montre à personne d'autre tant qu'un avis juridique (directive européenne DAC7) n'est pas rendu. Chaque réponse le dit : publie: false, raison: publication_suspendue_dac7.
Le bac à sable
Pas encore ouvert. Le bac à sable est prêt dans le code, mais ses adresses ne répondent pas encore. En attendant, une application en développement s'essaie avec ton propre compte (lui seul peut l'autoriser), une adresse de retour en boucle locale (http://127.0.0.1:…), et un tunnel https vers ton poste pour tes webhooks (au bac à sable, http:// suffira).
Quand il ouvrira, pour essayer ton application de bout en bout sans toucher une vraie personne : https://bac-a-sable.recodanse.fr (émetteur https://connexion.bac-a-sable.recodanse.fr). Tu y déclares ton application avec ton compte, puis la page « Autoriser une application » te propose de continuer en tant que l'un des comptes fictifs — leurs vidéos, leurs carnets, leurs cours sont là pour ça. Une application en développement s'y essaie sans revue.
Pour tester tes webhooks, déclenche un événement pour un compte fictif qui a autorisé ton application : POST /v0/tiers/bac-a-sable/evenements {"application", "evenement": "autorisation.retiree" | "compte.efface", "danseuse"}. L'envoi part signé comme en production ; l'accord est retiré, le compte fictif reste.
Tout s'efface à chaque redémarrage du bac à sable, et chaque semaine : ton compte, tes applications et tes webhooks compris. Un jeton du bac à sable ne vaut rien en production ; en production, ton application se déclare à nouveau, et passe la revue. Les quotas et les erreurs sont les mêmes qu'en production.
Webhooks
Donne une adresse https:// (port 443, un hôte public ; au bac à sable, http:// port 80 aussi — un tunnel ngrok, cloudflared ou localtunnel vers ton poste en est un) et choisis tes événements ; ReCoDanse y envoie un POST signé selon Standard Webhooks (en-têtes webhook-id, webhook-timestamp, webhook-signature). Huit tentatives sur environ 37 heures ; un 410 désactive le webhook. Au plus 60 envois par minute vers une même destination (toutes applications confondues) et 120 par minute d'une même application : au-delà, l'envoi est retenu et repart la minute suivante, sans compter de tentative.
autorisation.retiree— Une personne a retiré l'accès de ton application — `data.sujet` est le `sub` qu'elle avait chez toicompte.efface— Un compte qui t'avait autorisé s'est effacé — efface ce que tu gardes de `data.sujet`publication.retiree— La modération a retiré un de tes événements — `data.espece`, `data.reference`, `data.id`
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.SECRET_RECODANSE); // whsec_…
const evenement = wh.verify(corpsBrut, entetes); // lève une erreur si la signature est fausse
La charge ne porte jamais un nom, un e-mail ou un identifiant de compte : une personne y est son sujet, le même sub que dans tes jetons.
Assistants (MCP)
Le serveur MCP est https://api.recodanse.fr/mcp (Streamable HTTP). Un assistant compatible le découvre seul : sans jeton, la réponse 401 nomme https://api.recodanse.fr/.well-known/oauth-protected-resource, qui nomme la porte d'autorisation, qui annonce l'enregistrement (POST /v1/enregistrement, RFC 7591). La personne voit la page de consentement de ReCoDanse — l'assistant y est dit « non vérifié » tant que ReCoDanse ne l'a pas revu.
Outils : chercher_videos, lire_video, mes_carnets, regrouper_videos (lecture) et ranger_video (écriture, portée videos.ranger). Aucun ne rend un film, une vignette ou une adresse de lecture ; aucun ne supprime, ne partage ni ne publie.
Ce que l'API ne fait jamais
- servir un octet vidéo, une vignette, une adresse exacte de domicile, ou une donnée d'un autre compte ;
- laisser sortir l'identifiant interne d'un compte ;
- encaisser ou lire un paiement : un tarif est affiché, le règlement est un lien sortant.
En te servant de l'API, tu t'engages à ne pas reconstituer de données personnelles, à ne pas revendre ce que tu lis, et à effacer ce que tu gardes d'une personne quand elle retire ton application ou efface son compte. Un abus vaut suspension. C'est le résumé des conditions des développeurs, version 2026-10-30.
Référence
Générée du contrat OpenAPI — de quoi générer ton client. Aussi en texte, pour un assistant : llms.txt.
GET /.well-known/oauth-protected-resource
Métadonnées de la ressource (RFC 9728) — le point d'entrée de la découverte MCP
| Statut | Signification |
|---|---|
200 | la ressource et sa porte d'autorisation |
GET /.well-known/oauth-protected-resource/mcp
Les mêmes métadonnées, sous la forme « par chemin » (RFC 9728 §3.1)
| Statut | Signification |
|---|---|
200 | la ressource et sa porte d'autorisation |
POST /mcp
Le serveur MCP des vidéos (Streamable HTTP, sans état) — un message JSON-RPC 2.0 par requête
Pour un assistant qui aide une personne qui danse à retrouver et ranger SES vidéos. Révisions du protocole : 2025-06-18, 2025-03-26. Méthodes : `initialize`, `ping`, `tools/list`, `tools/call` ; une notification (sans `id`) rend 202. Outils : `chercher_videos`, `lire_video`, `mes_carnets`, `regrouper_videos` (portée `videos.lire`) et `ranger_video` (portée `videos.ranger`). Le jeton entre avec L'UNE de ces deux portées ; chaque outil exige la sienne, et `tools/list` ne montre que ceux que le jeton peut appeler. Sans `videos.lire`, `ranger_video` rend un accusé `{ "fait": true }`, jamais la fiche relue. Aucun outil ne rend un octet vidéo, une vignette ou une adresse de lecture ; aucun ne supprime, ne partage ni ne publie. `GET /mcp` rend 405 (pas de flux SSE). Découverte : sans jeton, 401 et `WWW-Authenticate: Bearer resource_metadata=…`.
Portée : videos.lire videos.ranger
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | la réponse JSON-RPC (`result` ou `error`) ; une erreur d'OUTIL est un `result` avec `isError: true` |
202 | notification reçue |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
GET /v1/applications
Tes applications, la plus récente d'abord
| Statut | Signification |
|---|---|
200 | tes applications, le plafond et la version des conditions des développeurs en vigueur |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/applications
Déclarer une application — elle naît EN DÉVELOPPEMENT ; le `client_secret` se montre UNE fois
Corps : DeclarationApplication
| Statut | Signification |
|---|---|
201 | l'application, et son secret (une fois) |
400 | `nom_invalide`, `categorie_invalide`, `portee_inconnue`, `portee_interdite`, `redirection_invalide`, `redirections_vides`, `redirections_inutiles`, `service_sans_secret`, `conditions_perimees` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
409 | dix applications au plus (`trop_d_applications`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
GET /v1/applications/{id}
Une de tes applications
| Paramètre | Où | Description |
|---|---|---|
id | path |
| Statut | Signification |
|---|---|
200 | l'application |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte (le même 404) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
PATCH /v1/applications/{id}
Corriger nom, description, site, portées, adresses de retour
| Paramètre | Où | Description |
|---|---|---|
id | path |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | l'application corrigée |
400 | mêmes codes que la déclaration |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
409 | une application publiée n'élargit pas ses portées sans revue (`portees_figees`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
DELETE /v1/applications/{id}
Retirer une application — ses jetons cessent de valoir à l'instant
| Paramètre | Où | Description |
|---|---|---|
id | path |
| Statut | Signification |
|---|---|
204 | retirée |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/applications/{id}/revue
Soumettre à la revue (developpement → en_revue) ; le fondateur relit chaque application
| Paramètre | Où | Description |
|---|---|---|
id | path |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | l'application, en revue |
400 | `conditions_perimees` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
409 | `transition_impossible` ou `conditions_a_accepter` ; pour une application `connexion` qui demande une portée gardée par l'effacement (`profile`, `email`, `offline_access`, `videos.lire` ; fiche 52 RG-117), `portee_sans_webhook_d_effacement` si elle n'a aucun webhook d'effacement (le message nomme les portées à retirer), puis l'épreuve du webhook (RG-94) : `webhook_d_effacement_injoignable` (l'essai signé n'a pas reçu de 2xx) ou `webhook_d_effacement_sans_verification` (le même essai mal signé n'a pas reçu de 4xx) — le message dit le statut reçu ; `webhook_d_effacement_retenu` : le débit des envois (60 par minute vers une même destination, 120 par minute d'une même application) a retenu l'essai, rien n'est parti, le message dit dans combien de secondes réessayer |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/applications/{id}/secret
Changer le secret (rotation) — l'ancien cesse de valoir à l'instant ; le nouveau se montre une fois
| Paramètre | Où | Description |
|---|---|---|
id | path |
| Statut | Signification |
|---|---|
200 | le nouveau secret |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
409 | un client public n'a pas de secret (`client_public`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
GET /v1/applications/{id}/webhooks
Les webhooks d'une de tes applications (sans secret), le catalogue des événements, le plafond
| Paramètre | Où | Description |
|---|---|---|
id | path |
| Statut | Signification |
|---|---|
200 | les webhooks |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/applications/{id}/webhooks
Poser un webhook — le secret `whsec_…` se montre UNE fois
| Paramètre | Où | Description |
|---|---|---|
id | path |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
201 | le webhook, et son secret (une fois) |
400 | `adresse_invalide` (une adresse `https://`, port 443, d'un hôte public ; au bac à sable, `http://` port 80 aussi), `evenements_vides`, `evenement_inconnu` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnue, ou à un autre compte |
409 | `trop_de_webhooks` (cinq au plus) ou `agent_sans_webhook` |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
GET /v1/creneaux
Les créneaux publiés par CETTE application, par pages
Portée : creneaux.publier
| Paramètre | Où | Description |
|---|---|---|
| ||
|
| Statut | Signification |
|---|---|
200 | une page des créneaux ; `publies` est faux tant que la publication est suspendue |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
PUT /v1/creneaux/{reference}
Publier ou corriger un créneau et sa grille de prix — idempotent
⚠ LA PUBLICATION DES CRÉNEAUX EST SUSPENDUE : ReCoDanse range, valide et te rend tes créneaux, mais ne les montre à personne d'autre tant qu'un avis juridique (directive DAC7) n'est pas rendu. Chaque réponse le dit (`publie: false`, `raison: publication_suspendue_dac7`). La grille : unités déclarées une fois, tranches contiguës de 1 personne à la capacité, montants en centimes d'euro. Le règlement est un lien SORTANT (`lien_externe`), `sur_place` ou `aucune` — ReCoDanse ne lit aucun état de paiement.
Portée : creneaux.publier
| Paramètre | Où | Description |
|---|---|---|
reference | path | TA clé du créneau |
Corps : SaisieCreneau
| Statut | Signification |
|---|---|
200 | le créneau tel qu'il est désormais |
400 | `corps_illisible`, `reference_invalide`, `nature_invalide`, `dates_invalides`, `creneau_passe`, `capacite_invalide`, `danse_inconnue`, `lieu_invalide`, `unite_montant_invalide`, `unite_temps_invalide`, `tranches_invalides`, `tranches_non_contigues`, `montant_invalide`, `reglement_invalide`, `creneau_retire` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
DELETE /v1/creneaux/{reference}
Retirer un créneau
Portée : creneaux.publier
| Paramètre | Où | Description |
|---|---|---|
reference | path | TA clé du créneau |
| Statut | Signification |
|---|---|
204 | retiré |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
404 | `reference_inconnue` |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
GET /v1/danses
Le vocabulaire des danses — les clés que `danses` attend (public, sans jeton)
| Statut | Signification |
|---|---|
200 | les danses promues |
POST /v1/enregistrement
Enregistrer un agent (RFC 7591) — annoncé par la découverte de la porte (`registration_endpoint`)
Quoi que l'agent demande, il reçoit `authorization_code` + `refresh_token` et les portées des vidéos (`openid`, `offline_access`, `videos.lire`, `videos.ranger`) — jamais `client_credentials`, jamais une portée de service. Un client public (`token_endpoint_auth_method: none`) n'a pas de secret et doit utiliser PKCE (S256). Borné à trente enregistrements par adresse et par quart d'heure.
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
201 | le client de l'agent |
400 | métadonnées refusées (`invalid_client_metadata`, `invalid_redirect_uri`) |
429 | trop d'enregistrements depuis cette adresse |
GET /v1/evenements
Les événements publiés par CETTE application (essais compris), par pages
Portée : evenements.publier
| Paramètre | Où | Description |
|---|---|---|
| ||
|
| Statut | Signification |
|---|---|
200 | une page des événements, par référence croissante (octet par octet) |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
PUT /v1/evenements/propositions/{reference}
Proposer un événement au nom de la personne — relu par un humain avant d'être publié
Un jeton DÉLÉGUÉ : la personne qui t'a autorisée est celle qui propose, et ReCoDanse la nomme par la délégation, jamais par le corps. L'événement part au statut `a_verifier` — aucune application, aucun palier n'y échappe — et n'est visible que de cette personne jusqu'à la relecture ; publié, il appartient au compte propriétaire de ton application. Adresse confirmée exigée (`adresse_non_verifiee`) ; un plafond par jour selon la confiance du compte (`plafond_du_jour`). Une référence qui désigne la proposition d'une autre personne, ou une proposition déjà relue, rend `reference_prise`.
Portée : evenements.proposer
| Paramètre | Où | Description |
|---|---|---|
reference | path | TA clé de la proposition (sans / ? #) : la reproposer sous la même référence la CORRIGE tant qu'elle attend |
Corps : SaisieEvenement
| Statut | Signification |
|---|---|
200 | la proposition telle qu'elle est rangée (`statut: a_verifier`, `essai: true`) |
400 | `corps_illisible`, `reference_invalide`, `espece_invalide`, `titre_invalide`, `danses_invalides`, `danse_inconnue`, `dates_invalides`, `evenement_passe`, `lieu_invalide`, `coordonnees_invalides`, `lien_invalide`, `lien_source_invalide` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | `adresse_non_verifiee`, `sans_proprietaire`, ou une portée qui manque |
409 | `reference_prise` |
429 | `plafond_du_jour`, ou le débit de l'application |
PUT /v1/evenements/{reference}
Publier ou corriger un événement — idempotent
L'événement apparaît dans l'agenda public et sur la carte du module social de ReCoDanse. Tant que l'application n'est pas publiée par la revue, c'est un ESSAI (`essai: true`) que seul le compte propriétaire voit. Un événement retiré par la modération ne se republie pas (`evenement_retire`).
Portée : evenements.publier
| Paramètre | Où | Description |
|---|---|---|
reference | path | TA clé de l'événement (sans / ? #) : republier la même référence CORRIGE au lieu de dupliquer |
Corps : SaisieEvenement
| Statut | Signification |
|---|---|
200 | l'événement tel qu'il est désormais |
400 | `corps_illisible`, `reference_invalide`, `espece_invalide`, `titre_invalide`, `danses_invalides`, `danse_inconnue`, `dates_invalides`, `evenement_passe`, `lieu_invalide`, `coordonnees_invalides`, `lien_invalide`, `evenement_retire` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
DELETE /v1/evenements/{reference}
Retirer un événement (il disparaît de l'agenda ; sa référence ne se republie pas)
Portée : evenements.publier
| Paramètre | Où | Description |
|---|---|---|
reference | path | TA clé de l'événement (sans / ? #) : republier la même référence CORRIGE au lieu de dupliquer |
| Statut | Signification |
|---|---|
204 | retiré |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
404 | aucun événement de cette application sous cette référence (`reference_inconnue`) |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
PUT /v1/programmes/{cle}
Poser un programme dans les entraînements de la personne (L238)
`{ "programme": { id, nom, definiA, elements | jours, rythme?, echeance? } }`, relu comme celui de l'app (`programme_<refus>`, 400). Le programme est marqué « posé par » l'application. Elle le REMPLACE tant qu'aucun jour n'est fini (`programme_commence` ensuite) ; elle ne touche jamais un programme qu'elle n'a pas posé (`programme_pas_a_toi`) ni un programme que la personne a supprimé (`programme_retire`), 409. Les cartes nomment les vidéos `vid_…` du compte.
Portée : programmes.poser
| Paramètre | Où | Description |
|---|---|---|
cle | path | l'identifiant du programme (`programme.id`) |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | posé : `{ cle, version }` |
400 | `programme_forme`, `programme_nom`, `programme_aucun_element`, `programme_jour_vide`, `programme_doublon`, `programme_rythme`, `programme_echeance` |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
409 | `programme_pas_a_toi`, `programme_commence`, `programme_retire` |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/videos
Déposer un fichier vidéo dans la bibliothèque de la personne — la fiche (L238)
Un outil que la personne autorise dépose les fichiers qu'elle lui confie, par la MÊME porte que l'app ReCoDanse : mêmes bornes (palier, quota, types), même revue, vidéo PRIVÉE. Trois temps : cette fiche, puis `…/depot` (une adresse signée, en parts au-delà de 8 Mio), puis `…/depot/confirmer`. Le corps est celui de l'app (`titre`, `source: fichier`, `duree_s`, `nom_d_origine`, `empreinte_source`, dimensions, date de prise) ; `ajouter_quand_meme` et `reference` sont ignorés. Un film que le compte a déjà rend 409 `meme_film` avec la vidéo existante : une relance ne duplique rien, elle reprend son dépôt si `stockage` le dit inachevé. Rien ne revient pour LIRE : ni adresse de lecture, ni vignette.
Portée : videos.deposer
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
201 | la fiche créée |
400 | `fichier_seulement` (un lien de plateforme n'entre pas ici), corps invalide |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
409 | `meme_film` — le compte a déjà ce film : `video` (réduite) et `voie` disent lequel et comment il a été reconnu |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/videos/{id}/depot
Demander le dépôt signé des octets (L238)
Exige que la personne ait accepté les conditions en vigueur et confirmé son adresse (`conditions_a_accepter`, `adresse_non_verifiee`) — la même garde que l'app. Le corps est `{ type_contenu, taille_octets }` ; au-delà de 8 Mio la réponse porte un `televersement` (un PUT par part, à confirmer). Les bornes du palier répondent 507 avec leur code (`taille_hors_gratuit`, `duree_hors_gratuit`, `volume_hors_gratuit`, `quota_depasse`), 413 au-delà du gabarit, 415 pour un type refusé.
Portée : videos.deposer
| Paramètre | Où | Description |
|---|---|---|
id | path | l'identifiant `vid_…` rendu par `POST /v1/videos` |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | l'adresse signée (`url`, `methode`, `expire_dans_s`, `taille_max_octets`), et `televersement` en parts |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
404 | aucune vidéo de ce compte sous cet identifiant |
413 | au-delà du gabarit |
415 | type refusé |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
507 | borne du palier ou quota (`taille_hors_gratuit`, `duree_hors_gratuit`, `volume_hors_gratuit`, `quota_depasse`) |
POST /v1/videos/{id}/depot/confirmer
Confirmer le dépôt — le magasin a le dernier mot sur la taille et le type (L238)
Portée : videos.deposer
| Paramètre | Où | Description |
|---|---|---|
id | path |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | la fiche, réduite |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
404 | aucune vidéo de ce compte sous cet identifiant |
415 | le fichier déposé n'est pas du type annoncé — dépôt retiré |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
POST /v1/videos/{id}/travail/fusion
Poser des passages et des explications sur une vidéo — par fusion, rien ne s'efface (L238)
Le corps est celui de l'app : `sequences` (`a`, `b`, `explication`) et `passages_nommes` (`nom`, `premiere_s`, `derniere_s`, `nomme_le`). Ce qui est déjà au compte reste ; la réponse est le travail fusionné.
Portée : videos.annoter
| Paramètre | Où | Description |
|---|---|---|
id | path |
Corps : objet JSON (voir le contrat)
| Statut | Signification |
|---|---|
200 | le travail fusionné |
400 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
403 | portée manquante (`portee_manquante`, avec `WWW-Authenticate: … error="insufficient_scope"`), application suspendue, compte suspendu, ou mauvaise espèce de jeton (`jeton_de_service`, `jeton_delegue`) |
404 | aucune vidéo de ce compte sous cet identifiant |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
DELETE /v1/webhooks/{id}
Retirer un webhook (son journal part avec lui)
| Paramètre | Où | Description |
|---|---|---|
id | path |
| Statut | Signification |
|---|---|
204 | retiré |
401 | jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`. |
404 | inconnu, ou d'une application d'un autre compte |
429 | le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes |
Schémas
Application
Une de tes applications, telle que ReCoDanse la connaît (le même objet que « Mes applications »).
| Propriété | Type | Description |
|---|---|---|
categorie | string (connexion | service | agent) | |
client_id | string | l'identifiant de client OAuth2 (Hydra) |
cree_le | string | |
description | string | |
id | string | l'identifiant ReCoDanse — distinct du `client_id` |
nom | string | |
portees | array | |
publique | boolean | |
redirections | array | |
site_web | string | |
statut | string (developpement | en_revue | publiee | suspendue | non_verifiee) |
CorpsDeWebhook
Le corps d'un envoi signé « Standard Webhooks » (en-têtes `webhook-id`, `webhook-timestamp`, `webhook-signature: v1,<HMAC-SHA256 base64>`).
| Propriété | Type | Description |
|---|---|---|
data | object | |
schema_version | integer | la version de la forme de `data` pour ce `type` (comme `eventSchemaVersion` chez Mindbody) ; elle monte quand un champ de `data` est retiré ou renommé, jamais pour un champ ajouté |
timestamp | string | |
type | string |
Creneau
| Propriété | Type | Description |
|---|---|---|
essai | boolean | |
etat | string (publie | complet) | |
id | string | |
publie | boolean | FAUX tant que la publication des créneaux est suspendue (DAC7) |
raison | string | |
reference | string | |
… | SaisieCreneau | toutes les propriétés de SaisieCreneau |
DeclarationApplication
| Propriété | Type | Description |
|---|---|---|
accepte_les_conditions | string | la version des conditions des développeurs acceptée |
categorie | string (connexion | service) | |
description | string | |
nom | string | |
portees | array | connexion : openid, profile, email, offline_access, videos.lire, videos.ranger, videos.deposer, videos.annoter, programmes.poser, evenements.proposer · service : evenements.publier, creneaux.publier |
publique | boolean | client sans secret (app native, page web) — PKCE obligatoire ; ne change plus après la déclaration |
redirections | array | connexion seulement : https://, http://127.0.0.1 ou un schéma d'app native ; dix au plus |
site_web | string | https:// seulement |
Erreur
| Propriété | Type | Description |
|---|---|---|
code | string | stable, à lire à la machine (`jeton_invalide`, `portee_manquante`, `application_suspendue`…) |
error | string | la phrase, en français — elle peut changer |
Evenement
| Propriété | Type | Description |
|---|---|---|
essai | boolean | vrai tant que l'application n'est pas publiée par la revue |
id | string | l'identifiant ReCoDanse de la fiche |
reference | string | |
statut | string (publie | annule | a_verifier) | `a_verifier` : une proposition qui attend la relecture d'un humain |
… | SaisieEvenement | toutes les propriétés de SaisieEvenement |
Lieu
| Propriété | Type | Description |
|---|---|---|
latitude | number | |
longitude | number | |
nom | string | |
ville | string |
SaisieCreneau
| Propriété | Type | Description |
|---|---|---|
capacite | integer | |
complet | boolean | |
danse | string | clé de GET /v1/danses (facultative) |
debut | string | |
fin | string | au plus 12 heures après le début |
grille | object | |
lieu | [object null] | null = « à convenir » |
message | string | |
nature | string (cours | salle) | cours : un prof ; salle : un studio loue une salle |
niveau | string | |
reglement | object |
SaisieEvenement
| Propriété | Type | Description |
|---|---|---|
annule | boolean | vrai : la fiche reste, et dit « annulé » (ignoré dans une proposition) |
danses | array | clés de GET /v1/danses |
debut | string | |
description | string | |
espece | string (social | stage | festival | marathon) | |
fin | string | au plus 14 jours après le début |
lien_billetterie | string | https:// seulement |
lien_source | string | d'où vient l'événement (sa publication, sa page) — https:// seulement ; distinct du lien de billetterie |
lieu | Lieu | un lieu PUBLIC — jamais un domicile |
prix_indicatif | string | |
titre | string |
Tranche
| Propriété | Type | Description |
|---|---|---|
a | integer | |
de | integer | |
montant_centimes | integer |
VideoDeposee
Ce qu'une fiche dit à l'outil qui l'a déposée (L238) — liste positive : jamais une adresse de lecture, jamais une vignette
| Propriété | Type | Description |
|---|---|---|
cree_le | string | |
duree_s | number | |
empreinte_source | [string null] | |
id | string | `vid_…` |
nom_d_origine | [string null] | |
reference_externe | string | |
source | string | |
stockage | object | l'état du dépôt (jamais une clé ni une adresse) |
titre | string |
Webhook
| Propriété | Type | Description |
|---|---|---|
actif | boolean | |
application | string | |
cree_le | string | |
evenements | array | |
id | string | |
url | string |