1. Obtenir une clé
Ajoutez Authorization: Bearer ... à chaque appel. Vous pouvez créer une clé depuis /api-key.
Intégration ERP/GED
Envoyez une facture PDF avec votre invoice_data pour récupérer un PDF/A-3 avec XML CII embarqué. Si vous avez seulement besoin du XML CII, demandez output=xml_cii avec des données ERP complètes.
Avant de câbler votre mapping, vérifiez les champs listés plus bas. Une version API antérieure peut refuser un champ documenté ici.
Ajoutez Authorization: Bearer ... à chaque appel. Vous pouvez créer une clé depuis /api-key.
Le Factur-X PDF/A-3 demande un file. Le XML CII seul peut être produit sans PDF si invoice_data est complet.
Avant de stocker le résultat, vérifiez success, target.status et la présence du fichier demandé.
Un résultat /convert reste une production documentaire. Il ne soumet pas la facture et ne garantit pas une acceptation par une Plateforme Agréée.
output=facturx_pdfa3, ou omettez output puisque c’est la sortie par défaut.output=xml_cii. Avec un invoice_data complet, le PDF source est optionnel. Ce livrable ne doit pas être présenté comme un Factur-X.La clé API s'envoie en header X-API-Key (recommandé pour une clé statique ERP) ou, à l'identique, en Authorization: Bearer <clé> — les deux fonctionnent. Définissez votre clé API dans FACTURX_API_KEY, puis gardez la même clé d’idempotence uniquement pour rejouer la même requête complète. Utilisez une nouvelle clé si le fichier, le JSON, la sortie, la cible de validation, les options, un complément inline ou un sélecteur de profil enregistré (profile_reuse, issuer_id/client_id, seller_profile_id/buyer_profile_id) changent. Comportement vérifié en production : une requête différente sous la même clé est refusée en 409 idempotency_conflict sans exécution ni consommation de quota ; une clé rejouée pendant le traitement répond 409 idempotency_in_progress — attendez la fin du premier appel plutôt que de rejouer en boucle.
curl -X POST https://api.facturxapi.com/api/v1/convert \
-H "Authorization: Bearer $FACTURX_API_KEY" \
-H "Idempotency-Key: erp-fa-2026-042-v1" \
-F "file=@./facture.pdf" \
-F "output=facturx_pdfa3" \
-F "validation_target=en16931" \
-F 'invoice_data={
"invoice_number": "FA-2026-042",
"issue_date": "2026-04-01",
"invoice_type": "380",
"currency": "EUR",
"seller": {
"name": "Ma Societe SAS",
"siret": "10000000900017",
"vat_id": "FR88100000009",
"address": {
"street": "10 rue de Rivoli",
"city": "Paris",
"postal_code": "75001",
"country": "FR"
}
},
"buyer": {
"name": "Client SA",
"siret": "10000001700010",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"references": {
"buyer_reference": "SERVICE-ACHATS",
"purchase_order_reference": "PO-2026-0017",
"contract_reference": "CTR-2026-04"
},
"totals": {
"net": "970.00",
"tax": "194.00",
"gross": "1164.00",
"prepaid_amount": "100.00",
"rounding_amount": "0.00",
"due": "1064.00"
},
"tax_breakdown": [
{
"rate": "20.00",
"category": "S",
"base": "970.00",
"amount": "194.00"
}
],
"line_items": [
{
"number": "1",
"description": "Prestation conseil",
"quantity": "10",
"unit": "C62",
"unit_price": "100.00",
"net_amount": "970.00",
"vat_rate": "20.00",
"vat_category": "S",
"purchase_order_line_reference": "10",
"gross_unit_price": "120.00",
"price_discount": "20.00",
"allowances": [
{
"amount": "50.00",
"reason": "Remise ligne",
"reason_code": "95"
}
],
"charges": [
{
"amount": "20.00",
"reason": "Supplement urgent"
}
]
}
],
"payment": {
"due_date": "2026-05-01",
"terms": "Paiement a 30 jours",
"iban": "FR7630006000011234567890189"
},
"delivery": {
"date": "2026-04-01",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"invoicing_period": {
"start_date": "2026-04-01",
"end_date": "2026-04-30"
}
}' Pour un flux ERP sans conteneur PDF, demandez explicitement output=xml_cii. Le résultat est un XML CII, pas un document Factur-X.
curl -X POST https://api.facturxapi.com/api/v1/convert \
-H "Authorization: Bearer $FACTURX_API_KEY" \
-H "Idempotency-Key: erp-fa-2026-042-xml-v1" \
-F "output=xml_cii" \
-F "validation_target=en16931" \
-F 'invoice_data={
"invoice_number": "FA-2026-042",
"issue_date": "2026-04-01",
"invoice_type": "380",
"currency": "EUR",
"seller": {
"name": "Ma Societe SAS",
"siret": "10000000900017",
"vat_id": "FR88100000009",
"address": {
"street": "10 rue de Rivoli",
"city": "Paris",
"postal_code": "75001",
"country": "FR"
}
},
"buyer": {
"name": "Client SA",
"siret": "10000001700010",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"references": {
"buyer_reference": "SERVICE-ACHATS",
"purchase_order_reference": "PO-2026-0017",
"contract_reference": "CTR-2026-04"
},
"totals": {
"net": "970.00",
"tax": "194.00",
"gross": "1164.00",
"prepaid_amount": "100.00",
"rounding_amount": "0.00",
"due": "1064.00"
},
"tax_breakdown": [
{
"rate": "20.00",
"category": "S",
"base": "970.00",
"amount": "194.00"
}
],
"line_items": [
{
"number": "1",
"description": "Prestation conseil",
"quantity": "10",
"unit": "C62",
"unit_price": "100.00",
"net_amount": "970.00",
"vat_rate": "20.00",
"vat_category": "S",
"purchase_order_line_reference": "10",
"gross_unit_price": "120.00",
"price_discount": "20.00",
"allowances": [
{
"amount": "50.00",
"reason": "Remise ligne",
"reason_code": "95"
}
],
"charges": [
{
"amount": "20.00",
"reason": "Supplement urgent"
}
]
}
],
"payment": {
"due_date": "2026-05-01",
"terms": "Paiement a 30 jours",
"iban": "FR7630006000011234567890189"
},
"delivery": {
"date": "2026-04-01",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"invoicing_period": {
"start_date": "2026-04-01",
"end_date": "2026-04-30"
}
}' Le code ci-dessous illustre seulement l’appel HTTP. Votre intégration doit construire invoiceData depuis votre ERP.
import { readFile } from "node:fs/promises";
const invoiceData = {
"invoice_number": "FA-2026-042",
"issue_date": "2026-04-01",
"invoice_type": "380",
"currency": "EUR",
"seller": {
"name": "Ma Societe SAS",
"siret": "10000000900017",
"vat_id": "FR88100000009",
"address": {
"street": "10 rue de Rivoli",
"city": "Paris",
"postal_code": "75001",
"country": "FR"
}
},
"buyer": {
"name": "Client SA",
"siret": "10000001700010",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"references": {
"buyer_reference": "SERVICE-ACHATS",
"purchase_order_reference": "PO-2026-0017",
"contract_reference": "CTR-2026-04"
},
"totals": {
"net": "970.00",
"tax": "194.00",
"gross": "1164.00",
"prepaid_amount": "100.00",
"rounding_amount": "0.00",
"due": "1064.00"
},
"tax_breakdown": [
{
"rate": "20.00",
"category": "S",
"base": "970.00",
"amount": "194.00"
}
],
"line_items": [
{
"number": "1",
"description": "Prestation conseil",
"quantity": "10",
"unit": "C62",
"unit_price": "100.00",
"net_amount": "970.00",
"vat_rate": "20.00",
"vat_category": "S",
"purchase_order_line_reference": "10",
"gross_unit_price": "120.00",
"price_discount": "20.00",
"allowances": [
{
"amount": "50.00",
"reason": "Remise ligne",
"reason_code": "95"
}
],
"charges": [
{
"amount": "20.00",
"reason": "Supplement urgent"
}
]
}
],
"payment": {
"due_date": "2026-05-01",
"terms": "Paiement a 30 jours",
"iban": "FR7630006000011234567890189"
},
"delivery": {
"date": "2026-04-01",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"invoicing_period": {
"start_date": "2026-04-01",
"end_date": "2026-04-30"
}
};
const form = new FormData();
form.set("file", new Blob([await readFile("./facture.pdf")], { type: "application/pdf" }), "facture.pdf");
form.set("output", "facturx_pdfa3");
form.set("validation_target", "en16931");
form.set("invoice_data", JSON.stringify(invoiceData));
const response = await fetch("https://api.facturxapi.com/api/v1/convert", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FACTURX_API_KEY}`,
"Idempotency-Key": "erp-fa-2026-042-v1",
},
body: form,
});
const result = await response.json();
if (!response.ok || result.success !== true) {
throw new Error(JSON.stringify(result));
}
Exemple synthétique pour invoice_data. Il couvre les zones les plus utiles pour un premier test ERP/GED : références, totaux de paiement, remises/charges, ventilation TVA, livraison, période de facturation et tarification ligne.
{
"invoice_number": "FA-2026-042",
"issue_date": "2026-04-01",
"invoice_type": "380",
"currency": "EUR",
"seller": {
"name": "Ma Societe SAS",
"siret": "10000000900017",
"vat_id": "FR88100000009",
"address": {
"street": "10 rue de Rivoli",
"city": "Paris",
"postal_code": "75001",
"country": "FR"
}
},
"buyer": {
"name": "Client SA",
"siret": "10000001700010",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"references": {
"buyer_reference": "SERVICE-ACHATS",
"purchase_order_reference": "PO-2026-0017",
"contract_reference": "CTR-2026-04"
},
"totals": {
"net": "970.00",
"tax": "194.00",
"gross": "1164.00",
"prepaid_amount": "100.00",
"rounding_amount": "0.00",
"due": "1064.00"
},
"tax_breakdown": [
{
"rate": "20.00",
"category": "S",
"base": "970.00",
"amount": "194.00"
}
],
"line_items": [
{
"number": "1",
"description": "Prestation conseil",
"quantity": "10",
"unit": "C62",
"unit_price": "100.00",
"net_amount": "970.00",
"vat_rate": "20.00",
"vat_category": "S",
"purchase_order_line_reference": "10",
"gross_unit_price": "120.00",
"price_discount": "20.00",
"allowances": [
{
"amount": "50.00",
"reason": "Remise ligne",
"reason_code": "95"
}
],
"charges": [
{
"amount": "20.00",
"reason": "Supplement urgent"
}
]
}
],
"payment": {
"due_date": "2026-05-01",
"terms": "Paiement a 30 jours",
"iban": "FR7630006000011234567890189"
},
"delivery": {
"date": "2026-04-01",
"address": {
"street": "20 rue de la Republique",
"city": "Lyon",
"postal_code": "69002",
"country": "FR"
}
},
"invoicing_period": {
"start_date": "2026-04-01",
"end_date": "2026-04-30"
}
} invoice_data
Pour une source ERP complète, envoyez les adresses électroniques, les notes et la référence de facture précédente directement dans invoice_data avec les chemins confirmés ci-dessus. Les racines ci-dessous servent surtout à compléter un PDF ou XML analysé ; les champs réellement non supportés sont refusés explicitement plutôt qu’ignorés.
Quand un diagnostic ou un scan demande de compléter un document analysé, reprenez uniquement les racines indiquées : invoice_patch, seller_context ou buyer_context. invoice_patch ne peut pas être combiné avec un invoice_data complet ; pour un flux ERP complet, préférez les champs directs de la matrice.
Les valeurs entre chevrons sont des champs à renseigner, pas des valeurs par défaut. Pour le schéma 0225, utilisez l’identifiant de routage confirmé par votre contexte métier ou par le diagnostic ; ne recopiez pas automatiquement un SIRET.
{
"invoice_patch": {
"preceding_invoice": {
"issue_date": "2025-08-31"
},
"payment": {
"iban": "FR7630006000011234567890189"
}
},
"seller_context": {
"electronic_address": {
"value": "<identifiant_routage_vendeur_0225>",
"scheme_id": "0225"
},
"document_notes": [
{
"subject_code": "PMT",
"content": "<mention_frais_recouvrement_pmt_a_completer>"
},
{
"subject_code": "PMD",
"content": "<mention_penalites_retard_pmd_a_completer>"
},
{
"subject_code": "AAB",
"content": "<mention_escompte_aab_a_completer>"
}
]
},
"buyer_context": {
"electronic_address": {
"value": "<identifiant_routage_acheteur_0225>",
"scheme_id": "0225"
}
}
}
Ne traitez le PDF généré comme disponible que si la réponse indique le succès, la cible vérifiée et packagingPerformed=true.
{
"success": true,
"target": {
"requested": "en16931",
"executed": "en16931",
"status": "verified",
"missing_inputs": [],
"not_run_reason": null
},
"result": {
"targetProfile": "EN16931",
"conversionSuccessful": true,
"xml": "PD94bWwgdmVyc2lvbj0iMS4wIj8+...",
"xmlSize": 4096,
"pdf": "JVBERi0xLjQKJc...",
"pdfSize": 102400,
"packagingPerformed": true,
"validation": {
"valid": true,
"profile": "EN16931"
}
}
}
Pour output=xml_cii, utilisez result.xml. Le PDF est absent et packagingPerformed=false ; cette absence est normale pour ce livrable.
{
"success": true,
"target": {
"requested": "en16931",
"executed": "en16931",
"status": "verified",
"missing_inputs": [],
"not_run_reason": null
},
"result": {
"targetProfile": "EN16931",
"conversionSuccessful": true,
"xml": "PD94bWwgdmVyc2lvbj0iMS4wIj8+...",
"xmlSize": 4096,
"pdf": null,
"pdfUrl": null,
"packagingPerformed": false,
"validation": {
"valid": true,
"profile": "EN16931"
}
}
}
Si target.status est bloqué ou incomplet, affichez les champs retournés au lieu de masquer l’échec. Une liste non exhaustive ne doit pas être présentée comme une checklist finale.
{
"success": false,
"target": {
"requested": "france_2026",
"executed": null,
"status": "blocked",
"missing_inputs": [
"seller_context.electronic_address.value",
"buyer_context.electronic_address.value"
],
"not_run_reason": "missing_inputs"
},
"verdict": "convert_with_inputs",
"targetPreflight": {
"requested": "france_2026",
"status": "incomplete",
"exhaustive": false,
"requiredInputs": [
{
"btCode": "BT-34",
"requestContextPath": "seller_context.electronic_address.value"
},
{
"btCode": "BT-49",
"requestContextPath": "buyer_context.electronic_address.value"
}
],
"unsupportedBlockers": []
}
} 401 : clé absente, invalide ou révoquée. Reprenez la clé depuis /api-key ou /dashboard/keys.400 file_required_for_pdf_output : vous demandez le livrable PDF/A-3 sans fournir de PDF. Ajoutez file ou demandez explicitement output=xml_cii avec un invoice_data complet.400 invalid_options : options.mode="xml_only" n’est pas le sélecteur public du livrable final. Utilisez output=xml_cii.400 invalid_invoice_patch : invoice_patch combiné avec un invoice_data complet, ou JSON de patch invalide.409 inline_context_conflict : une valeur inline contredit une valeur visible dans le document.409 idempotency_conflict : même Idempotency-Key rejouée avec une requête différente (fichier, invoice_data, sortie, cible ou options modifiés). Action : nouvelle clé. La requête rejouée n'est pas exécutée et ne consomme pas de quota (vérifié en production).409 idempotency_in_progress : même clé rejouée pendant qu'une opération est en cours. Action : attendre puis re-vérifier côté ERP ; ne changez pas de clé pour « forcer » un doublon.413 file_too_large : fichier au-delà de la taille maximale (10 Mo).415 unsupported_media_type : fichier non PDF pour le flux Factur-X PDF/A-3.422 insufficient_data : données insuffisantes pour produire la cible demandée.422 invalid_invoice_data : arithmétique ligne incohérente, remise de prix sans prix brut, catégorie TVA O/K/G/L/M incohérente, motif d’exonération ambigu en mode multi-catégories, buyer.tax_registration_id non supporté, ou règle EN16931 refusée explicitement.422 unsupported_output_profile_for_invoice_data : invoice_data ne peut pas cibler MINIMUM, BASIC_WL ou BASIC. Gardez le profil EN16931 par défaut ou utilisez EXTENDED si votre contrat le prévoit.422 unextractable_pdf : aucune donnée exploitable extraite du PDF, sans invoice_data pour compenser.503 requested_output_unavailable : le PDF/A-3 demandé n’a pas pu être produit ; l’API échoue explicitement (quota remboursé) au lieu de retourner un succès XML-only silencieux.422 ocr_confidence_too_low : confiance OCR insuffisante en mode strict. Action : fournir invoice_data (recommandé) ou options.confidence_mode="lenient".503 ocr_service_unavailable / 503 ocr_quota_exhausted : OCR indisponible ou quota OCR épuisé — header Retry-After fourni. Action : rejouer après le délai, même clé d'idempotence. Sans objet en mode invoice_data complet (pas d'OCR).402 quota_exceeded : quota mensuel de factures traitées atteint (définitif jusqu'au renouvellement ou upgrade — pas de Retry-After).429 : rate limit par minute — header Retry-After fourni. Action : backoff puis rejouer à l'identique (même clé d'idempotence).
En résumé pour votre gestionnaire d'erreurs : les 4xx hors 429 et hors 409 idempotency_in_progress sont des erreurs de requête à corriger avant un nouvel appel (nouvelle clé d'idempotence) ; 409 idempotency_in_progress est le seul cas où il faut attendre sur la clé d'origine — en changer relancerait une seconde conversion ; 429 et les 503 se rejouent à l'identique après le délai ; 503 requested_output_unavailable rembourse le quota et se rejoue tel quel.
Facture 20 % + 5,5 % avec une remise BG-20 portée par son taux : une entrée tax_breakdown par couple (catégorie, taux), bases exactes par groupe (BR-S-08). Exemple exécuté et vérifié contre la production.
{
"invoice_number": "FA-2026-118",
"issue_date": "2026-06-11",
"seller": {
"name": "Smoke Editeur SAS",
"address": {
"country": "FR",
"street": "10 rue de la Paix",
"city": "Paris",
"postal_code": "75002"
},
"vat_id": "FR80421347006",
"siret": "42134700600080",
"electronic_address": {
"value": "42134700600080",
"scheme_id": "0225"
}
},
"buyer": {
"name": "Smoke Client SARL",
"address": {
"country": "FR",
"street": "5 avenue des Champs",
"city": "Lyon",
"postal_code": "69002"
},
"vat_id": "FR40303265045",
"siret": "30326504500017"
},
"totals": {
"net": "73.33",
"tax": "7.42",
"gross": "80.75"
},
"tax_breakdown": [
{
"rate": "20",
"category": "S",
"base": "23.33",
"amount": "4.67"
},
{
"rate": "5.5",
"category": "S",
"base": "50.00",
"amount": "2.75"
}
],
"line_items": [
{
"number": "1",
"description": "Prestation 20%",
"quantity": "1",
"unit_price": "33.33",
"net_amount": "33.33",
"vat_rate": "20"
},
{
"number": "2",
"description": "Prestation 5.5%",
"quantity": "1",
"unit_price": "50.00",
"net_amount": "50.00",
"vat_rate": "5.5"
}
],
"allowances": [
{
"amount": "10.00",
"reason": "Remise",
"vat_category": "S",
"vat_rate": "20"
}
],
"payment": {
"due_date": "2026-07-11",
"terms": "30 jours"
}
} Pour valider votre mapping sans générer de livrable ni consommer de quota, ajoutez dry_run=true : la réponse liste les champs manquants (targetPreflight, et convertPreparation.fieldsToProvide quand des champs guidés sont attendus) avant votre premier appel final.
invoice_data est un champ multipart de type chaîne contenant le JSON sérialisé (pas un body JSON) — en shell, préférez -F "invoice_data=$(cat facture.json)" ou --form-string pour éviter les surprises d'échappement."970.00", "20.00") — un montant sub-centime est refusé en 422 ; quantity et unit_price peuvent porter plus de décimales.Et après ?
Choisissez l'étape suivante selon votre besoin. Certains liens ouvrent une autre surface ou préparent un email lorsque c'est indiqué.
Créez une clé et testez le premier appel depuis votre environnement.
Relisez les paramètres, réponses et codes erreur de la référence API principale.
Envoyez votre contexte ERP/GED et le type de flux à tester, par email.