Aller au contenu

Pour les développeurs

API de facturation : brouillons, factures émises, événements webhook

Dernière vérification SUPPORTED WITH LIMITATIONS

Traduction de la version anglaise, mise à jour en premier. Les indications réglementaires renvoient aux sources citées et à leur date de consultation.

L'API de facturation KRONENWERK permet à votre logiciel de démarrer un brouillon de facture pour un client avec POST /invoices/drafts, de lire les factures émises avec GET /invoices et GET /invoices/{number}, et d'être informé de l'émission, du paiement et de l'annulation par les webhooks invoice.issued, invoice.paid et invoice.cancelled. L'émission elle-même n'est pas exposée : le numéro, le verdict fiscal, la vérification VIES et le fichier structuré validé sont produits lorsqu'une personne émet le brouillon dans le produit.

Ce que l'API de facturation fait et ne fait pas

Elle crée des brouillons et lit les archives. Un brouillon est un document de travail : il peut être corrigé, retarifé ou jeté, et personne en dehors de la société ne l'a vu. Une facture émise est tout le contraire : un numéro a été consommé dans une séquence continue, une ligne d'archive a été figée, un fichier conforme à une norme nationale a été produit, et en Pologne le document peut avoir été remis à un système d'État qui décide de son existence juridique. L'API vous donne le premier et ne fait que lire le second.

OpérationVia l'APIOù cela se passe
Créer un clientPOST /customersAPI ou produit
Démarrer un brouillon de facturePOST /invoices/draftsAPI ou produit
Ajouter des lignes, fixer les prix, choisir la date de livraisonnon exposéProduit
Émettre : numéro, verdict fiscal, vérification VIES, fichier structuré, validationnon exposéProduit ; signalé par invoice.issued
Enregistrer un paiementnon exposéProduit (manuel, import bancaire) ; signalé par invoice.paid et payment.recorded
Annuler par correction intégralenon exposéProduit ; signalé par invoice.cancelled
Lire les factures émisesGET /invoices, GET /invoices/{number}API
Lire ce qui est dû aujourd'huiGET /reports/outstandingAPI

La liste complète des endpoints, l'authentification et la structure des erreurs figurent sur la page de l'API comptable et dans la référence.

Créer un brouillon : POST /invoices/drafts

La requête désigne un client et rien d'autre. Ce qui revient est un brouillon préparé comme le produit le prépare : la proposition de numérotation du vendeur, l'échéance calculée à partir des délais de paiement convenus avec le client, et la mention de paiement de la juridiction du vendeur dans la langue dans laquelle cette juridiction rédige ses documents. Chacune de ces décisions appartient à un module pays ; un champ de requête permettrait à un appelant de contourner discrètement les règles d'un pays qu'il n'a pas lues.

Trois scopes sont requis — invoices:write, customers:read et companies:read — parce que le brouillon est construit à partir d'un client et pour une entité juridique dont la numérotation, les délais de paiement et la juridiction décident du contenu du document. L'en-tête Idempotency-Key est obligatoire.

curl -X POST https://kronenwerk.org/api/extern/v1/invoices/drafts \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: contract-7731-invoice-1" \
  -H "Content-Type: application/json" \
  -d '{ "customerId": "3f2b…" }'
{
  "id": "e41a…",
  "number": "2026-0042",
  "documentType": "INVOICE",
  "customerId": "3f2b…",
  "customer": "Beispiel GmbH",
  "currency": "EUR",
  "issuedOn": "2026-09-03",
  "dueOn": "2026-09-17",
  "state": "DRAFT",
  "createdAt": "2026-09-03T08:16:05Z"
}

number est une proposition dans le format que le module pays du vendeur considère comme licite, avec le préfixe de la société si un préfixe est configuré ; il ne devient définitif qu'à l'émission. state vaut toujours DRAFT sur cette surface. Un customerId inexistant, ou appartenant à une autre société, répond 404 NICHT_GEFUNDEN — une seule réponse pour les deux cas, afin que les codes de statut ne puissent pas servir à énumérer les identifiants d'autrui. Une répétition avec la même Idempotency-Key renvoie le même brouillon ; une répétition avec un corps différent répond 409 IDEMPOTENZ_KONFLIKT. Voir idempotence.

Après l'appel, le brouillon apparaît dans la liste des factures du produit, où une personne ajoute les lignes, vérifie le numéro de TVA du client et l'émet. Votre intégration apprend le résultat par le webhook, non par interrogation répétée.

Pourquoi l'émission reste dans le produit

Parce que l'émission est le moment où trois décisions deviennent définitives, et que chacune est vérifiée par rapport à des faits que l'appelant de l'API ne détient pas.

