1. Aperçu

Le serveur fournit trois outils et une ressource que les agents IA peuvent appeler via le Model Context Protocol.

ScénarioOutil / Ressource
Vérifier une facture avant l'envoivalidate_invoice
Lire les données XML d'un PDF ZUGFeRDextract_xml
Vérifier que le PDF et le XML concordentcheck_consistency
Interroger les formats et jeux de règles disponiblesvalidation://rules
Toutes les réponses sont du JSON structuré. Pas de texte libre — chaque erreur contient l'ID de règle, le champ concerné, le message d'erreur, une suggestion de correction applicable et le XPath.

2. Architecture & flux de données

Agent IA │ │ Message MCP (JSON-RPC via stdio) ▼ ┌─────────────────────────────────────────┐ │ zugferd-mcp-client (npm, local) │ │ │ │ validate_invoice · extract_xml │ │ check_consistency │ │ │ │ │ Requête REST HTTPS │ │ ▼ │ │ API ZUGFeRD Validator (hébergée) │ │ api.zugferd-validator.de │ │ Auth: X-Api-Key │ │ │ │ │ Base64 → Mustang + KoSIT (parallèle) │ │ ▼ │ │ Parseur rapport + BdD corrections │ └─────────────────┬───────────────────────┘ │ JSON structuré ▼ L'agent IA reçoit le résultat

Déroulement pour validate_invoice

1
Le client MCP reçoit l'appel — fichier Base64 + paramètres de l'agent IA
2
Requête HTTPS vers l'API — POST /v1/validate avec l'en-tête X-Api-Key
3
Auth & limite de débit — l'API vérifie la clé, le quota hebdomadaire et la limite horaire ; au-delà de la limite horaire, l'appel passe dans la voie lente
4
Double validation (en parallèle) — Mustang CLI (ZUGFeRD/Factur-X) et l'outil de validation KoSIT (XRechnung + EN 16931 CII) s'exécutent en même temps (max. 30 s)
5
Consolidation des résultats — les erreurs des deux moteurs sont fusionnées et dédupliquées ; les suggestions de correction sont ajoutées
6
Résultat JSON — l'API répond, le client MCP transmet à l'agent IA

3. Moteurs de validation

Chaque requête est vérifiée par deux moteurs en même temps. Les résultats sont consolidés, dédupliqués, puis renvoyés.

MoteurVersionFormats couverts
Mustang Project v2.26.0 ZUGFeRD 1.0–2.4, Factur-X 1.0, XRechnung (général)
Outil de validation KoSIT v1.6.3 XRechnung 3.0.2 (CII + UBL), EN 16931 CII/UBL (brut), Factur-X 1.07.3 / 1.08 (tous les profils)
Réponse consolidée : les erreurs des deux moteurs apparaissent dans la même liste errors. Les doublons (même ID de règle + message) sont supprimés automatiquement. Les erreurs KoSIT ne sont retenues que si un scénario de validation adapté a été détecté — pour des GuidelineIDs inconnus, Mustang seul prend le relais.

4. Installation & configuration

1
Obtenir une clé API
# Kostenlos registrieren:
https://zugferd-validator.de/portal
2
Installer le client MCP
npm install -g zugferd-mcp-client
3
Configurer dans le client MCP
// mcp_config.json (je nach Client abweichender Pfad)
{
  "mcpServers": {
    "zugferd": {
      "command": "zugferd-mcp-client",
      "env": {
        "ZUGFERD_API_KEY": "zv_dein_key_hier"
      }
    }
  }
}

API REST directe

L'API peut aussi être appelée directement, sans client MCP :

# Beispiel: Validierung per curl
curl -X POST https://api.zugferd-validator.de/v1/validate \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: zv_dein_key_hier" \
  -d '{"file_content":"<base64>","file_type":"xml"}'

Variables d'environnement (client MCP)

VariableDescriptionDéfaut
ZUGFERD_API_KEYClé API du portail– (obligatoire)
ZUGFERD_API_URLURL de base de l'APIhttps://api.zugferd-validator.de

5. Outils

validate_invoice TOOL

Valide une facture électronique (PDF ZUGFeRD/Factur-X ou XML XRechnung) selon la norme EN 16931 et les extensions allemandes. Renvoie des erreurs, avertissements et suggestions de correction structurés.

Schéma d'entrée

file_content * string Contenu du fichier PDF ou XML encodé en Base64. Les préfixes data-URL (data:application/pdf;base64,…) sont retirés automatiquement.
file_type * enum "pdf" pour les PDF ZUGFeRD/Factur-X · "xml" pour les fichiers XML XRechnung/CII purs
profile enum? Indication de profil optionnelle. En cas d'écart avec le profil détecté, un warning avec rule_id: "PROFILE_MISMATCH" est généré.
Valeurs : minimum · basic_wl · basic · en16931 · extended · xrechnung

Schéma de sortie

{
  "valid":    true,
  "format":   "ZUGFeRD 2.x",
  "profile":  "EN16931",
  "container": "pdf",
  "syntax":   "CII",
  "summary":  "Keine Probleme gefunden",
  "errors":   [],
  "warnings": [],
  "notices":  [],
  "metadata": {
    "invoice_number": "RE-2026-001",
    "issue_date":     "2026-04-01",
    "seller":         "Musterfirma GmbH",
    "buyer":          "Beispiel AG",
    "total_amount":   "1190.00",
    "currency":       "EUR"
  }
}
{
  "valid":   false,
  "format":  "XRechnung 3.0",
  "profile": "XRECHNUNG",
  "summary": "1 Fehler, 1 Warnung gefunden",
  "errors": [
    {
      "severity":       "error",
      "rule_id":        "BR-DE-15",
      "field":          "BT-10",
      "message":        "Die Käuferreferenz / Leitweg-ID (BT-10) muss übermittelt werden.",
      "fix_suggestion": "Füge die Käuferreferenz / Leitweg-ID (BT-10) in 'ram:ApplicableHeaderTradeAgreement/ram:BuyerReference' ein.",
      "xpath":          "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"
    }
  ],
  "warnings": [
    {
      "severity":       "warning",
      "rule_id":        "BR-DE-17",
      "field":          "BT-3",
      "message":        "Mit dem Element \"Invoice type code\" (BT-3) sollen ausschließlich folgende Codes aus der Codeliste UNTDID 1001 übermittelt werden: 326, 380, 384, 389 …",
      "fix_suggestion": "Bei einer Vorschussrechnung (386) ist die Warnung hinnehmbar: XRechnung empfiehlt den Code nicht, lässt ihn aber zu. Wer sie vermeiden will, nimmt 326 (Teilrechnung).",
      "xpath":          "//rsm:ExchangedDocument/ram:TypeCode"
    }
  ]
}

