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

« Se connecter avec ReCoDanse »Ton site authentifie les ReCoDanseurs·euses avec leur accord : un pseudonyme propre à ton application, le prénom public et le @nom si la personne l'accepte.
Publier des événementsTon logiciel d'organisateur pousse tes socials, stages et festivals : ils apparaissent dans l'agenda et sur la carte du module social.
Publier des créneauxLe planning de ton studio pousse ses créneaux et leurs tarifs. La publication est suspendue pour l'instant (voir plus bas).
Brancher un assistantUn assistant aide une personne qui danse à retrouver et ranger ses vidéos, par le serveur MCP — jamais les films eux-mêmes.

Démarrer

  1. Ouvre un compte sur https://recodanse.fr et confirme ton adresse e-mail.
  2. Déclare ton application. Choisis son espèce : connexion (un site ou une app qui authentifie les ReCoDanseurs·euses) ou service (un logiciel sans humain derrière, qui publie pour toi).
  3. Garde le client_secret : il ne se montre qu'une fois.
  4. Pose un webhook https:// abonné à autorisation.retiree et à 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 »).
  5. Pour l'ouvrir aux autres, soumets-la à la revue (POST /v0/tiers/applications/{id}/revue) en acceptant la version 2026-10-30 des 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 :

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éeCe que la personne litPour toiWebhook d'effacement
openidTe 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.—
profileTon prénom public (« Léa D. ») et ton @nom, si tu en as unRevendications `name` (prénom et initiale publics) et `preferred_username` (le @nom, sans arobase).exigé
emailTon adresse e-mailRevendications `email` et `email_verified` (vrai seulement si ReCoDanse a vérifié l'adresse).exigé
offline_accessGarder cet accès quand tu n'es pas là, jusqu'à ce que tu le retiresDélivre un jeton de rafraîchissement ; retiré dès que la personne retire l'application.exigé
videos.lireVoir la liste de tes vidéos et ce que tu en as noté (danse, prof, lieu, étiquettes) — jamais les films eux-mêmesLecture des MÉTADONNÉES des vidéos du compte (galerie, qualification, carnets). Aucun octet vidéo, aucune adresse de lecture.exigé
videos.rangerRanger 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.deposerDéposer dans ta bibliothèque les vidéos que tu lui confies — jamais en lire, en effacer ni en partagerDé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.annoterPoser des passages et marquer les explications sur tes vidéos — jamais en effacerFusion du travail d'une vidéo du compte (séquences, explications, passages nommés) : additive, rien ne s'efface.—
programmes.poserAjouter des programmes à tes entraînements — jamais changer les tiensPose 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.proposerProposer à l'agenda, en ton nom, les événements que tu ajoutes — relus par ReCoDanse avant d'être publiésJeton 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.publierPublier les événements de ton organisationCompte de service : publier, corriger et retirer les événements de SON propriétaire.—
creneaux.publierPublier les créneaux et les tarifs de ton studioCompte 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 nousEn anglaisSchema.orgChez les voisins
evenementeventDanceEventevent (Billetweb, Eventbrite, Weezevent)
especeevent type@type (+ rc:espece)category
titretitlenamename
debutstartstartDatestart / date_start
finendendDateend / date_end
lieuvenuelocation → Place · SportsActivityLocationvenue
dansesdance stylesabout → DefinedTermtags
prix_indicatifindicative priceoffers.descriptionprice
lien_billetterieticket linkoffers.urlticket url
annulecancelledeventStatus = EventCancelledstatus: canceled
creneauclass slotCourseInstance + Offersession / class (bsport, Mindbody)
capacitecapacitymaximumAttendeeCapacitycapacity
niveaulevelrc:niveauViselevel
trancheprice tierUnitPriceSpecificationticket class / tarif
videovideoVideoObject—
duree_sduration (seconds)duration—
applicationappSoftwareApplicationapp
porteesscopes—scopes
webhookwebhook—webhook / notification
espacecourseCourse—
CoDansesocial dance eventDanceEvent + rc:CoDanse—
inscritattendeeEventReservationattendee / 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.

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

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

StatutSignification
200la 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)

