Guide cas concret · API Datacopro v2 · Assemblées générales

Préparer l'ordre du jour d'une AG

Créer une assemblée générale, composer son ordre du jour (résolutions, sous-résolutions, majorités, clés de répartition), le réordonner, figer les textes de convocation et y joindre les pièces, jusqu'à l'envoi de la convocation.

Périmètre : une copropriété Avant la séance Suite : guide « Tenir une AG »
À propos de ce guide

Ce guide décrit uniquement le contrat de l'API Datacopro : les appels, leur ordre, les paramètres utiles et les comportements à connaître. Vous n'avez besoin de connaître aucun logiciel de gestion en particulier. Les parcours s'inspirent d'une intégration réelle en production, citée ponctuellement à titre d'illustration.

La tenue de la séance (émargement, votes, calcul des résultats, clôture) fait l'objet d'un guide séparé : Tenir une AG.

01

Modèle & périmètre

Une assemblée générale appartient à une copropriété. Son ordre du jour n'est pas un objet à part : c'est la liste des résolutions rattachées à l'assemblée, chacune portant son numéro d'ordre. Toutes les routes sont préfixées par https://syndic.datacopro.org/v2 et scopées par /copro/{idCopro}. Les dates s'échangent au format AAAA-MM-JJ HH:MM:SS.

Exemple : ordre du jour tel que l'API le structure
  1. 1Élection du président de séancesimple · art. 24
  2. 2Approbation des comptes de l'exercice 2025simple · art. 24
  3. 3Désignation du syndicabsolue · art. 25 · revotable
  4. 4Ravalement de la façade sur rueabsolue · art. 25 · revotable
  5. 4.1Choix de l'entreprise Asous-résolution
  6. 4.2Choix de l'entreprise Bsous-résolution
  7. 5Questions diversessans vote

Assemblée /copro/{id}/assemblee/{idAg}

  • id, type : ordinaire, extraordinaire ou constitutive
  • libelle, note, langues (FR, NL)
  • datePrevisionnelle, dateEnvoiConvocation, dateReelle, dateFermeture, dateEnvoiPv
  • estAvecVotes : l'assemblée enregistre-t-elle des votes nominatifs
  • acces[] : modalités de participation (type, libelle, description, procedure)
  • exercices[], documents[], resolutions[]
  • statut : ouverte, confirmée ou annulée

Résolution resolutions[]

  • id, numero, numeroReference (numéro du parent pour une sous-résolution)
  • majorite : la référence textuelle (simple, absolue…), pas un identifiant
  • estRevotable : éligible au second vote (passerelle art. 25-1 / 26-1)
  • cle : clé de répartition qui porte les tantièmes du vote
  • contact, historique (qui a suggéré la résolution)
  • Trois jeux de textes : voir ci-dessous
  • sousResolutions[], resolutionRevote, documents[]

Trois versions du texte d'une résolution

ChampsRôleQuand l'écrire
libelle, contenuTexte de travail, éventuellement avec vos propres variables de modèle.Pendant la préparation.
libelleConvocation, contenuConvocationTexte définitif tel qu'il figure dans la convocation.Avant de générer la convocation.
libellePv, contenuPvTexte final, éventuellement amendé, tel qu'il figurera au procès-verbal.Pendant la séance (guide « Tenir une AG »).

En lecture, contenuVariabilise renvoie contenuConvocation, ou contenu si le premier est vide. contenuFinal renvoie contenuPv. L'API ne remplace aucune variable : les substitutions (nom du syndic, date de l'assemblée…) sont à votre charge.

Où en est l'assemblée ? Lire les dates, pas le statut

Le champ statut est un statut administratif (ouverte à la création, puis éventuellement confirmée ou annulée). Il ne reflète pas l'avancement. Pour savoir à quelle étape se trouve l'assemblée, lisez ses dates, de la plus avancée à la moins avancée :