Champs de sortie

ChampTypeObligatoireDescription
validbooleanOuitrue si aucune erreur n'a été trouvée
formatstringNonFormat détecté : "ZUGFeRD 2.x" ou "ZUGFeRD 1.0" pour un PDF, sinon p. ex. "XRechnung 3.0", "Peppol BIS Billing 3.0" ou "EN 16931" ; null si aucun XML n'est extractible
profilestringNonProfil détecté en majuscules, p. ex. "EN16931", "EXTENDED" ou "XRECHNUNG" ; null si aucun XML n'est extractible
containerstringNonpdf (PDF avec facture électronique intégrée) ou xml (fichier XML)
syntaxstringNonCII ou UBL
summarystringOuiRésumé lisible, p. ex. "2 Fehler, 1 Warnung gefunden"
errorsarrayOuiErreurs de validation — rendent la facture non valide
warningsarrayOuiAvertissements — la facture peut néanmoins être valide
noticesarrayNonRemarques informatives sans effet sur la validité
metadataobjectNonDonnées de facture extraites — présentes pour les PDF si le XML intégré a pu être lu, et toujours pour file_type: "xml"
extract_xml TOOL

Extrait le document XML intégré d'un PDF ZUGFeRD/Factur-X. Renvoie le contenu XML complet sous forme de chaîne, avec le format et le profil détectés.

Entrée

pdf_content * string Contenu du fichier PDF ZUGFeRD/Factur-X encodé en Base64.

Sortie

{
  "xml_content": "<?xml version='1.0' encoding='UTF-8'?>\n<rsm:CrossIndustryInvoice ...>...</rsm:CrossIndustryInvoice>",
  "format":      "ZUGFeRD 2.x",
  "profile":     "EN16931"
}
Le xml_content extrait peut être transmis directement (après encodage Base64) à validate_invoice avec file_type: "xml".
check_consistency TOOL

Vérifie que les données visibles par l'humain dans le PDF (numéro de facture, date, montant total) correspondent aux données machine stockées dans la pièce jointe XML. Révèle les manipulations ou erreurs de saisie.

Entrée

pdf_content * string Contenu du fichier PDF ZUGFeRD/Factur-X encodé en Base64.

Sortie

{
  "consistent":    true,
  "discrepancies": []
}
{
  "consistent":    false,
  "discrepancies": [
    {
      "field":     "total_amount",
      "pdf_value": "1190.00",
      "xml_value": "1180.00",
      "message":   "Gesamtbetrag im PDF ('1190.00') unterscheidet sich von dem im XML ('1180.00')."
    }
  ]
}

Champs vérifiés & tolérances