StatutSignification
200la 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)

StatutSignification
200la réponse JSON-RPC (`result` ou `error`) ; une erreur d'OUTIL est un `result` avec `isError: true`
202notification reçue
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
429le 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

StatutSignification
200tes applications, le plafond et la version des conditions des développeurs en vigueur
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
429le 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

StatutSignification
201l'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`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
409dix applications au plus (`trop_d_applications`)
429le 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ètreOùDescription
idpath
StatutSignification
200l'application
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte (le même 404)
429le 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ètreOùDescription
idpath

Corps : objet JSON (voir le contrat)

StatutSignification
200l'application corrigée
400mêmes codes que la déclaration
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte
409une application publiée n'élargit pas ses portées sans revue (`portees_figees`)
429le 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ètreOùDescription
idpath
StatutSignification
204retirée
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte
429le 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ètreOùDescription
idpath

Corps : objet JSON (voir le contrat)

StatutSignification
200l'application, en revue
400`conditions_perimees`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, 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
429le 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ètreOùDescription
idpath
StatutSignification
200le nouveau secret
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte
409un client public n'a pas de secret (`client_public`)
429le 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ètreOùDescription
idpath
StatutSignification
200les webhooks
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte
429le 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ètreOùDescription
idpath

Corps : objet JSON (voir le contrat)

StatutSignification
201le 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`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnue, ou à un autre compte
409`trop_de_webhooks` (cinq au plus) ou `agent_sans_webhook`
429le 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ètreOùDescription
StatutSignification
200une page des créneaux ; `publies` est faux tant que la publication est suspendue
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
429le 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ètreOùDescription
referencepathTA clé du créneau

Corps : SaisieCreneau

StatutSignification
200le 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`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
429le 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ètreOùDescription
referencepathTA clé du créneau
StatutSignification
204retiré
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`
429le 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)

StatutSignification
200les 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)

StatutSignification
201le client de l'agent
400métadonnées refusées (`invalid_client_metadata`, `invalid_redirect_uri`)
429trop 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ètreOùDescription
StatutSignification
200une page des événements, par référence croissante (octet par octet)
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
429le 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ètreOùDescription
referencepathTA clé de la proposition (sans / ? #) : la reproposer sous la même référence la CORRIGE tant qu'elle attend

Corps : SaisieEvenement

StatutSignification
200la 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`
401jeton 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ètreOùDescription
referencepathTA clé de l'événement (sans / ? #) : republier la même référence CORRIGE au lieu de dupliquer

Corps : SaisieEvenement

StatutSignification
200l'é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`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
429le 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ètreOùDescription
referencepathTA clé de l'événement (sans / ? #) : republier la même référence CORRIGE au lieu de dupliquer
StatutSignification
204retiré
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
404aucun événement de cette application sous cette référence (`reference_inconnue`)
429le 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ètreOùDescription
clepathl'identifiant du programme (`programme.id`)

Corps : objet JSON (voir le contrat)

