Erreurs et catalogue
Le JSON de problème et tous les codes du catalogue.
- Dans le bac à sable
En termes simples
Quand un appel échoue, la réponse indique si c’est la requête ou la facture qui est erronée. Pour une facture, un code nomme le champ dans l’export du client et indique qui le corrige. L’intégrateur corrige les requêtes et les données erronées ; nous corrigeons notre propre mapping et réessayons en cas d’échec côté canal.
Conseil
400 concerne le format de la requête. 422 concerne la facture, et son code du catalogue nomme le champ dans l’export ERP. Ne confondez pas les deux.
JSON de problème
Toute réponse d’erreur est un JSON de problème (RFC 9457) : type, title et status, avec detail quand il y a plus à dire. Un 422 ajoute errors, une liste de constats. Chacun comporte un code du catalogue, qui le corrige (who_fixes), un fix_hint et un message, ainsi qu’un field quand le constat porte sur un seul champ (voir la page 3.2). La ligne surlignée est le code.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/xml" \
-H "Idempotency-Key: order-2026-0051" \
--data-binary @not-an-invoice.xmlimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/xml")
.header("Idempotency-Key", "order-2026-0051")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("not-an-invoice.xml")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/xml',
'Idempotency-Key': 'order-2026-0051',
},
body: await readFile('not-an-invoice.xml'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/validation-failed",
"title": "The invoice did not pass the checks",
"errors": [
{
"code": "EI-XML-TYPE",
"fix_hint": "Send the invoice itself, in the format agreed for the route.",
"who_fixes": "erp",
"source": "XML-safety",
"message": "The file is not an invoice in a format this route accepts. Please send the invoice in the agreed format."
}
],
"status": 422
}Pour un chemin que le service ne connaît pas, la réponse est 404 avec {"detail": "Not Found"}, en JSON simple.
Ce que signifie chaque statut
| Statut | Signification | Ce que vous faites |
|---|---|---|
400 | La requête est illisible : pas du JSON, un champ erroné, ou l’en-tête Idempotency-Key absent ou ne comptant pas de 8 à 100 caractères. | Corrigez la requête. |
401 | Aucune clé, ou une clé inconnue. | Corrigez la clé. |
403 | La clé n’a pas la portée dont l’appel a besoin, ou l’appel vise les données d’un autre client (forbidden). | Utilisez une clé dotée de la portée, ou le bon client. |
404 | Cette facture, ce document, cette entrée du catalogue ou cet élément de suivi n’existe pas pour ce client. | Vérifiez l’identifiant. |
409 | L’en-tête Idempotency-Key a été utilisé avec un corps différent, ou sa première requête est encore en cours. Une annulation est arrivée trop tard. Un identifiant d’accès existe déjà ou a été révoqué. | Corrigez l’appel. |
413 | Le corps dépasse 5 Mo (payload-too-large). | Envoyez un fichier plus petit. |
415 | Le type de contenu n’est ni XML ni PDF, ou un corps PDF n’est pas un PDF. | Corrigez le type de contenu. |
422 | La facture a échoué à un contrôle. Rien n’a été mis en file d’attente. | Corrigez les constats marqués erp. Ceux marqués us relèvent de nous. |
429 | Trop de requêtes pour la clé. | Attendez le nombre de secondes indiqué dans Retry-After, puis réessayez. |
500 | La facture n’a pas pu être contrôlée. Quelque chose a échoué de notre côté. | Relancez le même appel avec la même clé. |
503 | Le service est occupé (busy), ou un appel à l’API des identifiants d’accès est arrivé sur un processus sans clé maîtresse définie. | Relancez le même appel après Retry-After secondes. |
Chaque 409 a son propre type de problème, sous https://eurinvoice.com/problems/ : idempotency-conflict, request-in-progress, already-submitted, send-in-progress, dead-letter, credential-exists et credential-revoked. Lisez le type, et non le title, pour les distinguer. Un 413 n’est pas enregistré sous la valeur de l’en-tête Idempotency-Key : la même clé peut donc être réutilisée avec un corps plus petit.
Un 429 est compté par client et par portée, avec Retry-After (voir limites). Après un 202, vous ne renvoyez jamais la facture. Les erreurs passagères côté réseau donnent lieu à de nouvelles tentatives selon notre calendrier, et un rejet définitif va sur la liste de suivi.
Qui agit
Chaque code du catalogue a un seul responsable.
| Responsable | De qui il s’agit |
|---|---|
erp | L’intégrateur : l’export ERP ou ses données de référence. |
us | eurinvoice : mapping, sérialiseur ou configuration. |
business | L’entreprise du vendeur, avec son acheteur ou son comptable. |
client | Le client, c’est-à-dire le vendeur : enregistrement, identifiants d’accès ou autorisation. |
buyer | Le côté acheteur. |
route | L’opérateur du canal, une administration, un point d’accès ou une plateforme : attendre et réessayer. |
L’intégrateur corrige 400, 401, 403, 409, 413 et 415. Un 422 contient des constats, et chacun indique qui le corrige : erp est l’intégrateur, us est eurinvoice.
Le catalogue
Le catalogue contient un code pour chaque constat. Cette page en montre un échantillon de douze, un ou deux par famille de règles. Tapez un code et appuyez sur Entrée pour y accéder. Avec une clé, GET /catalogue/{code} explique n’importe quel code (voir consulter le catalogue). Le catalogue complet est réservé aux intégrateurs : demandez-le avec l’accès au bac à sable.
12 codes
| Code | Qui agit | Ce qui ne va pas | Ce qu’il faut faire |
|---|---|---|---|
EI-ID-IBANNos contrôles, contrôle d’identifiant | Intégrateur | L’IBAN échoue à son contrôle mod-97. | Corrigez le compte bancaire dans les paramètres de la société. |
EI-SCHEMANos contrôles, schéma | eurinvoice | Le JSON de la facture ne correspond pas au modèle canonique : un champ absent ou inconnu, un type ou un code erroné, ou une règle de structure propre au canal. | Lisez le chemin JSON indiqué dans l’erreur et corrigez le mapping du client. |
EI-TOTALS-MISMATCHNos contrôles, pré-contrôle | Intégrateur | Les totaux envoyés par l’ERP (erp_totals) diffèrent des totaux calculés à partir des lignes : le document ne correspondrait donc pas à la comptabilité de l’ERP lui-même. | Trouvez l’écart (en général un arrondi par ligne plutôt que par document, ou une ligne de remise omise par l’export) et corrigez l’export ou le mapping. |
BR-CO-16EN 16931 et syntaxe, validateur du canal | eurinvoice | Le montant à payer (BT-115) n’est pas égal au total TTC (BT-112) moins le montant déjà payé (BT-113) plus l’arrondi (BT-114). | Nous calculons les totaux à partir des lignes : cette erreur n’apparaît donc que lorsque les totaux viennent de l’extérieur (un fichier transmis tel quel) ou ont été modifiés. Recalculez les totaux à partir des lignes et renvoyez. |
EI-XML-DTDEN 16931 et syntaxe, validateur du canal | Intégrateur | Le XML déclare un DOCTYPE. UBL, CII et FA(3) n’en utilisent jamais, et c’est par un DOCTYPE que des entités externes, des chargements de DTD distantes et des expansions d’entités s’introduisent dans un fichier (XXE). Le fichier est refusé avant qu’un validateur ou un canal ne le lise. | Exportez la facture sans la ligne DOCTYPE. Si l’ERP en ajoute une volontairement, signalez-le à l’éditeur de l’ERP : aucun format de facturation électronique ne l’utilise. |
EI-XML-SYNTAXEN 16931 et syntaxe, validateur du canal | Intégrateur | Le fichier n’est pas un XML bien formé : par exemple, il est tronqué, son encodage ne correspond pas à sa déclaration, ou un caractère comme & n’est pas échappé. Aucun validateur ne peut le lire. | Exportez à nouveau le fichier et ouvrez-le dans n’importe quel visualiseur XML. Cherchez un fichier tronqué, un encodage différent de la déclaration, ou un & non échappé. |
EI-XML-TYPEEN 16931 et syntaxe, validateur du canal | Intégrateur | Le XML est bien formé mais n’est pas une facture que nous validons : ni une Invoice ou une CreditNote UBL, ni une facture CII UN/CEFACT, ni une facture FA(3) KSeF (par exemple une Order UBL, ou un ancien fichier FA(2)). | Envoyez la facture elle-même, dans le format convenu pour le canal. |
EI-PEPPOL-NO-ROUTEPeppol, réponse du réseau, nécessite un réseau | Intégrateur | Le point d’accès n’a trouvé aucun destinataire pour l’identifiant de l’acheteur : l’acheteur n’est pas enregistré sur Peppol pour ce type de document. Définitif pour cet envoi. | Vérifiez l’identifiant Peppol de l’acheteur dans la fiche client de l’ERP par rapport à l’annuaire Peppol ; si l’acheteur n’est pas sur Peppol, convenez avec lui d’un autre moyen de transmission. |
PEPPOL-EN16931-R001Peppol, validateur du canal | eurinvoice | Le processus métier (BT-23) devrait être présent. Mustang l’a signalé comme une remarque sur notre fichier ZUGFeRD EN 16931, qui n’est pas un document Peppol. | Aucune action pour ZUGFeRD ; notre UBL Peppol écrit toujours le processus. |
BR-DE-5Allemagne, validateur du canal | Intégrateur | Le nom du contact du vendeur (BT-41) est absent. | Ajoutez une personne ou un service à contacter pour la facturation aux paramètres de la société. |
KSEF-440Pologne, réponse du réseau, nécessite un réseau | eurinvoice | KSeF détient déjà une facture avec le même NIP vendeur, le même type de facture (RodzajFaktury) et le même numéro (P_2) ; il conserve cette clé pendant 10 ans. La clé est le numéro, pas le fichier : en TEST, un autre fichier sous un numéro accepté a aussi reçu 440. La réponse donne le numéro KSeF et la session de la copie acceptée en premier. Un numéro que KSeF a rejeté (430 ou 450) n’est pas conservé et peut être réutilisé. | Ne renvoyez pas. Consignez le numéro KSeF d’origine indiqué dans la réponse et déclarez la facture comme acceptée sous ce numéro. |
BR-RO-001Roumanie, validateur du canal | eurinvoice | L’identifiant de spécification (BT-24) n’est pas la valeur CIUS-RO. | Définissez le profil ro-cius, qui écrit l’identifiant CIUS-RO 1.0.1. |