ConditionÉtapeOrdre du jour modifiable ?
dateEnvoiPv renseignéePV envoyé, assemblée terminéeNon (convention recommandée)
dateFermeture renseignéeSéance close, PV à envoyerAjout et suppression refusés par l'API
Statut annuléeAssemblée annuléeNon (convention recommandée). L'API, elle, ne bloque rien
dateReelle sans dateFermetureSéance en coursVoir « Tenir une AG »
dateEnvoiConvocation renseignéeConvocation envoyée, assemblée à tenirNon (convention recommandée)
datePrevisionnelle et au moins un accèsPrête à convoquerOui
Aucune de ces datesBrouillonOui
Illustration

Cette lecture par étapes est une convention, pas une donnée de l'API. C'est ainsi qu'un logiciel de gestion existant affiche l'étape d'une assemblée à ses utilisateurs, et c'est lui qui interdit l'édition de l'ordre du jour une fois la convocation envoyée. L'API, elle, ne l'interdit pas (voir Limites).

Périmètre

02

Contrôle d'accès

Chaque appel est authentifié par un jeton OAuth. Le client doit être autorisé sur la copropriété visée, sinon l'API répond 403 avec {"message":["User not allowed"],"code":403}. L'API vérifie aussi que l'assemblée appartient bien à la copropriété de l'URL, et la résolution à l'assemblée. Aucun accès « copropriétaire » n'est prévu : ces routes sont réservées à l'usage du gestionnaire.

03

Parcours fonctionnels

A

Créer l'assemblée

Cas d'usage : le gestionnaire ouvre une nouvelle AG ordinaire pour approuver les comptes de l'exercice écoulé.

POST/copro/{idCopro}/assemblee.json
{
  "type": "ordinaire",
  "libelle": "AG ordinaire 2026",
  "datePrevisionnelle": "2026-06-18 18:30:00",
  "avecVotes": 1,
  "exercices": [812],
  "langues": [],
  "acces": [
    { "type": "physique", "libelle": "Salle paroissiale",
      "description": "12 rue des Lilas, Lyon" },
    { "type": "correspondance", "libelle": "Vote par correspondance",
      "procedure": "Formulaire à retourner au syndic au moins 3 jours francs avant la séance" }
  ]
}
  • exercices : identifiants des exercices comptables de la copropriété soumis à l'assemblée (pour une AG ordinaire d'approbation des comptes).
  • acces : un seul accès par type (physique, visio, audio, correspondance, autre). type et libelle sont obligatoires pour chaque accès.
  • avecVotes : à 1 par défaut. À 0, la séance n'enregistrera que les résultats, sans vote nominatif.
  • libelle : 256 caractères au maximum.

Réponse 201 : l'assemblée complète, au statut ouverte. Conservez son id.

Limite

À la création, seuls type, libelle, note, datePrevisionnelle, avecVotes, acces, exercices et langues sont pris en compte. Les autres champs acceptés par la route (dateEnvoiConvocation, distributionPouvoir, tags…) sont ignorés sans erreur. Renseignez-les ensuite par un PUT.

PUT/copro/{idCopro}/assemblee/{idAg}.json

Modification partielle : seuls les champs envoyés sont modifiés. Le statut ne se change pas ici (voir Tenir une AG).

Limite

La liste acces est traitée par type. Retirer un accès en l'omettant n'est pas garanti : relisez l'assemblée après modification pour vérifier que l'accès retiré a bien disparu. Lorsque vous modifiez acces ou exercices, renvoyez toujours la liste complète.

B

Charger les référentiels : majorités et clés

Cas d'usage : proposer au gestionnaire, dans un formulaire de résolution, uniquement les majorités et les clés valables pour cette copropriété.

GET/copro/{idCopro}/type/majorite.json

Renvoie les majorités du cadre juridique de la copropriété, plus sans vote. Chaque entrée porte sa reference (la valeur à envoyer dans majorite), ses seuils (tauxTantiemesMin, tauxParticipationMin) et ses traductions.

RéférenceArticle (France)Revotable ?
simpleart. 24Non
absolueart. 25Oui : passerelle art. 25-1 vers un second vote à l'art. 24
doubleart. 26Oui : passerelle art. 26-1 vers un second vote à l'art. 25
unanimitéunanimitéNon
sans votepoint d'informationNon