StatutSignification
200posé : `{ cle, version }`
400`programme_forme`, `programme_nom`, `programme_aucun_element`, `programme_jour_vide`, `programme_doublon`, `programme_rythme`, `programme_echeance`
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`
429le 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)

StatutSignification
201la fiche créée
400`fichier_seulement` (un lien de plateforme n'entre pas ici), corps invalide
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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
429le 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ètreOùDescription
idpathl'identifiant `vid_…` rendu par `POST /v1/videos`

Corps : objet JSON (voir le contrat)

StatutSignification
200l'adresse signée (`url`, `methode`, `expire_dans_s`, `taille_max_octets`), et `televersement` en parts
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
404aucune vidéo de ce compte sous cet identifiant
413au-delà du gabarit
415type refusé
429le quota de l'application est dépassé (`quota_depasse`) : réessayer après `Retry-After` secondes
507borne 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ètreOùDescription
idpath

Corps : objet JSON (voir le contrat)

StatutSignification
200la fiche, réduite
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
404aucune vidéo de ce compte sous cet identifiant
415le fichier déposé n'est pas du type annoncé — dépôt retiré
429le 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ètreOùDescription
idpath

Corps : objet JSON (voir le contrat)

StatutSignification
200le travail fusionné
400porté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`)
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
403porté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`)
404aucune vidéo de ce compte sous cet identifiant
429le 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ètreOùDescription
idpath
StatutSignification
204retiré
401jeton absent, inconnu, expiré ou révoqué (`jeton_invalide`). L'en-tête `WWW-Authenticate` nomme `resource_metadata`.
404inconnu, ou d'une application d'un autre compte
429le 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éTypeDescription
categoriestring (connexion | service | agent)
client_idstringl'identifiant de client OAuth2 (Hydra)
cree_lestring
descriptionstring
idstringl'identifiant ReCoDanse — distinct du `client_id`
nomstring
porteesarray
publiqueboolean
redirectionsarray
site_webstring
statutstring (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éTypeDescription
dataobject
schema_versionintegerla 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é
timestampstring
typestring

Creneau

PropriétéTypeDescription
essaiboolean
etatstring (publie | complet)
idstring
publiebooleanFAUX tant que la publication des créneaux est suspendue (DAC7)
raisonstring
referencestring
…SaisieCreneautoutes les propriétés de SaisieCreneau

DeclarationApplication

PropriétéTypeDescription
accepte_les_conditionsstringla version des conditions des développeurs acceptée
categoriestring (connexion | service)
descriptionstring
nomstring
porteesarrayconnexion : openid, profile, email, offline_access, videos.lire, videos.ranger, videos.deposer, videos.annoter, programmes.poser, evenements.proposer · service : evenements.publier, creneaux.publier
publiquebooleanclient sans secret (app native, page web) — PKCE obligatoire ; ne change plus après la déclaration
redirectionsarrayconnexion seulement : https://, http://127.0.0.1 ou un schéma d'app native ; dix au plus
site_webstringhttps:// seulement

Erreur

PropriétéTypeDescription
codestringstable, à lire à la machine (`jeton_invalide`, `portee_manquante`, `application_suspendue`…)
errorstringla phrase, en français — elle peut changer

Evenement

PropriétéTypeDescription
essaibooleanvrai tant que l'application n'est pas publiée par la revue
idstringl'identifiant ReCoDanse de la fiche
referencestring
statutstring (publie | annule | a_verifier)`a_verifier` : une proposition qui attend la relecture d'un humain
…SaisieEvenementtoutes les propriétés de SaisieEvenement

Lieu

PropriétéTypeDescription
latitudenumber
longitudenumber
nomstring
villestring

SaisieCreneau

PropriétéTypeDescription
capaciteinteger
completboolean
dansestringclé de GET /v1/danses (facultative)
debutstring
finstringau plus 12 heures après le début
grilleobject
lieu[object null]null = « à convenir »
messagestring
naturestring (cours | salle)cours : un prof ; salle : un studio loue une salle
niveaustring
reglementobject

SaisieEvenement

PropriétéTypeDescription
annulebooleanvrai : la fiche reste, et dit « annulé » (ignoré dans une proposition)
dansesarrayclés de GET /v1/danses
debutstring
descriptionstring
especestring (social | stage | festival | marathon)
finstringau plus 14 jours après le début
lien_billetteriestringhttps:// seulement
lien_sourcestringd'où vient l'événement (sa publication, sa page) — https:// seulement ; distinct du lien de billetterie
lieuLieuun lieu PUBLIC — jamais un domicile
prix_indicatifstring
titrestring

Tranche

PropriétéTypeDescription
ainteger
deinteger
montant_centimesinteger

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éTypeDescription
cree_lestring
duree_snumber
empreinte_source[string null]
idstring`vid_…`
nom_d_origine[string null]
reference_externestring
sourcestring
stockageobjectl'état du dépôt (jamais une clé ni une adresse)
titrestring

Webhook

PropriétéTypeDescription
actifboolean
applicationstring
cree_lestring
evenementsarray
idstring
urlstring