Traitement sidekiq-like, idéal pour ERP custom et portails fournisseurs.

FacturX API pour Symfony

Utilisez HttpClient, Messenger et Notifier pour piloter la validation.

HttpClient + AsyncDecorator
Messenger pour gérer les retries
Notifications Slack/Email intégrées

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 Symfony

Symfony HttpClient — génération /api/v1/convert
$client = HttpClient::create();

$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', 'https://api.facturxapi.com/api/v1/convert', [
    'headers' => [
        'Authorization' => 'Bearer ' . $_ENV['FACTURX_API_KEY'],
        'Accept-Language' => 'fr',
    ],
    'timeout' => 15,
    'body' => [
        'file' => fopen('/srv/app/var/FX-2024-0001.pdf', 'r'),
        'output' => 'facturx_pdfa3',
        'validation_target' => 'en16931',
        'invoice_data' => $invoiceData,
    ],
]);

$data = $response->toArray(false);
if (!($data['success'] ?? false)) {
    $this->notifier->send(new ChatMessage('Conversion FacturX à compléter: ' . ($data['target']['status'] ?? 'cible non vérifiée')));
}

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

  • Utiliser la pool de transport Async pour ne pas bloquer le worker

  • Ajouter un middleware Messenger pour tracer request_id

  • Stocker les rapports dans un storage chiffré (S3 SSE)

Retries & timeouts

Configurer Messenger pour rejouer 3 fois avec délai progressif (1/4/15 min).

  • • Timeout HttpClient : 15 s
  • • Limiter le parallélisme via messenger:consume --limit
  • • Notifier les erreurs 5xx via Notifier component

Erreurs fréquentes

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

Exception client locale

Timeout client ou proxy

Firewall ou proxy bloquant l'API sortante.

💡 Autoriser api.facturxapi.com sur votre proxy/SASE.

Code API public

415 unsupported_media_type

Payload multipart incorrect ou fichier non supporté.

💡 Envoyer un PDF Factur-X ou un XML CII pris en charge dans le champ multipart file ; corriger lang seulement si l’API renvoie un rejet de langue.

Exception client locale

Fichier local illisible

Flux tronqué lors de l'envoi.

💡 Toujours streamer via fopen et éviter file_get_contents sur les gros PDF.

FAQ

Peut-on utiliser API Platform ?

Oui, déclarez un provider custom qui appelle l'API FacturX.

Comment tracer le request_id ?

Ajoutez un middleware PSR pour logger X-Request-Id dans Monolog.

Guide Schematron

Comprendre les règles métier

Errors library

Trouver l'origine d'un BR-xx

Pricing

Prévoir votre budget