Les copropriétés belges reçoivent leurs propres références (absolue (belgique), deux-tiers (belgique), etc.). Certaines copropriétés disposent de majorités spécifiques supplémentaires : ne codez donc pas la liste en dur.

Pourquoi

À la création d'une résolution, l'API vérifie que la référence existe, pas qu'elle correspond au cadre de la copropriété. C'est à vous de ne proposer que les majorités renvoyées par cette route.

GET/copro/{idCopro}/cles.json?displays[]=!tantiemesParLot.*

Liste les clés de répartition. L'exclusion !tantiemesParLot.* évite de rapatrier les tantièmes lot par lot, inutiles pour un simple choix de clé. Proposez par défaut la clé générale de la copropriété (celle qui répartit les charges communes sur l'ensemble des lots) : c'est la clé habituelle des résolutions sans objet de dépense spécifique.

C

Ajouter une résolution, puis ses sous-résolutions

Cas d'usage : inscrire le ravalement de façade (art. 25, revotable), puis deux variantes à départager, une par entreprise.

POST/copro/{idCopro}/assemblee/{idAg}/resolution.json
{
  "numero": 4,
  "libelle": "Ravalement de la façade sur rue",
  "contenu": "L'assemblée générale, après en avoir délibéré, décide…",
  "majorite": "absolue",
  "revotable": 1,
  "cle": 3021,
  "historique": "Résolution inscrite à la demande du conseil syndical"
}
  • Obligatoires : numero (entier non nul), libelle, majorite (référence), cle (identifiant d'une clé de la copropriété).
  • contenu est facultatif : un point « Questions diverses » peut n'avoir aucun texte.
  • revotable n'est accepté qu'avec absolue ou double. C'est ce drapeau qui déclenchera automatiquement le second vote pendant la séance si les conditions légales sont réunies.
  • Vous pouvez aussi envoyer d'emblée libelleConvocation et contenuConvocation (voir parcours E).

Réponse 201 : la résolution créée, avec son id.

Limite

numero n'est pas contrôlé en unicité : deux résolutions peuvent porter le même numéro. Calculez vous-même le prochain numéro libre (le plus grand numéro existant + 1). Évitez aussi revotable avec une majorité absente ou invalide : l'API répond alors une erreur 500 au lieu d'un 400 explicite.

POST/copro/{idCopro}/assemblee/{idAg}/resolution.json
{ "numero": 1, "libelle": "Choix de l'entreprise A", "majorite": "absolue",
  "cle": 3021, "resolutionParente": 90412 }

resolutionParente rattache la résolution à son parent (90412, la résolution 4 créée juste avant). Le numero d'une sous-résolution est son rang parmi ses sœurs (1, 2…). L'affichage « 4.1 » se déduit de numeroReference (numéro du parent) et numero. En pratique, reprenez la clé et la majorité du parent comme valeurs par défaut.

Effet de bord

Ajouter une résolution en dernière position étend automatiquement jusqu'à elle les présences déjà enregistrées qui couraient jusqu'à la fin de l'ordre du jour. Sans conséquence en préparation, ce comportement est utile en séance (guide « Tenir une AG »).

D

Réordonner, modifier, supprimer

Cas d'usage : le gestionnaire déplace « Désignation du syndic » en tête, corrige une clé, puis retire un point devenu inutile.

PUT/copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}.json
{ "numero": 1 }

Il n'existe pas de route de réordonnancement : l'ordre du jour est trié par numero. Pour déplacer une résolution, attribuez-lui son nouveau numéro, puis renumérotez ses sœurs (même niveau, même parent) en n'envoyant un PUT qu'aux résolutions dont le numéro change réellement.

Le même PUT modifie n'importe quel champ : libelle, contenu, majorite, revotable, cle, contact, historique… Seuls les champs présents sont modifiés. Réponse 202 avec la résolution.

Limite : aucun contrôle de périmètre en modification

