Si vous envoyez des e-factures à un client B2B allemand en 2026, le fichier est conforme ZUGFeRD ou il est rejeté à la réception. Même logique en France avec Factur-X. Le format est une enveloppe PDF/A-3 avec un EN 16931 CII XML joint ; le générer à partir de zéro n’est pas trivial, et le valider exige un moteur de référence.
En pratique, ce moteur est Mustang (mustangproject.org) : un projet Java open-source qui extrait le XML embarqué d’un PDF/A-3 et le valide contre EN 16931 Schematron. Mustang a le support le plus profond pour ZUGFeRD et Factur-X parmi les outils ouverts, et c’est ce que beaucoup de vérificateurs indépendants exécutent.
Cet article passe en revue les échecs que Mustang signale, et une manière plus rapide de le lancer.
Ce que Mustang vérifie réellement
Quand vous donnez un PDF Factur-X ou ZUGFeRD à Mustang, il fait à peu près ceci :
- Extraire le fichier embarqué. PDF/A-3 stocke les attachments dans le name tree
/EmbeddedFiles. Mustang cherche le nom canonique (factur-x.xmlpour Factur-X,zugferd-invoice.xmlpour ZUGFeRD 2.x) et lit les bytes. - Vérifier AFRelationship. Le fichier joint doit être déclaré
AFRelationship="Alternative"selon la baseline Factur-X / ZUGFeRD. Toute autre valeur (Source,Data,Supplement) échoue. - Vérifier le namespace XMP et la version. Factur-X 1.0 utilise
urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#. ZUGFeRD 2.x utiliseurn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#. Un namespace ou une version erronés échouent. - Parser le XML comme Cross-Industry Invoice (CII). Il doit être well-formed XML et commencer par le bon root element CII (
rsm:CrossIndustryInvoice). - Exécuter EN 16931 Schematron. C’est le cœur de la validation : environ 200 règles métier sur la sémantique des champs, les codes obligatoires, le calcul des totaux, la logique VAT, les identifiants de parties, etc.
Pass = la facture est acceptable pour tout système AP conforme EN 16931 dans l’UE. Fail = l’automatisation AP du client rejettera la facture à réception, et l’équipe AR recevra une exception manuelle.
Les cinq échecs les plus fréquents
Ils reviennent souvent côté Mustang dans validator quand les équipes testent leurs premières e-factures.
1. AFRelationship incorrect
ERROR: Embedded file factur-x.xml uses AFRelationship="Source",
expected "Alternative".
La spécification PDF autorise plusieurs relationship types pour les fichiers joints. Factur-X / ZUGFeRD exigent Alternative : le XML joint est une représentation alternative du contenu visible du PDF. Si votre générateur PDF utilise Data (valeur par défaut de nombreuses bibliothèques), Mustang échoue immédiatement. Le PDF visible se rend toujours correctement, mais le payload structuré n’est pas valable pour le système AP.
2. Namespace XMP incorrect ou absent
ERROR: XMP metadata missing fx:DocumentType or fx:DocumentFileName under
namespace urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#.
Le paquet XMP du PDF doit déclarer le profil Factur-X (MINIMUM, BASIC, EN 16931, EXTENDED) et le nom de fichier à rechercher. C’est facile à oublier quand on écrit le wrapper PDF/A-3 à la main ; l’endpoint /api/v1/e-invoice/render de gPdf émet ces champs automatiquement.
3. CII XML well-formed, mais EN 16931 Schematron échoue
ERROR: BR-CO-25 — In an invoice (BR-01) the
ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime is required when
ram:DocumentTypeCode is 380.
C’est la majorité des échecs réels. Le XML est syntaxiquement valide ; les règles métier échouent. Les règles EN 16931 Schematron ont des IDs stables (BR-01, BR-CO-25, etc.) que vous pouvez retrouver dans la spécification. Les fréquentes :
- BR-01 : la facture doit avoir un numéro unique.
- BR-04 : la facture doit avoir une date d’émission.
- BR-05 : la facture doit avoir un invoice type code.
- BR-CO-25 : payment terms requis quand le document type est “Commercial invoice”.
- BR-Z-01 : VAT category codes doit être l’un de
S,Z,E,AE,K,G,O,L,M.
Corrigez les données source, reconstruisez, puis revalidez.
4. Le wrapper PDF/A ne valide pas
INFO: CII XML extracted and validates against EN 16931.
ERROR: PDF/A-3b conformance check failed: missing Output Intent.
Ici, le contrôle XML de Mustang passe, mais l’enveloppe PDF/A-3 sous-jacente échoue. Cause fréquente : le XML est correct, mais la sortie est un PDF ordinaire plutôt qu’un PDF/A-3. Le fichier embarqué existe, mais les règles d’archivage ne sont pas satisfaites. Le validator de gpdf.com/validator/ le détecte en lançant veraPDF en parallèle : l’échec PDF/A-3 apparaît dans la colonne veraPDF tandis que Mustang indique XML pass.
5. Encoding / declaration mismatch
ERROR: XML declares <?xml version="1.0" encoding="UTF-8"?> but the
embedded byte stream is UTF-8 with BOM. Mustang strict mode rejects BOM.
Problème étonnamment courant lorsqu’un outil XML émet un UTF-8 BOM puis que les bytes sont embarqués raw. La correction : supprimer le BOM avant embedding. L’endpoint e-invoice de gPdf normalise cela.
Exécuter Mustang sans installer Java
Installer Java + Mustang CLI convient pour un contrôle ponctuel. Pour une vérification continue — chaque facture générée, chaque CI run qui affirme la conformité e-invoice — c’est une friction inutile.
gpdf.com/validator/ exécute Mustang dans le navigateur :
- Déposez le PDF Factur-X / ZUGFeRD dans la zone d’upload.
- Le validator extrait le XML embarqué et exécute le Schematron engine de Mustang (compilé en JavaScript / WebAssembly, exécuté dans Cloudflare Worker).
- Le rapport Mustang revient à côté du rapport PDF/A-3 de veraPDF, puisque les deux couches doivent passer.
- Téléchargez le rapport JSON comme preuve QA.
Pas de login. Pas de quota. Le même type de Mustang que vous installeriez via Maven, servi comme service public gratuit.
TL;DR
Mustang signale 5 failure modes fréquents ; la plupart reviennent à “le fichier a été généré par un outil qui n’émet pas un PDF/A-3 Factur-X / ZUGFeRD pleinement conforme”. L’E-invoice API de gPdf l’émet en un appel. validator vérifie le résultat avec Mustang + veraPDF en parallèle.
La plupart des bugs que Mustang attrape concernent le wrapper ou AFRelationship, pas seulement la sémantique XML. Générer correctement le fichier est déjà l’essentiel ; le validator est le reçu qui le prouve.