ChampMotif de détection dans le PDFTolérance
invoice_numberRechnungsnummer:, Rechnung Nr., Invoice No.Casse, espaces et tirets ignorés
issue_dateRechnungsdatum:, Datum:, Invoice Date:Aucune — les formats de date sont normalisés en ISO 8601
total_amountGesamtbetrag:, Rechnungsbetrag:, Total:±0,01 EUR (différences d'arrondi)
La reconnaissance de texte repose sur le texte PDF lisible par machine. Les PDF scannés sans couche OCR ne sont pas pris en charge.
create_invoice TOOL

Crée une facture électronique valide à partir de données structurées, au choix comme PDF ZUGFeRD (PDF/A-3 avec XML CII EN 16931 intégré) ou comme XML XRechnung pur (CII avec CIUS XRechnung 3.0 et Leitweg-ID pour le B2G). Plusieurs lignes, catégories de TVA S, Z, E, AE, K et G, débours sans TVA, remises et majorations, date ou période de prestation, montants déjà payés, références à des factures antérieures, pièces jointes, virement ou prélèvement SEPA. Sans état : rien n'est conservé, pièces jointes comprises. REST : POST /v1/create. Montants en centimes, date au format YYYY-MM-DD.

Entrée (extrait)

format *stringzugferd (PDF) ou xrechnung (XML)
document_typestringType de document (BT-3), défaut invoice : credit_note (avoir/annulation ; montants positifs, le PDF n'affiche alors pas de montant à payer), corrected (facture rectificative), self_billed (autofacturation), prepayment (facture d'acompte ; XRechnung émet pour 386 l'avertissement BR-DE-17, la facture reste valide), partial (facture partielle), debit_note (note de débit). En brut via type_code.
preceding_invoicesarrayRéférences à des factures antérieures (BG-3), par exemple des factures d'acompte : [{ number, date }], 20 au plus. Dans les deux formats, le XML ne contient que la première en BG-3, car le schéma de l'EN 16931 n'en admet qu'une ; la note (BT-22) cite toutes les autres.
preceding_invoiceobjectForme courte pour une seule référence { number, date } (BT-25/26), par exemple pour un avoir. Pas en même temps que preceding_invoices.
number, date *stringNuméro et date du document (YYYY-MM-DD)
sellerobjectVendeur (name, street, zip, city, country, vat_id, tax_number, email, phone, contact_name). Obligatoire sans profil d'émetteur ; si seller manque, nous reprenons le profil d'émetteur de votre compte.
seller.tax_numberstringNuméro fiscal allemand (Steuernummer, BT-32), si vous n'avez pas de numéro de TVA. Sans numéro de TVA, nous l'écrivons aussi comme identifiant du vendeur (BT-29), car l'EN 16931 exige un tel identifiant (BR-CO-26).
buyer *objectAcheteur (name, street, zip, city, country, vat_id, email …)
lines *arrayLignes : name, quantity, unit_net_price_cents, vat_category, vat_rate, pass_through. vat_category : défaut S ; Z = 0 %, E = exonéré, AE = autoliquidation, K = livraison intracommunautaire, G = exportation.
lines[].pass_throughbooleantrue = débours sans TVA (durchlaufender Posten, § 10, al. 1 UStG) : vat_rate: 0, vat_category omis ou E. Dans le XML, catégorie E avec motif et code VATEX-EU-79-C. Pas en même temps que d'autres lignes de catégorie E (BR-E-01). Dans le XML, le débours compte dans le total HT (BT-109), mais pas dans la TVA, comme l'exige l'EN 16931. Si votre propre facture affiche le total HT sans lui, les deux montants diffèrent ; le total TTC concorde.
delivery_date, billing_periodstring, objectDate de prestation (BT-72) ou période de prestation (BG-14), la période sous la forme { start, end }, la fin pas avant le début. Avec une période et sans date de prestation, nous fixons BT-72 à la fin de la période. Pour une facture d'acompte (prepayment) sans l'une ni l'autre, nous omettons BT-72 ; la vérification ZUGFeRD émet alors un avertissement (PEPPOL-EN16931-R008), c'est normal. Sinon, la date de facture s'applique.
prepaid_amount_cents, prepaid_vat_centsintegerMontant déjà payé, par exemple un acompte, TTC en centimes (BT-113). Nous le déduisons du montant à payer (BR-CO-16) ; il ne peut pas dépasser le total de la facture. Nous ajoutons une note (BT-22) avec la déduction et les références ; avec prepaid_vat_cents, elle indique aussi le montant HT et la TVA de la déduction, comme l'exige le droit allemand (§ 14, al. 5 UStG) pour les factures finales.
allowances_chargesarrayRemises/majorations au niveau du document
buyer_referencestringLeitweg-ID (BT-10) — obligatoire pour xrechnung
payment_terms, due_date, payment_meansstring/objectConditions de paiement, échéance, IBAN/BIC
direct_debitobjectPrélèvement SEPA : mandate_reference (BT-89), creditor_id (BT-90, sinon repris du profil d'émetteur), debtor_iban (BT-91). Fixe le moyen de paiement 59. Pour ZUGFeRD, l'IBAN peut être masqué (DE89**************3000), pour XRechnung non. Nous n'écrivons alors pas de compte bénéficiaire (BR-DE-25-b). Si vous envoyez direct_debit, les trois sont nécessaires ; omettez alors payment_means.type_code ou mettez 59.
attachmentsarrayPièces jointes (BG-24) : [{ filename, content_base64, description? }]. Sont admis PDF, PNG, JPEG, CSV, XLSX et ODS (BR-CL-24), 10 fichiers au plus, 5 Mo au plus au total. Les noms de fichier doivent être uniques. À partir de deux pièces jointes, la vérification émet l'avertissement CII-SR-476 (avec deux descriptions aussi CII-SR-475) ; la règle compte toutes les pièces jointes ensemble, la facture reste valide. Via MCP, la réponse d'une facture ZUGFeRD avec pièces jointes ne contient que pdf_base64 ; le XML est dans le PDF.
seller_logostringLogo en Base64 (PNG/JPG) — uniquement Automatiser/Scaler
self_checkbooleanVérifier immédiatement selon EN 16931 (plus lent). Défaut false.

Sortie

{
  "format":     "zugferd",
  "profile":    "EN16931",
  "pdf_base64": "JVBERi0xLjc…",
  "xml":        "<?xml version=\"1.0\"…",
  "branding":   "free_footer"
}

xml est toujours joint, sauf via MCP pour une facture ZUGFeRD avec pièces jointes. extract_xml le tire alors du PDF.

Pièces jointes

Les pièces jointes figurent seulement dans le XML de la facture électronique (BT-125), pas en plus comme pièce jointe du PDF. Chaque fichier fait 5 Mo au plus, et tous ensemble 5 Mo au plus aussi, mesurés après décodage. Nous lisons le type à l'extension (.pdf, .png, .jpg, .jpeg, .csv, .xlsx, .ods) et le vérifions sur les premiers octets du fichier ; s'ils ne concordent pas, vous recevez 400. Un nom de fichier a jusqu'à 100 caractères, sans / ni \ et sans point au début ; deux noms qui ne diffèrent que par les majuscules et minuscules comptent comme identiques. description (BT-123) a 200 caractères au plus. content_base64 contient du Base64 pur ; nous retirons un préfixe data:…;base64,. Le Base64 grossit les fichiers d'un tiers : 5 Mo de pièces jointes donnent environ 7 Mo dans la requête, et la réponse les contient encore une fois dans la facture. Via MCP, envoyez donc de préférence de petites pièces jointes.

Profil d'émetteur

Ce qui manque dans la requête, nous le complétons à partir du profil d'émetteur de votre compte : tout le vendeur si seller manque (son numéro fiscal seulement si le profil n'a pas de numéro de TVA), ainsi que l'IBAN, le BIC, le titulaire du compte, les conditions de paiement, le logo et, pour un prélèvement, l'identifiant créancier. Ce que contient la requête l'emporte toujours. Vous gérez le profil dans votre compte ou via l'API : GET /v1/keys/issuer le lit, PUT /v1/keys/issuer l'enregistre, DELETE /v1/keys/issuer le supprime. Champs : name, street, zip, city, country, vat_id, tax_number, email, phone, contact_name, iban, bic, account_name, payment_terms, logo_b64, creditor_id. PUT ne modifie que les champs présents dans la requête ; une chaîne vide ou null efface un champ. PUT refuse avec 400 un numéro de TVA sans code pays, un numéro fiscal de forme incorrecte et un identifiant créancier invalide.

Erreurs

Nous répondons à une entrée invalide par 400 et { "error": "Ungültige Eingabe", "details": "…" }. Les erreurs de schéma indiquent le chemin et la raison, plusieurs séparées par des points-virgules. Les problèmes de contenu, comme un prélèvement sans référence de mandat, figurent en phrases entières dans details (en allemand), plusieurs séparées par des espaces. Une date qui n'a pas la forme YYYY-MM-DD nomme son champ, par exemple preceding_invoices[0].date (compté à partir de 0). Via MCP, les problèmes de contenu et les dates reviennent sous la forme du même objet. Les erreurs de schéma sont interceptées plus tôt par le protocole MCP lui-même : vous recevez une erreur d'outil (isError: true) avec le texte de la vérification du schéma, pas un objet avec error et details.

Self-check découplé : par défaut, la facture est renvoyée immédiatement. La preuve de conformité s'obtient dans un second temps via validate_invoice sur le pdf_base64 ou le xml renvoyé, ou en réglant self_check: true pour un aller-retour unique. Le serveur détermine le branding selon le forfait (pied de page sur le forfait Gratuit, white-label à partir d'Automatiser). Quota propre pour la création : Gratuit 1 facture par mois ; Automatiser et Scaler illimités, usage raisonnable via la limite horaire.
Clé sandbox (zv_test_…, via GET /v1/keys/me) : pour intégrer librement sans entamer le quota réel. Les factures créées portent un filigrane « DEMO » en mosaïque sur chaque page plus un marqueur XML — entièrement testables, mais sans valeur comme véritable facture. 100/jour, 3/minute ; comptées séparément du quota réel.
POST /v1/view REST

Afficher une facture sous forme lisible. Transforme une XRechnung (UBL ou CII), une facture CII ou un PDF Factur-X/ZUGFeRD en affichage lisible. Il repose sur la visualisation de la KoSIT (Apache 2.0), dans la version fournie avec Mustang 2.26.0. Aucune clé nécessaire ; l'affichage ne compte pas dans le quota de contrôles mais a sa propre limite journalière : 20 par adresse IP sans compte, 50 avec l'offre gratuite, 500 avec Automatiser, 2 000 avec Scaler (sinon 429). Rien n'est enregistré ni journalisé. Comme outil MCP : view_invoice.

Champs

file_content *Fichier en Base64, 15 Mo au maximum (sinon 413)
file_type *"pdf" ou "xml"
languagede, en ou fr, par défaut de
checkContrôler aussi le fichier, par défaut true (false via MCP)

Réponse : readable, html, format, profile, syntax, attachments (nom, type, taille, Base64), check (valide, nombre d'erreurs et d'avertissements, premiers messages) et limit. Le HTML est nettoyé : pas de script, pas de gestionnaires d'événements, pas de liens avec cible, pas d'images ni de formulaires, plus une Content Security Policy. Affichez-le tout de même uniquement dans un <iframe sandbox> sans droits, et enregistrez les pièces jointes comme fichiers au lieu de les ouvrir dans le navigateur. Si le fichier ne peut pas être affiché, readable vaut false et check en donne la raison ; un PDF sans facture électronique donne 422.

GET /v1/leitweg/check REST

Vérifier un Leitweg-ID. Vérifie la structure, le code (Land 01 à 16, État fédéral 99) et les chiffres de contrôle (modulo 97-10) selon la spécification de format 2.0.2 de la KoSIT. Si les chiffres de contrôle sont faux ou manquent, la réponse donne l'identifiant correspondant dans corrected_id. Elle ne dit pas si l'identifiant est attribué ; il n'existe pas d'annuaire public. Sans clé, sans quota, 120 appels par minute au plus (sinon 429). Rien n'est enregistré. Outil MCP : check_leitweg_id.

Champs

id *Le Leitweg-ID, 200 caractères au plus
languagede, en ou fr, par défaut de

Réponse (200, aussi pour un identifiant invalide) : valid, leitweg_id (forme normalisée), parts (coarse, fine, check_digits), region, expected_check_digits, corrected_id, errors et warnings (chacun code et message), notice. Faites confirmer un identifiant proposé par le donneur d'ordre avant de l'utiliser.

POST /v1/stapel REST

Contrôle par lot sur le serveur. Pour de nombreuses factures à la fois, sans que votre programme ou navigateur reste connecté tout le temps : téléverser les fichiers, lancer, récupérer les résultats plus tard. À partir de l'offre Automatiser. Les factures restent chiffrées sur notre serveur en Allemagne jusqu'au contrôle et sont supprimées juste après. Les résultats restent sept jours, puis nous les supprimons. Quand tout est terminé, un e-mail part à l'adresse du compte. Dans un compte d'entreprise, le titulaire peut désactiver cette option pour les autres accès (PATCH /v1/org/settings avec { "stapel_ablage": false }).

Appels

POST /v1/stapelCréer un lot. Corps { sprache?: "de" | "en" | "fr" } (langue de l'e-mail). Réponse 201 avec { id, max_dateien, max_bytes }. Au maximum 3 lots ouverts par clé.
POST /v1/stapel/{id}/dateienUn fichier : { name, file_type: "pdf" | "xml", file_content } (Base64, 15 Mo au maximum). Au maximum 500 fichiers par lot.
POST /v1/stapel/{id}/startTéléversement terminé, le contrôle commence. Un lot jamais lancé est supprimé après deux heures.
GET /v1/stapel/{id}?seit=…État : status (hochladen = téléversement, wartend = en attente, fertig = terminé, angehalten = arrêté), anzahl, fertig, ok, mit_fehlern, neu, grund, ablauf. ergebnisse contient les résultats comme pour validate_invoice, avec nr et reference (nom du fichier). Avec seit=0, vous recevez tout et la liste namen ; ensuite passez le dernier stand comme seit pour ne recevoir que les nouveaux (le dernier peut revenir deux fois).
GET /v1/stapelVos lots.
DELETE /v1/stapel/{id}Supprimer tout de suite, avec tous les fichiers et résultats.

Chaque fichier compte dans le quota hebdomadaire. S'il est épuisé, le lot s'arrête (status: "angehalten", grund: "kontingent") ; les fichiers restants ne sont pas contrôlés et sont supprimés. Le serveur traite ces lots uniquement sur les places libres à ce moment ; les contrôles directs passent en premier.

validation_report TOOL

Renvoie le résultat du contrôle sous forme de rapport de validation au format PDF/A-3b, prêt à archiver et à transmettre. Le rapport indique le résultat, chaque message avec son identifiant de règle et son champ, la date du contrôle, le format et le profil reconnus, l’empreinte SHA-256 du fichier contrôlé et le jeu de règles, c’est-à-dire les versions des outils utilisés. Chaque appel effectue un nouveau contrôle et compte dans le quota hebdomadaire comme une validation. Disponible comme outil MCP validation_report et via REST avec POST /v1/report.

Entrée

file_content *stringContenu de la facture en base64
file_type *stringpdf ou xml
attach_sourcebooleanJoindre la facture contrôlée de façon visible : pour un PDF, ses pages sont ajoutées après le rapport ; pour un XML, le contenu est imprimé. Le fichier est en outre incorporé sans modification (PDF/A-3, AFRelationship /Source) pour rester lisible par machine. Par défaut false.
langstringde, en, fr — par défaut de
file_namestringNom de fichier affiché dans le rapport. Par défaut rechnung.pdf ou rechnung.xml.

Sortie

Content-Type: application/pdf
Content-Disposition: attachment; filename="rapport-validation-facture.pdf"
X-Validation-Result: valid | invalid

Exemple

curl -X POST https://api.zugferd-validator.de/v1/report \
  -H "X-Api-Key: $ZV_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"file_content\": \"$(base64 -w0 rechnung.pdf)\", \"file_type\": \"pdf\", \"attach_source\": true}" \
  -o bericht.pdf
Rien n’est conservé. Le fichier est contrôlé pour l’appel puis supprimé ; pour pouvoir rapprocher plus tard le rapport et la facture archivée, l’empreinte SHA-256 figure dans le rapport. Le rapport n’est pas une attestation juridiquement contraignante : il documente un contrôle technique à une date donnée selon un jeu de règles nommé, et il ne remplace pas la conservation de la facture dans son format d’origine.
À partir de l’offre Automatiser, clés bac à sable comprises. Dans l’offre gratuite, le point d’entrée répond 403 ; un exemple de rapport filigrané est accessible sans clé via GET /v1/report/sample?lang=de|en|fr.

6. Ressource : validation_rules

Renvoie l'ensemble de règles actuel du serveur : formats et profils pris en charge, ainsi que le moteur de validation utilisé.

URI : validation://rules

{
  "supported_formats": [
    "ZUGFeRD 1.0", "ZUGFeRD 2.0", "ZUGFeRD 2.1", "ZUGFeRD 2.2",
    "ZUGFeRD 2.3", "ZUGFeRD 2.x / Factur-X 1.0x",
    "XRechnung 1.2", "XRechnung 2.0", "XRechnung 2.3", "XRechnung 3.0"
  ],
  "supported_profiles": [
    "minimum", "basic_wl", "basic", "en16931", "extended", "xrechnung"
  ],
  "validation_engines": [
    "Mustang Project v2.26.0",
    "KoSIT Validierungstool v1.6.3 (XRechnung 3.0.2 + EN 16931 CII)"
  ],
  "last_updated":      "2026-04-08"
}

7. Gestion des erreurs

En cas d'erreur, tous les outils renvoient un objet JSON avec un champ error. Via MCP, il y a une exception : si l'entrée ne correspond pas au schéma de l'outil (mauvais type, champ obligatoire manquant, valeur hors liste), le protocole MCP le signale lui-même par une erreur d'outil (isError: true) avec le texte de la vérification du schéma, et non par un objet JSON.

{
  "error":   "Kurze Fehlerkategorie",
  "details": "Ausführliche Beschreibung mit konkretem Hinweis zur Behebung."
}
errorDéclencheur
"Fehlender Parameter"Champ obligatoire non transmis
"Ungültiger Parameter"Valeur incorrecte pour file_type
"Ungültiger Base64-Input"Chaîne Base64 non valide transmise
"Validierungsfehler"Mustang CLI n'a pas pu démarrer (p. ex. Java absent) ou timeout après 30 s
"XML-Extraktion fehlgeschlagen"Aucun fichier XML trouvé dans la pièce jointe du PDF (pour extract / consistency). Pour validate, un notice avec rule_id: "NO_EMBEDDED_XML" est renvoyé à la place et valid: true est défini
"PDF-Lesefehler"Le PDF ne peut pas être lu
"XML-Parsing-Fehler"Le XML extrait n'est pas un XML valide
"Interner Fehler"Erreur d'exécution inattendue
Timeout : les deux moteurs de validation s'exécutent en parallèle et sont interrompus après 30 secondes chacun. Si Mustang échoue, "error": "Validierungsfehler" est renvoyé. Un timeout de KoSIT est ignoré en silence — les résultats de Mustang sont conservés.

8. Types de données communs

ValidationIssue

Utilisé dans les tableaux errors, warnings et notices de validate_invoice.

ChampTypeObligatoireDescription
severity"error" | "warning" | "notice"OuiNiveau de gravité du constat
rule_idstringOuiID de règle, p. ex. "BR-DE-1", "BR-CL-10". Valeur "UNKNOWN" pour les violations de schéma XSD (KoSIT) ou lorsqu'aucune ID de règle n'a pu être déterminée
fieldstringNonChamp BT concerné, p. ex. "BT-10"
messagestringOuiMessage d'erreur (en allemand)
fix_suggestionstringNonConseil de correction concret avec exemple XML
xpathstringNonXPath vers l'élément XML concerné
scope"xrechnung" | "peppol"NonUniquement sur les remarques d'une facture reconnue qui n'est pas une XRechnung (BT-24 sans l'identifiant xrechnung), par exemple ZUGFeRD ou Factur-X. "xrechnung" pour les règles BR-DE-… : elles ne s'appliquent que si votre destinataire exige une XRechnung, par exemple une administration allemande. "peppol" pour les règles PEPPOL-… : elles ne s'appliquent qu'à l'envoi par le réseau Peppol. Absent sur les erreurs, les avertissements et les autres remarques.

InvoiceMetadata

Champ optionnel dans le résultat de validate_invoice (uniquement pour file_type: "xml").

ChampTypeDescription
invoice_numberstring?Numéro de facture (BT-1)
issue_datestring?Date de facture ISO 8601, p. ex. "2026-04-01"
sellerstring?Nom du vendeur (BT-27)
buyerstring?Nom de l'acheteur (BT-44)
total_amountstring?Montant total sous forme de chaîne décimale, p. ex. "1190.00"
currencystring?Code devise ISO 4217, p. ex. "EUR"

9. Formats & profils pris en charge

Formats

FormatStandardRemarque
ZUGFeRD 1.0ZUGFeRD 1.0 / GEFEGVersion plus ancienne, prise en charge des profils limitée
ZUGFeRD 2.0FeRD 2.0Première version basée sur CII
ZUGFeRD 2.1Factur-X 1.0 (FR)Techniquement identique à Factur-X 1.0
ZUGFeRD 2.2Factur-X 1.0.05Corrections mineures
ZUGFeRD 2.3Factur-X 1.0.06Version antérieure à 2.4
ZUGFeRD 2.x / Factur-X 1.0xEN 16931 + D16BVersion principale actuelle (2026) — l'API renvoie "ZUGFeRD 2.x"
XRechnung 1.2XRechnung 1.2Version XRechnung plus ancienne
XRechnung 2.xXRechnung 2.0–2.3Différentes versions intermédiaires
XRechnung 3.0XRechnung 3.0Version XRechnung actuelle

Profils (ZUGFeRD/Factur-X)

ID de profilNom affichéUsage typique
minimumMINIMUMTraitement machine simple
basic_wlBASIC-WLSans détail des lignes
basicBASICFactures standard
en16931EN 16931 (COMFORT)Donneurs d'ordre publics, PEPPOL
extendedEXTENDEDProcessus B2B complexes
xrechnungXRECHNUNGAdministration publique allemande

10. Règles & suggestions de correction

Le serveur contient une base de suggestions de correction pour 160 catégories de règles. Les erreurs des deux moteurs de validation (Mustang + KoSIT) sont consolidées — lorsqu'une ID de règle connue est trouvée, la suggestion de correction est ajoutée automatiquement.

rule_id donne la règle en majuscules et sans zéro initial : BR-6 au lieu de BR-06, BR-DE-25-B au lieu de BR-DE-25-b. Quand XRechnung scinde une règle en deux, l'identifiant complet est indiqué. Les identifiants de champ comme BT-89 ne sont jamais une ID de règle.

Règles BR-DE 32 règles

Extensions allemandes, obligatoires pour les factures conformes à XRechnung. État XRechnung 3.0.2 ; les avertissements et notes ne rendent pas la facture invalide.

ID de règleChampDescription courte
BR-DE-1BG-16PAYMENT INSTRUCTIONS (BG-16) manquantes
BR-DE-2BG-6Contact vendeur (BG-6)
BR-DE-3BT-37Ville du vendeur (BT-37)
BR-DE-4BT-38Code postal du vendeur (BT-38)
BR-DE-5BT-41Interlocuteur du vendeur (BT-41)
BR-DE-6BT-42Numéro de téléphone du vendeur (BT-42)
BR-DE-7BT-43E-mail du vendeur (BT-43)
BR-DE-8BT-52Ville de l'acheteur (BT-52)
BR-DE-9BT-53Code postal de l'acheteur (BT-53)
BR-DE-10BT-77Ville de livraison (BT-77)
BR-DE-11BT-78Code postal de livraison (BT-78)
BR-DE-12–supprimée dans la version XRechnung actuelle
BR-DE-13–supprimée dans la version XRechnung actuelle
BR-DE-14BT-119Taux de TVA (BT-119)
BR-DE-15BT-10Référence acheteur / Leitweg-ID (BT-10)
BR-DE-16BT-31Numéro de TVA / numéro fiscal du vendeur
BR-DE-17BT-3Type de facture que XRechnung ne recommande pas, par exemple 386 (avertissement)
BR-DE-18BT-20Informations d'escompte (BT-20) au mauvais format
BR-DE-19BT-84IBAN du bénéficiaire invalide pour un virement (58) (avertissement)
BR-DE-20BT-91IBAN du payeur invalide pour un prélèvement (59) (avertissement)
BR-DE-21BT-24Specification identifier (BT-24) non conforme à XRechnung (avertissement)
BR-DE-22BT-125Noms de fichiers joints non uniques
BR-DE-23-ABG-17Virement (30, 58) sans coordonnées du compte
BR-DE-23-BBT-81Virement (30, 58) avec carte ou prélèvement
BR-DE-24-ABG-18Paiement par carte (48, 54, 55) sans données de carte
BR-DE-24-BBT-81Paiement par carte avec compte ou prélèvement
BR-DE-25-ABG-19Prélèvement (59) sans données de prélèvement
BR-DE-25-BBT-81Prélèvement (59) avec compte bénéficiaire ou carte
BR-DE-26BT-3Facture rectificative (384) sans référence à la facture antérieure (avertissement)
BR-DE-27BT-42Téléphone avec moins de trois chiffres (avertissement)
BR-DE-28BT-43Adresse e-mail de forme incorrecte (avertissement)
BR-DE-30BT-90Prélèvement sans identifiant créancier
BR-DE-31BT-91Prélèvement sans IBAN du payeur
BR-DE-TMP-32BT-72Aucune date de livraison ou de prestation (note)

Règles fondamentales EN 16931 (BR-*) 10 règles

ID de règleChampDescription courte
BR-1BT-24Specification identifier (BT-24)
BR-2BT-1Numéro de facture (BT-1)
BR-3BT-2Date de facture (BT-2)
BR-4BT-3Code de type de facture (BT-3)
BR-5BT-5Code devise (BT-5)
BR-6BT-27Nom du vendeur (BT-27)
BR-7BT-44Nom de l'acheteur (BT-44)
BR-8BG-5Adresse postale du vendeur (BG-5)
BR-9BG-5Code pays du vendeur (BT-40)
BR-10BG-8Adresse postale de l'acheteur (BG-8)

Règles de calcul (BR-CO-*) & règles de listes de codes (BR-CL-*) 8 règles

ID de règleDescription courte
BR-CO-3La date de taxe et le code de date de taxe s'excluent mutuellement
BR-CO-9Numéro de TVA du vendeur sans préfixe pays
BR-CO-10La somme des montants nets des lignes est incorrecte
BR-CO-13Montant total hors TVA mal calculé
BR-CL-10schemeID non valide (pas issue d'ISO 6523)
BR-CL-16Code de moyen de paiement non valide (pas issu d'UNTDID 4461)
BR-CL-17Catégorie de TVA non valide dans une remise ou majoration au niveau du document (en UBL aussi dans la ventilation de TVA)
BR-CL-18Catégorie de TVA non valide au niveau de la ligne (en CII aussi dans la ventilation de TVA)

Règles de catégorie de taxe (BR-S/Z/E/AE-*) 4 règles

ID de règleDescription courte
BR-S-1Taux normal (S) sans ventilation de TVA de catégorie S
BR-Z-1Taux zéro (Z) : exactement une ventilation de TVA de catégorie Z
BR-E-1Exonéré (E) : exactement une ventilation de TVA de catégorie E, donc un seul motif de 0 % par facture
BR-AE-1Autoliquidation (AE) : exactement une ventilation de TVA de catégorie AE

11. Exemples d'utilisation

Exemple 1 : valider un XML XRechnung

{
  "tool": "validate_invoice",
  "arguments": {
    "file_content": "PD94bWwgdmVyc2lvbj0iMS4wIj8+...",
    "file_type":   "xml",
    "profile":     "xrechnung"
  }
}
{
  "valid":   true,
  "format":  "XRechnung 3.0",
  "profile": "XRECHNUNG",
  "summary": "Keine Probleme gefunden",
  "errors":  [],
  "warnings": [],
  "metadata": {
    "invoice_number": "INV-2026-0042",
    "issue_date":     "2026-04-07",
    "seller":         "Tech GmbH",
    "buyer":          "Bundesbehörde X",
    "total_amount":   "5950.00",
    "currency":       "EUR"
  }
}

Exemple 2 : facture erronée avec suggestion de correction

{
  "tool": "validate_invoice",
  "arguments": {
    "file_content": "JVBERi0xLjQK...",
    "file_type":   "pdf"
  }
}
{
  "valid":   false,
  "format":  "ZUGFeRD 2.x",
  "profile": "EN16931",
  "summary": "1 Fehler gefunden",
  "errors": [{
    "severity":       "error",
    "rule_id":        "BR-DE-15",
    "field":          "BT-10",
    "message":        "Käuferreferenz (BT-10) muss für XRechnung angegeben werden.",
    "fix_suggestion": "Füge 'ram:BuyerReference' hinzu, z.B. '04011000-1234-34' für Behörden.",
    "xpath":          "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"
  }],
  "warnings": []
}

Exemple 3 : extraire et valider le XML

// Schritt 1 — XML aus PDF extrahieren
{ "tool": "extract_xml", "arguments": { "pdf_content": "JVBERi0x..." } }

// Schritt 2 — Extrahiertes XML validieren (base64-kodiert übergeben)
{ "tool": "validate_invoice", "arguments": { "file_content": "<base64 des xml_content>", "file_type": "xml" } }

Exemple 4 : contrôle de cohérence

{
  "tool": "check_consistency",
  "arguments": { "pdf_content": "JVBERi0xLjQK..." }
}
{
  "consistent":    false,
  "discrepancies": [{
    "field":     "total_amount",
    "pdf_value": "1190.00",
    "xml_value": "1180.00",
    "message":   "Gesamtbetrag im PDF ('1190.00') unterscheidet sich von dem im XML ('1180.00')."
  }]
}

Exemple 3 : PDF simple sans XML intégré

Une facture PDF classique sans pièce jointe ZUGFeRD/Factur-X renvoie valid: true avec un notice informatif — pas d'erreur, mais une indication qu'aucune donnée structurée n'a pu être vérifiée.

{
  "tool": "validate_invoice",
  "arguments": {
    "file_content": "JVBERi0xLjQK...",
    "file_type":   "pdf"
  }
}
{
  "valid":    true,
  "format":   null,
  "profile":  null,
  "summary":  "2 Hinweise gefunden",
  "errors":   [],
  "warnings": [],
  "notices": [
    {
      "severity": "notice",
      "rule_id":  "UNKNOWN",
      "message":  "XML could not be extracted"
    },
    {
      "severity": "notice",
      "rule_id":  "NO_EMBEDDED_XML",
      "message":  "Kein eingebettetes XML gefunden. Die PDF ist möglicherweise keine ZUGFeRD/Factur-X Rechnung."
    }
  ]
}

12. Limites & restrictions connues

RestrictionDétails
TimeoutMustang CLI est interrompu côté serveur après 30 secondes. Les fichiers très volumineux ou corrompus peuvent déclencher ce timeout.
Limite de débitValidation : Gratuit 20/semaine · Automatiser 500/semaine · Scaler illimité. Création (quota propre) : Gratuit 1 par mois · Automatiser et Scaler illimités, usage raisonnable via la limite horaire. Création sandbox : 100/jour, max. 3/minute. En cas de dépassement : HTTP 429.
DébitAutomatiser tourne à pleine vitesse jusqu'à 60 appels par heure, Scaler jusqu'à 300. Au-delà, rien n'est bloqué : les appels suivants passent dans une voie lente et n'obtiennent que les places libres à ce moment. Si le serveur est plein, il répond après au plus 20 secondes d'attente avec HTTP 503, Retry-After: 15 et slow_lane: true. Votre programme renvoie alors simplement la facture. Le quota hebdomadaire reste valable.
OCR des PDFcheck_consistency n'analyse que le texte PDF lisible par machine. Les PDF scannés sans couche OCR ne sont pas pris en charge.
Métadonnées pour les PDFvalidate_invoice extrait aussi les métadonnées des PDF, à condition qu'un XML intégré soit présent et lisible. Pour les PDF simples sans XML, ce champ est absent.
Contrôle de cohérenceSeuls trois champs sont comparés (numéro, date, montant). Les adresses, numéros fiscaux et détails de lignes ne sont pas confrontés.
ID de règle inconnuesSi une ID de règle manque dans la base de suggestions, fix_suggestion reste vide. Le message est renvoyé malgré tout.
Taille de fichierAPI hébergée : une requête peut peser au plus 50 Mo en JSON, sinon vous recevez 413. Le Base64 grossit les fichiers d'un tiers, donc environ 35 Mo de fichiers tiennent dans une requête. Dans le contrôle par lot (/v1/stapel), chaque fichier fait au plus 15 Mo. Le serveur MCP auto-hébergé n'a pas de limite fixe, mais Mustang s'arrête après 30 secondes ; les très gros PDF n'y arrivent peut-être pas.
Pièces jointesÀ la création d'une facture, 10 pièces jointes au plus, chacune et toutes ensemble 5 Mo au plus, mesurés après décodage. À partir de deux pièces jointes, la vérification émet l'avertissement CII-SR-476 ; la facture reste valide.

13. Journal des modifications

Novembre 2026 : quand une remarque s'applique

  • Nouveau : sur une facture qui n'est pas une XRechnung, les remarques des règles BR-DE-… et PEPPOL-… portent le champ scope ("xrechnung" ou "peppol"). Il indique quand la remarque s'applique. Le rapport PDF et le validateur du site l'affichent sous le message. Les autres champs restent inchangés.

Octobre 2026 : numéro fiscal, prélèvement et pièces jointes

  • Nouveau dans create_invoice / POST /v1/create : numéro fiscal allemand au lieu d'un numéro de TVA (seller.tax_number), débours sans TVA (lines[].pass_through), montants déjà payés (prepaid_amount_cents, prepaid_vat_cents), références à des factures antérieures (preceding_invoices), prélèvement SEPA (direct_debit) et pièces jointes (attachments).
  • Nouveau : le profil d'émetteur (/v1/keys/issuer) contient l'identifiant créancier (creditor_id). PUT /v1/keys/issuer ne modifie que les champs présents dans la requête ; une chaîne vide ou null efface un champ. Il refuse avec 400 un numéro de TVA sans code pays et un numéro fiscal de forme incorrecte.
  • Modifié : avec une période de prestation et sans date de prestation, la date de prestation (BT-72) est désormais la fin de la période, et non plus la date de facture. Pour une facture d'acompte sans date ni période, BT-72 est omis ; la vérification ZUGFeRD émet alors un avertissement (PEPPOL-EN16931-R008).
  • Modifié : les entrées qui produisaient jusqu'ici un fichier invalide (ni numéro de TVA ni numéro fiscal, numéro de TVA sans code pays, période finissant avant son début, prélèvement dans une XRechnung sans mandat) reçoivent désormais une réponse 400.
  • Modifié : le PDF d'un avoir (credit_note) n'affiche plus de montant à payer, mais indique que le montant sera crédité.
  • Modifié : via MCP, la réponse d'une facture ZUGFeRD avec pièces jointes ne contient que pdf_base64 ; le XML est dans le PDF.
  • Modifié : ID de règles corrigées : plus de fausses ID (BT-89, TMP-32, EU-79), les règles KoSIT avec une lettre gardent leur nom complet (BR-DE-25-B au lieu de BR-DE-25), les messages en double disparaissent. La suggestion pour BR-DE-20 (IBAN du payeur) ne dit plus que la règle n'existe plus ; CII-SR-475 et CII-SR-476 avec plusieurs pièces jointes sont expliquées comme sans conséquence.

Octobre 2026 : détection du format

  • format et profile proviennent désormais de l'identifiant de spécification (le champ guideline en CII, CustomizationID en UBL), et non plus de la première URN du document. Auparavant, beaucoup de factures XRechnung et EN 16931 revenaient sans format.
  • Nouveaux champs container (pdf : PDF avec facture électronique intégrée, xml : fichier XML) et syntax (CII, UBL).
  • Libellés : ZUGFeRD 2.x et ZUGFeRD 1.0 pour un PDF, sinon XRechnung 3.0, Peppol BIS Billing 3.0 ou EN 16931. Nouveaux profils XRECHNUNG et PEPPOL ; EXTENDED n'est plus signalé comme EN16931.

Juin 2026 — Création de factures

  • Nouvel outil create_invoice / POST /v1/create : créer des factures électroniques valides à partir de données structurées — comme PDF ZUGFeRD (PDF/A-3) ou XML XRechnung pur (avec Leitweg-ID pour le B2G).
  • Plusieurs lignes, toutes les catégories de TVA (S/Z/E/AE), remises/majorations, informations de paiement, échéance.
  • Types de document : facture, avoir/annulation, correction, autofacturation, facture d'acompte et facture partielle — avec référence à la facture d'origine.
  • Branding selon le forfait (pied de page sur le forfait Gratuit / white-label à partir d'Automatiser avec logo optionnel) ; quota hebdomadaire propre, distinct de la validation.
  • Clés sandbox/test (zv_test_…) : intégration libre avec filigrane « DEMO », sans entamer le quota réel.

Avril 2026 — Première publication

  • Validation selon EN 16931 (validate_invoice) pour les PDF ZUGFeRD/Factur-X et les XML XRechnung, avec des suggestions de correction concrètes.
  • Extraction XML (extract_xml) et contrôle de cohérence PDF↔XML (check_consistency).
  • Client MCP pour Claude & autres agents IA ; moteurs Mustang et KoSIT.