Contrairement à la création, cette route ne refuse pas une clé, un contact ou un parent hors périmètre : une clé ou un contact d'une autre copropriété, ou un parent pris dans une autre assemblée, est accepté et enregistré, avec une réponse 202. Relire la réponse ne suffit donc pas à détecter l'erreur. Validez l'identifiant avant l'envoi : la clé doit figurer dans GET /copro/{idCopro}/cles.json, le contact dans les contacts de la copropriété, le parent parmi les résolutions de premier niveau de cette assemblée. Seuls un identifiant qui n'existe pas du tout et une référence de majorité inconnue sont ignorés : pour ces deux cas, comparez la résolution renvoyée à ce que vous avez envoyé.

Limite

La règle « revotable seulement avec absolue ou double » n'est vérifiée qu'à la création. Si vous passez une résolution de absolue à simple, envoyez aussi "revotable": 0 dans le même appel. Une sous-résolution ne peut pas être détachée de son parent : supprimez-la et recréez-la au premier niveau. Enfin, en modification, rien n'empêche de rattacher une résolution sous une sous-résolution (deux niveaux) : n'acceptez comme parent qu'une résolution de premier niveau.

DELETE/copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}.json

Réponse 204. La suppression emporte les sous-résolutions et les votes. Les pièces jointes sont détachées de la résolution mais restent dans les documents de la copropriété.

Limite

Les résolutions restantes ne sont pas renumérotées. Supprimer la 3 sur 6 laisse la suite 1, 2, 4, 5, 6. Renumérotez les sœurs de 1 à n juste après (un PUT {"numero": i} par résolution décalée). Pour vider entièrement l'ordre du jour, supprimez les résolutions une à une, en commençant par les sous-résolutions.

E

Figer les textes de convocation

Cas d'usage : vos modèles contiennent des variables (nom du syndic, date de l'assemblée, majorité, clé). Avant de produire la convocation, il faut en stocker la version définitive.

PUT/copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}.json
{
  "libelleConvocation": "Ravalement de la façade sur rue",
  "contenuConvocation": "L'assemblée générale du 18 juin 2026, statuant à la majorité de l'article 25…"
}

Recalculez ces deux champs après chaque modification de l'ordre du jour ou de l'assemblée (la date, par exemple), pour chaque résolution et sous-résolution, et n'envoyez le PUT que si la valeur change.

Pourquoi

Garder contenu comme texte de travail et contenuConvocation comme texte envoyé vous permet de régénérer la convocation sans perdre le modèle. Le jour de la séance, le texte au procès-verbal part de la version convoquée.

Illustration

Un logiciel de gestion existant refait ce calcul après chaque ajout, modification ou suppression de résolution, puis supprime les convocations déjà générées pour éviter d'en envoyer une version périmée.

F

Ordre du jour bilingue (copropriétés belges)

Cas d'usage : une assemblée convoquée en français et en néerlandais.

Créez l'assemblée avec "langues": ["FR","NL"]. Créez chaque résolution dans la langue principale, puis envoyez les textes de chaque langue par un PUT portant le paramètre locale : d'abord la langue secondaire, puis la langue principale.

PUT /copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}.json
{ "locale": "NL", "libelle": "Gevelrenovatie", "contenu": "…" }

PUT /copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}.json
{ "locale": "FR", "libelle": "Rénovation de la façade", "contenu": "…" }

En lecture, ajoutez ?locale=NL (ou FR) pour obtenir les textes dans la langue voulue.

Illustration

Cet ordre (secondaire, puis principale) est celui qu'utilise une intégration en production pour que les deux traductions soient bien enregistrées. Relisez la résolution dans chaque locale pour vérifier le résultat.

G

Joindre les pièces et marquer la convocation envoyée

Cas d'usage : annexer un devis à une résolution, déposer la convocation générée, puis enregistrer la date d'envoi.

POST/copro/{idCopro}/assemblee/{idAg}/resolution/{idRes}/document/{type}.json
{
  "libelle": "Devis entreprise A",
  "tags": ["AG", "devis"],
  "fichier": { "mode": "url", "nom": "devis-a.pdf",
               "valeur": "https://stockage.example.com/devis-a.pdf" }
}