Validation du fichier structuré

À l'émission, KRONENWERK génère la facture électronique structurée attendue par le pays du vendeur — XRechnung ou ZUGFeRD en Allemagne, Factur-X en France, UBL Peppol BIS Billing 3.0 en Belgique, XML FA(3) en Pologne — et la valide avant que le numéro ne soit consommé. Un document allemand est contrôlé par rapport aux règles Schematron de la KoSIT et recoupé avec la bibliothèque Mustang. Un brouillon qui échoue à la validation n'est pas émis ; la personne voit quelle règle a échoué. Une API qui émettrait directement devrait soit sauter ce contrôle, soit inventer un canal d'erreur pour un document que son appelant n'a jamais vu. Voir la page de l'API de facturation électronique.

Le verdict fiscal

Chaque facture reçoit un verdict fiscal dérivé des faits de la transaction — pays du vendeur et de l'acheteur, entreprise ou consommateur, nature de l'opération : taux normal, taux zéro, exonération, autoliquidation, hors champ, ou « saisie requise » / « confirmation professionnelle requise ». Le numéro de TVA de l'acheteur est vérifié dans VIES à l'émission et le verdict est stocké avec la facture. Lorsque les faits ne tranchent pas, le produit le dit et interroge une personne ; il ne devine pas, et un script ne devrait pas non plus.

Numérotation

Les numéros de facture proviennent d'une séquence continue, et un numéro consommé ne peut pas être restitué ; le remède à une facture erronée est un document de correction, non une suppression. Une boucle exécutée deux fois ne doit pas pouvoir consommer deux numéros, ce qui explique pourquoi l'API s'arrête au brouillon et pourquoi chaque écriture qu'elle propose est idempotente.

Lire les factures émises : GET /invoices

