Aller au contenu

Rapports X, Z et A

POST /businesses/{business}/reports (Idempotency-Key obligatoire)
{ "type": "Z", "point_of_sale": "ent_2xJ4kQ9nVbT7mLpR3sYz" }
type Ce que c’est point_of_sale
X Le rapport X de la DGI pour la session en cours du point de vente. Ne clôt rien. facultatif : un point de vente, ou toute l’entreprise
X_PERIODIC Un X sur une période : period_start et period_end (des instants, le début avant la fin) sont obligatoires. facultatif, comme X
Z La clôture journalière d’un point de vente. Clôt sa session. obligatoire (400 POINT_OF_SALE_REQUIRED)
A Le rapport des articles d’un point de vente (il compte les articles distincts ; il répond total_articles et total_ttc). Clôt sa session. obligatoire

Z et A se font par point de vente seulement, parce que les compteurs de la DGI sont par e-MCF. Seul X_PERIODIC prend une période.

La réponse est 202 { "id": "prp_...", "state": "queued" }. Le rapport est produit en arrière-plan ; report.ready (ou report.failed) est émis. GET /businesses/{business}/reports/{id} donne son state : queued, running, ready ou failed. Un rapport en échec donne error_code et error_message ; il a été tenté trois fois au plus. POST …/reports/{id}/retry remet en file un rapport failed (sinon 409 REPORT_NOT_FAILED). GET /businesses/{business}/reports les liste, du plus récent au plus ancien, avec les filtres type, origin (API, AUTO, FINAL, CONSOLE), state, point_of_sale, from, to. origin: "CONSOLE" est un X ou un X périodique que votre équipe a demandé dans la console Ripa : la console ne demande jamais de Z ni de A. Ses report.ready et report.failed vous parviennent comme les autres.

{
"object": "report",
"data": {
"id": "prp_2xJ4kQ9nVbT7mLpR3sYz",
"business_id": "biz_2xJ4kQ9nVbT7mLpR3sYz",
"type": "Z",
"origin": "API",
"state": "ready",
"point_of_sale": "ent_2xJ4kQ9nVbT7mLpR3sYz",
"nid": "CD01004159-1",
"session_number": 57,
"period_start": "2026-11-04T17:31:04Z",
"period_end": "2026-11-05T17:58:12Z",
"total_invoices": 128,
"total_ht": 2540000.00,
"total_vat": 406400.00,
"total_ttc": 2946400.00,
"created_at": "2026-11-05T17:59:10Z",
"finished_at": "2026-11-05T17:59:14Z"
},
"meta": { "request_id": "req_08" }
}

GET …/reports/{id}/file?format=csv (par défaut) ou format=xlsx. Avant ready, la réponse est 409 REPORT_NOT_READY (un rapport en échec en dit la cause dans le message).

Le CSV est exact. Les cellules numériques du classeur sont des doubles, qui tiennent environ 15 chiffres significatifs : à partir de 10^13 CDF environ, un montant du classeur perd des centimes. Rapprochez au centime à partir du CSV.

  • Un Z clôt une session, pas un jour calendaire. Il couvre ce que le point de vente a vendu depuis son dernier Z, quel que soit le moment où il a eu lieu. Un point de vente qui a sauté trois jours les clôt tous les trois en un seul Z.
  • Un Z s’arrête environ une minute avant votre demande (la marge de stabilisation). Une facture que la DGI a normalisée pendant cette dernière minute n’est pas dans ce Z ; elle tombe dans le suivant. Le period_end du Z est donc une minute avant l’instant où vous l’avez demandé.
  • Deux Z demandés au même moment passent l’un après l’autre : le second clôt la période suivante. Une période vide est un Z valide. Une relance ne clôt jamais une seconde session.
  • Un rapport A est refusé au-delà de 200 000 articles distincts : le rapport est failed avec error_code REPORT_TOO_LARGE, sa session reste ouverte, et il n’est pas relancé. Contactez-nous.
  • Un Z ou un A d’une entreprise transférée vers un compte autonome échoue avec BUSINESS_MOVED avant de rien clore.

Si vous avez beaucoup de points de vente (des milliers), ne demandez pas chaque Z vous-mêmes : vous rencontreriez le 429 REPORT_QUEUE_FULL comme une chose normale à 1 000 Z et A en attente (le compte des X est à part, et réunit les X de la console et les vôtres). Demandez-nous de régler votre heure de Z automatique (auto_z_time). Chaque jour à cette heure, dans le fuseau horaire propre à chaque point de vente, tous les points de vente actifs de vos entreprises actives sont clos (un point de vente inactif aussi, pour qu’un jour calme se distingue d’un traitement qui n’a pas eu lieu). Ces rapports portent origin: "AUTO", ne sont jamais refusés faute de place. Leur local_date désigne le jour pour lequel ils ont été faits, pas le jour des ventes qu’ils closent (qui sont celles depuis le dernier Z). Un point de vente créé après l’heure n’est pas dû ce jour-là. Si l’heure est changée pour une heure déjà passée aujourd’hui, les points de vente sont clos dans la minute. Une entreprise que vous avez mise en pause prend son Z quand vous la reprenez, ou quand vous en demandez un. Quand une entreprise se termine, chaque point de vente qui a vendu depuis son dernier Z reçoit un Z final (origin: "FINAL").

Sur un environnement où la normalisation n’est pas encore ouverte, POST …/reports, POST …/exports, POST …/invoices et POST …/credit-notes répondent 409 PIPELINE_NOT_ENABLED et n’enregistrent rien ; la lecture fonctionne. Écrivez-nous si vous le rencontrez en production après la mise en service.