fichier.mode vaut url (l'API télécharge le fichier) ou base64 (contenu dans valeur). {type} est libre pour une pièce de résolution ; autre convient.

Limite

Retirer une pièce d'une résolution (DELETE …/resolution/{idRes}/document/{idDoc}.json) supprime le document lui-même, pas seulement le lien. Si le fichier sert ailleurs, gardez-en une copie.

POST/copro/{idCopro}/assemblee/{idAg}/document/{type}.json

Même corps de requête. Les types d'usage courant sont convocation, odj, coproprietaire (convocation nominative), note-informations-convocation et comptabilite. Utilisez ces valeurs : l'API ne les valide pas, mais les consommateurs de l'assemblée s'appuient dessus pour retrouver les pièces.

Si vous régénérez une convocation, retirez d'abord l'ancienne version avec DELETE /copro/{idCopro}/assemblee/{idAg}/document/{idDoc}.json. Cet appel supprime aussi le fichier lui-même lorsqu'il n'est pas utilisé ailleurs (par exemple dans un envoi déjà journalisé).

PUT/copro/{idCopro}/assemblee/{idAg}.json
{ "dateEnvoiConvocation": "2026-05-20 09:12:00" }

À n'envoyer qu'une fois la convocation réellement expédiée. Cette date fait passer l'assemblée à l'étape « à tenir » pour tous les logiciels qui la lisent.

Limite

L'API ne verrouille pas l'ordre du jour après l'envoi de la convocation : ajouts, modifications et suppressions restent techniquement possibles jusqu'à la clôture de la séance. Or une résolution non inscrite à la convocation ne peut pas être valablement votée. Bloquez vous-même l'édition dès que dateEnvoiConvocation est renseignée.

H

Relire l'ordre du jour

Cas d'usage : afficher l'ordre du jour d'une assemblée, ou lister les assemblées d'une copropriété.

GET/copro/{idCopro}/assemblee/{idAg}.json?displays[]=!presences.*&displays[]=!resolutions.votesResolution.*

Sans displays, l'API renvoie l'assemblée complète, y compris la feuille de présence et tous les votes. Les deux exclusions ci-dessus allègent fortement la réponse pour un simple affichage de l'ordre du jour.

resolutions[] ne contient que les résolutions de premier niveau, sans tri garanti. Les sous-résolutions sont imbriquées dans sousResolutions[] et un éventuel second vote dans resolutionRevote. Triez vous-même chaque niveau par numero.

GET/copro/{idCopro}/assemblees.json

Liste les assemblées de la copropriété (notez le pluriel : /assemblee.json est la route de création). Cette liste n'est pas paginée et renvoie des assemblées complètes : utilisez les mêmes exclusions, ou une inclusion explicite des seuls champs utiles (displays[]=id&displays[]=libelle&displays[]=datePrevisionnelle…).

Pour une vue multi-copropriétés, GET /domaines/{idDomaine}/assemblees.json renvoie les assemblées d'un domaine, avec leur copropriété et leurs exercices, mais sans résolutions ni documents.

04

Référence des endpoints

MéthodeRouteRôle
GET/copro/{id}/assemblees.jsonLister les assemblées d'une copropriété.
GET/copro/{id}/assemblee/{idAg}.jsonLire une assemblée et son ordre du jour.
POST/copro/{id}/assemblee.jsonCréer une assemblée.
PUT/copro/{id}/assemblee/{idAg}.jsonModifier une assemblée (partiel), dont dateEnvoiConvocation.
DELETE/copro/{id}/assemblee/{idAg}.jsonSupprimer une assemblée et tout son contenu.
GET/copro/{id}/type/majorite.jsonMajorités disponibles pour la copropriété.
GET/copro/{id}/cles.jsonClés de répartition de la copropriété.
POST/copro/{id}/assemblee/{idAg}/resolution.jsonAjouter une résolution ou une sous-résolution.
GET/copro/{id}/assemblee/{idAg}/resolution/{idRes}.jsonLire une résolution.
PUT/copro/{id}/assemblee/{idAg}/resolution/{idRes}.jsonModifier une résolution, dont son numéro et ses textes.
DELETE/copro/{id}/assemblee/{idAg}/resolution/{idRes}.jsonSupprimer une résolution (sans renumérotation).
POST/copro/{id}/assemblee/{idAg}/resolution/{idRes}/document/{type}.jsonJoindre une pièce à une résolution.
DELETE/copro/{id}/assemblee/{idAg}/resolution/{idRes}/document/{idDoc}.jsonRetirer et supprimer une pièce de résolution.
POST/copro/{id}/assemblee/{idAg}/document/{type}.jsonDéposer un document d'assemblée (convocation, ODJ…).
DELETE/copro/{id}/assemblee/{idAg}/document/{idDoc}.jsonRetirer un document d'assemblée.
GET/copro/{id}/assemblee/{idAg}/logs.jsonHistorique des modifications de l'assemblée et de ses résolutions.
GET/domaines/{idDomaine}/assemblees.jsonAssemblées de toutes les copropriétés d'un domaine (vue résumée).

Une route de duplication de résolution existe (PUT …/resolution/{idRes}/dupliquer.json), mais elle place la copie en fin de liste et ne renvoie pas l'identifiant créé. Pour dupliquer, relisez la résolution source et recréez-la par un POST.

05

Paramètres transverses

ParamètreSyntaxeEffet sur le coût de l'appel
displaysdisplays[]=champ, displays[]=objet.*, displays[]=!champSans paramètre ou avec des exclusions seulement : tout sauf les champs exclus. Avec au moins une inclusion : seuls les champs listés, et sur une assemblée la feuille de présence et les votes ne sont alors chargés que si vous incluez resolutions.* ou presences.*. C'est le levier principal pour alléger la réponse.
filtersfilters[champ]=valeur, filters[champ__op]=valeur, groupes filters[0][…] combinés en OUSur les listes seulement. Opérateurs : eq, diff, gt, gte, lt, lte, contains, ncontains, empty, nempty. Texte : contains par défaut. Nombres et dates : opérateur obligatoire, par exemple filters[datePrevisionnelle__gte]=2026-01-01 00:00:00.
localeFR, NLLangue des textes lus ou écrits (assemblées multilingues).
Pièges de syntaxe
  • Pour un objet ou une liste, l'inclusion doit se terminer par .*. displays[]=resolutions seul renvoie des objets vides. De même, l'exclusion d'une liste s'écrit !presences.*.
  • Pour « inférieur ou égal », utilisez le suffixe __lte. Les préfixes <= dans la valeur sont refusés. Pour « différent de », utilisez __diff.
  • Les routes d'assemblée ne gèrent ni tri ni pagination : triez côté client.
06

Limites & pièges connus

07

Questions de validation

Je supprime la résolution n° 3 d'un ordre du jour qui en compte 6. Les suivantes sont-elles renumérotées ?

Non. L'ordre du jour devient 1, 2, 4, 5, 6. Envoyez ensuite un PUT {"numero": i} à chaque résolution décalée du même niveau. Voir parcours D.

Mon PUT qui change la clé de répartition d'une résolution a répondu 202. Suis-je sûr que la bonne clé est enregistrée ?

Non. En modification, l'API ne vérifie pas que la clé appartient à la copropriété : une clé d'une autre copropriété est enregistrée sans erreur, et la réponse renvoie bien l'identifiant envoyé. Vérifiez donc, avant l'envoi, que la clé figure dans GET /copro/{idCopro}/cles.json. Seul un identifiant inexistant est ignoré, ce que la comparaison de la réponse permet de repérer. Voir parcours D.

Une fois la convocation envoyée, l'API m'empêche-t-elle de modifier l'ordre du jour ?

Non. Renseigner dateEnvoiConvocation ne verrouille rien. Seule la clôture de la séance (dateFermeture) bloque l'ajout et la suppression de résolutions ; même alors, les modifications restent possibles. Le statut annulée ne bloque rien non plus. Bloquez l'édition dans votre logiciel. Voir parcours G et Limites.