GET /invoices renvoie les factures émises, les plus récentes en premier, une page à la fois, avec les montants figés à l'émission — un client renommé la semaine dernière ne change pas le nom sur une facture émise l'an dernier. Les filtres sont status (OPEN ou PAID ; une valeur illisible signifie aucun filtre), from et to (dates d'émission ISO), page et size (25 par défaut, 100 au maximum). GET /invoices/{number} lit une facture par le numéro sous lequel l'entreprise et son client la connaissent tous deux.

curl "https://kronenwerk.org/api/extern/v1/invoices?status=OPEN&from=2026-01-01&size=50" \
  -H "Authorization: Bearer greif_live_…"
{
  "data": [
    {
      "id": "7a90…",
      "number": "2026-0041",
      "documentType": "INVOICE",
      "buyer": "Beispiel GmbH",
      "currency": "EUR",
      "issuedOn": "2026-08-28",
      "dueOn": "2026-09-11",
      "deliveredOn": "2026-08-28",
      "net": { "minor": 89000, "currency": "EUR" },
      "tax": { "minor": 16910, "currency": "EUR" },
      "gross": { "minor": 105910, "currency": "EUR" },
      "outstanding": { "minor": 105910, "currency": "EUR" },
      "paymentState": "OPEN",
      "overdue": false,
      "cancelled": false,
      "creditNote": false,
      "paidOn": null,
      "recordedAt": "2026-08-28T14:02:11Z"
    }
  ],
  "page": 0,
  "size": 50,
  "total": 1,
  "more": false
}

paymentState vaut OPEN, OVERDUE, PAID, CANCELLED ou CORRECTION ; overdue est calculé par rapport à la date du jour. cancelled signifie qu'un document de correction annulant intégralement cette facture existe ; creditNote signifie que ce document est une correction. Rien n'est jamais supprimé ni modifié dans les archives.

Webhooks : invoice.issued, invoice.paid, invoice.cancelled

Chaque événement est livré sous forme de POST HTTPS avec un en-tête de signature (KRONENWERK-Signature: t=…,v1=…, HMAC-SHA256 sur l'horodatage, un point et le corps brut) et un identifiant d'événement stable dans KRONENWERK-Event-Id et Idempotency-Key. La livraison est de type « au moins une fois » ; stockez donc l'identifiant d'événement et ignorez les répétitions. Le corps est un objet JSON plat ; chaque valeur est une chaîne, et les clés sont triées.

{
  "amountDueMinor": "105910",
  "buyerName": "Beispiel GmbH",
  "currency": "EUR",
  "documentType": "INVOICE",
  "dueDate": "2026-09-17",
  "event": "invoice.issued",
  "grossMinor": "105910",
  "id": "0d3c…",
  "invoiceId": "7a90…",
  "issueDate": "2026-09-03",
  "netMinor": "89000",
  "number": "2026-0042",
  "paymentState": "OPEN",
  "taxMinor": "16910"
}

invoice.paid porte les mêmes champs plus paidOn ; il est déclenché là où le paiement solde effectivement la créance, quel que soit le chemin emprunté — un écran de paiement, un import bancaire, le téléphone. invoice.cancelled ajoute cancelledByInvoiceId, cancelledByNumber et reason, en désignant le document de correction afin qu'un récepteur puisse annuler le bon enregistrement et rapprocher l'avoir. Un événement distinct payment.recorded signale les mouvements d'argent dans les deux sens, avec direction, amountMinor, method, reference, targetKind et targetId. Les étapes de vérification figurent sur la page des webhooks.

Une séquence typique

  1. Votre application crée le client une seule fois avec POST /customers (nom, rue, code postal et ville sont obligatoires ; pays, numéro de TVA et devise sont facultatifs) et stocke l'id renvoyé.
  2. Lorsqu'un événement facturable survient, votre application appelle POST /invoices/drafts avec ce customerId et une Idempotency-Key dérivée de votre propre enregistrement, par exemple le numéro de contrat ou de commande.
  3. Une personne de la société complète et émet le brouillon. KRONENWERK calcule le verdict fiscal, vérifie le numéro de TVA dans VIES, valide le fichier structuré et consomme le numéro.
  4. Votre endpoint de webhook reçoit invoice.issued, vérifie la signature, déduplique sur id et stocke number et invoiceId en regard de votre enregistrement.
  5. Lorsque la facture est réglée, invoice.paid arrive. Si la personne l'annule, invoice.cancelled arrive avec le numéro de la correction.
  6. Pour le rapprochement, GET /reports/outstanding renvoie les créances et les dettes ouvertes à ce jour dans la devise des livres, à partir des mêmes chiffres que ceux affichés sur le tableau de bord du propriétaire.

Ce schéma est déroulé pour une entreprise à abonnement dans connecter un produit SaaS à la comptabilité.

Comment KRONENWERK gère cela

PRIS EN CHARGE AVEC LIMITATIONS La création de brouillons, la lecture des factures et les trois événements de facture fonctionnent comme décrit, sur le plan Enterprise (tarifs). La limitation est délibérée et permanente dans la conception actuelle : l'API n'ajoute pas de lignes à un brouillon, n'émet pas, n'enregistre pas de paiements et n'annule pas. Si votre intégration a besoin d'un flux d'émission entièrement automatisé sans intervention humaine, l'API de KRONENWERK n'est pas cela aujourd'hui, et cette page le dit plutôt que de laisser entendre le contraire.

Ce que le produit fait à l'émission est décrit sur factures et facturation électronique : XRechnung et ZUGFeRD pour l'Allemagne, Factur-X pour la France, UBL Peppol BIS pour la Belgique, FA(3) pour la Pologne, et factures PDF avec règles fiscales nationales pour le Canada et les États-Unis. L'envoi via Peppol passe par un fournisseur de point d'accès accrédité (Storecove) une fois la société connectée dans Paramètres → Envoi ; la transmission au KSeF polonais n'est pas encore prête pour la production. Les deux sont traités sur Intégration Peppol et Intégration KSeF.

Questions fréquentes

Puis-je définir les lignes de facture ou le total via l'API ?

Non. POST /invoices/drafts n'accepte que customerId. Les lignes, les prix et la date de livraison sont saisis dans le produit avant qu'une personne n'émette le brouillon.

L'API peut-elle émettre une facture ?

Non, quel que soit le scope. L'émission consomme un numéro et libère un document juridique ; elle reste dans le produit, et le webhook invoice.issued la signale.

Comment savoir qu'une facture a été payée ?

Abonnez-vous à invoice.paid (et à payment.recorded pour le paiement lui-même), ou interrogez GET /invoices?status=PAID avec une date from. Le webhook est la voie prévue.

Pourquoi l'endpoint de brouillon a-t-il besoin de companies:read ?

Le brouillon est construit pour l'entité juridique émettrice : sa numérotation, ses délais de paiement et sa juridiction décident du contenu du document. La lecture de ces paramètres fait partie de la création du brouillon ; le scope est donc déclaré plutôt que silencieusement exigé.

Le numéro de facture du brouillon est-il définitif ?

Non. C'est la proposition du module pays pour le prochain numéro licite, et il n'est confirmé qu'à l'émission de la facture.

Sources

  1. KRONENWERK developer documentation consulté le
  2. Directive 2006/112/EC on the common system of value added tax, Title XI Chapter 3 (invoicing) consulté le
  3. European Commission — VIES VAT number validation consulté le

Commencer l'intégration

Lire le démarrage rapide Référence

À lire ensuite