Aller au contenu

Flux d’événements

Le flux est la référence de tout ce qui s’est passé sur votre compte. Le webhook vous signale seulement que le flux a du nouveau.

GET /events?after=<position>&limit=<1..1000>
{
"object": "list",
"data": [
{
"id": "pev_5d41402abc4b2a76b9719d911017c592",
"type": "invoice.normalised",
"business": { "id": "biz_2xJ4kQ9nVbT7mLpR3sYz", "external_id": "plateforme-cust-001842" },
"subject_type": "invoice",
"subject_id": "inv_2xJ4kQ9nVbT7mLpR3sYz",
"version": 2,
"occurred_at": "2026-11-05T08:12:58Z",
"position": 18342,
"data": { "id": "inv_2xJ4kQ9nVbT7mLpR3sYz", "normalisation_status": "normalised", "...": "les champs d'impression" }
}
],
"next_after": 18342,
"meta": { "request_id": "req_06" }
}

Comment le lire. Conservez la position du dernier événement traité. Appelez avec after=<cette position> ; gardez next_after (la dernière position renvoyée, ou after lui-même quand il n’y a rien de neuf). after absent ou égal à 0 part du plus ancien événement conservé. limit va de 1 à 1 000, 1 000 par défaut.

  • Ordre et trous. Les positions se suivent : after+1, after+2, etc., sans trou, par partenaire. Les événements arrivent dans l’ordre des positions. Une position est l’ordre dans lequel nous avons numéroté les événements, qui peut s’écarter un peu de occurred_at ; ne triez pas par occurred_at.
  • Conservation : 30 jours. Une facture reste lisible bien plus longtemps ; le flux, non.
  • Le même id peut revenir à une position ultérieure. Gardez le premier. L’id d’un événement est déterministe. Si nous rejouons un règlement après qu’il a été numéroté, il devient une nouvelle ligne à une nouvelle position, avec le même id. Dédoublonnez sur id.
  • Ordonnez par version pour un même sujet : invoice.pending a version 1 et un événement de règlement version 2. Si vous croisez un pending après le règlement, ignorez-le. Pour les événements qui ne concernent pas une facture, version est une date en millisecondes depuis 1970.
  • Un curseur en avance sur le flux (un after plus grand que la dernière position qui existe) répond 400 (details[0].field vaut after, et le message donne la dernière position). Lu comme « rien de neuf », un tel curseur ferait sauter tous les événements jusqu’à ce numéro : nous le refusons. Il vient en général d’un autre environnement.
  • Un curseur plus ancien que le flux répond 410 FEED_CURSOR_EXPIRED. error.params.resume_after donne la position de reprise, sous forme de nombre, et le message dit la même chose (reprenez depuis after=N) ; elle est toujours au-dessus du curseur que vous avez envoyé, donc la suivre ne peut pas tourner en rond. Une resynchronisation qui repart toujours de after=0 ne rencontre pas cette réponse : elle lit depuis la plus ancienne position conservée, avance donc elle aussi, et vous redonne les 30 jours. Ce que vous avez manqué entre les deux n’est plus dans le flux : relisez vos factures ouvertes avec GET …/invoices?from=&to= ou prenez un export.
  • Après une coupure du webhook : Ce qui s’est passé pendant qu’il était désactivé n’est pas envoyé : le flux sert de rattrapage. Lisez GET /events à partir de la dernière position traitée. En règle générale, prenez un webhook pour un « allez lire le flux », et faites votre travail à partir du flux.

Les types d’événements sont dans le catalogue des événements.