Upload sécurisé (multipart), réponse JSON structurée < 1 s, retry natif via Guzzle.

Intégrer FacturX API avec PHP

Envoyez vos PDF/XML Factur-X depuis un backend Laravel, Symfony ou WordPress en quelques lignes.

Compatible Laravel HTTP Client & Guzzle
Support natif des jobs/queues pour traiter des lots
Idéal pour automatiser un précontrôle ERP avant le canal réglementaire

Exemple cURL /convert

multipart/form-data — /convert + invoice_data
curl -X POST https://api.facturxapi.com/api/v1/convert \
  -H "Authorization: Bearer $FACTURX_API_KEY" \
  -H "Accept-Language: fr" \
  -F "file=@./facture-x.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"}}'

Snippet PHP

Guzzle — génération /api/v1/convert
<?php

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://api.facturxapi.com',
    'timeout' => 15,
]);

$invoiceData = <<<'JSON'
{
  "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"
  }
}
JSON;

$response = $client->request('POST', '/api/v1/convert', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('FACTURX_API_KEY'),
        'Accept-Language' => 'fr',
    ],
    'multipart' => [
        [
            'name' => 'file',
            'contents' => fopen(__DIR__ . '/invoices/FX-2024-0001.pdf', 'r'),
        ],
        [
            'name' => 'output',
            'contents' => 'facturx_pdfa3',
        ],
        [
            'name' => 'validation_target',
            'contents' => 'en16931',
        ],
        [
            'name' => 'invoice_data',
            'contents' => $invoiceData,
        ],
    ],
]);

$payload = json_decode((string) $response->getBody(), true);
logger()->info('facturx.convert', [
    'success' => $payload['success'] ?? false,
    'target' => $payload['target'] ?? null,
    'request_id' => $payload['request_id'] ?? null,
]);

Parcours conseillé — générer puis contrôler

Commencez par /convert pour produire un livrable Factur-X contrôlé, puis utilisez /validate comme précontrôle ou contrôle indépendant.

POST /api/v1/convert

PDF → Factur-X PDF/A-3

Génère un Factur-X PDF/A-3 à partir d'un PDF visuel et de données invoice_data. Les livrables ne sont exposés que si la cible demandée est vérifiée.

curl -X POST https://api.facturxapi.com/api/v1/convert \
  -H "Authorization: Bearer $KEY" \
  -H "Accept-Language: fr" \
  -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"}}'

POST /api/v1/validate

Précontrôle technique

Contrôle un PDF Factur-X ou un XML CII déjà produit. Retourne un rapport JSON structuré avec codes BR-* par ligne/champ.

curl -X POST https://api.facturxapi.com/api/v1/validate?validation_target=en16931 \
  -H "Authorization: Bearer $KEY" \
  -F "file=@./facture.pdf"

POST /api/v1/extract

XML CII embarqué → JSON

Extrait le XML CII d'un PDF Factur-X reçu. Paramètre validate=true combine extraction + validation en une requête.

curl -X POST "https://api.facturxapi.com/api/v1/extract?validate=true&lang=fr" \
  -H "Authorization: Bearer $KEY" \
  -F "file=@./facture-recue.pdf"

POST /api/v1/repair

Corrections déterministes

Corrige automatiquement les erreurs réparables d'un XML CII (dates, décimaux, namespaces, schemeID). Retour : diff + XML réparé.

curl -X POST https://api.facturxapi.com/api/v1/repair \
  -H "Authorization: Bearer $KEY" \
  -F "file=@./facture-invalide.xml"

Checklist intégration

  • Centraliser la clé dans .env + config/cache Laravel

  • Utiliser Storage::disk pour les fichiers temporaires (< 10 MB)

  • Logger request_id pour corréler avec Plausible / billing

Retries & timeouts

Configurer Guzzle RetryMiddleware sur 429/500 avec backoff exponentiel (max 3 tentatives).

  • • Timeout réseau recommandé : 15 s
  • • Backoff : 1s, 3s, 9s
  • • Traiter 402 (quota) côté business avant retry

Erreurs fréquentes

Mappez vos logs sans confondre codes API publics, exceptions client locales et règles métier EN16931.

Code API public

401 authentication_required

Clé API absente, expirée ou variable d'environnement non chargée.

💡 Vérifiez FACTURX_API_KEY dans .env + config:cache après déploiement.

Code API public

413 file_too_large

PDF au-dessus de la limite acceptée par l’API.

💡 Validez la taille avant upload et évitez les PDF scannés trop lourds.

Code API public

402 quota_exceeded

Quota mensuel atteint pour la clé utilisée.

💡 Traitez ce cas comme un signal business : bloquer le retry et afficher le besoin de plan supérieur.

FAQ

Puis-je déclencher la validation depuis une queue Horizon ?

Oui, l'upload est idempotent. Conservez seulement le request_id pour vos logs.

Comment associer un rapport à une facture ?

Utilisez vos identifiants (invoice_number) dans les métadonnées de job et stockez le JSON retourné.

Documentation API

Endpoints, schémas JSON et statuts

Obtenir une clé

Clé Sandbox et offres API

Bibliothèque d'erreurs

Comprendre BR-CO-xx et BR-CL-xx