Aller au contenu

Pour les développeurs

Connecter votre SaaS à la comptabilité : clients, brouillons, webhooks

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.

Connecter un produit SaaS à la comptabilité avec KRONENWERK signifie quatre choses : créer un client par compte payant, ouvrir une transaction et un brouillon de facture pour chaque événement facturable avec une Idempotency-Key dérivée de votre propre enregistrement, recevoir invoice.issued, invoice.paid et payment.recorded sur un endpoint de webhook, et rapprocher avec GET /reports/outstanding. L'API n'émet pas de factures et n'enregistre pas de paiements ; une personne le fait dans le produit, et les événements indiquent à votre système ce qui s'est passé. C'est la forme honnête de l'intégration, et cette page la présente pas à pas.

Ce que l'intégration peut et ne peut pas automatiser

L'API KRONENWERK crée des enregistrements récupérables et lit les livres. Elle n'accomplit pas les actes irréversibles — émettre une facture, enregistrer un paiement, annuler — parce que chacun d'eux consomme quelque chose qui ne peut pas être restitué ou déplace de l'argent dans le grand livre. Pour un back-end SaaS, c'est une contrainte à connaître avant de concevoir.

Votre événementCe que fait votre applicationCe qui se passe dans le produitCe qui revient
Un compte s'inscrit ou passe à un plan payantPOST /customersLe client apparaît dans les données de base avec un numéro de partenaire201 avec l'id et le number du client
Un contrat ou une commande est concluPOST /transactionsUne transaction (un dossier avec une étape et une échéance) apparaît sur le tableau de la société201 avec un number tel que V2026-0481
Une période de facturation arrive à échéance pour un compte B2BPOST /invoices/draftsUn brouillon attend ses lignes et son émission par une personne201 avec le brouillon ; plus tard invoice.issued
Le client paie (carte, virement)Rien sur l'APILe paiement est enregistré dans le produit : manuellement, ou rapproché depuis le compte bancaire connectépayment.recorded et, lorsque la créance est soldée, invoice.paid
Un remboursement ou un litige annule une factureRien sur l'APIUne personne émet une correction intégraleinvoice.cancelled désignant l'avoir
Contrôle de fin de moisGET /reports/outstanding, GET /invoices?status=OPENCréances et dettes ouvertes à ce jour ; les factures ouvertes

L'API fait partie du plan Enterprise ; l'ensemble de la surface est décrit sur la page de l'API comptable. Le volet métier de la tenue des livres d'une entreprise à abonnement — produits constatés d'avance, TVA sur les services numériques, multidevise — est traité dans la comptabilité des entreprises SaaS et connecter une application à la comptabilité.

Schéma 1 : un client par compte payant, créé de manière idempotente

Créez le client KRONENWERK lorsqu'un compte devient un client payant, non à l'inscription, et utilisez votre propre identifiant de compte dans l'Idempotency-Key. Une nouvelle tentative après une réponse perdue renvoie alors le client qui a été créé plutôt qu'un doublon, et un client en double est l'erreur que personne ne remarque jusqu'à ce qu'une facture parte vers le mauvais enregistrement.

curl -X POST https://kronenwerk.org/api/extern/v1/customers \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: account-88213" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Beispiel GmbH",
    "email": "billing@example.de",
    "street": "Musterstraße 1",
    "postalCode": "10115",
    "city": "Berlin",
    "country": "DE",
    "vatId": "DE123456789",
    "currency": "EUR"
  }'

Le nom, la rue, le code postal et la ville sont obligatoires — l'EN 16931 porte une adresse décomposée en parties, et un client sans rue est un client auquel aucune facture ne peut être adressée. Le pays, le numéro de TVA et la devise sont facultatifs ; un pays manquant prend par défaut celui de la société. Stockez l'id renvoyé en regard de votre compte. Le numéro de TVA compte plus qu'il n'y paraît : à l'émission, KRONENWERK le vérifie dans VIES et en dérive le verdict fiscal (autoliquidation pour un client professionnel dans un autre pays de l'UE, par exemple). Collectez-le lors du paiement.

Schéma 2 : une transaction par commande, avec vos identifiants dedans

Une transaction dans KRONENWERK est une unité de travail avec un titre, un client, une étape issue du flux de travail propre à la société et une échéance — une commande, un projet, une période d'abonnement. Elle ne porte aucun montant, ce qui est exactement la raison pour laquelle c'est le bon enregistrement pour « quelque chose de facturable s'est produit » avant que quiconque n'ait décidé de ce que dira la facture. Mettez vos identifiants de prestataire dans la description afin que la personne qui émettra ensuite la facture puisse retrouver l'abonnement Stripe ou la commande en une seule recherche.

curl -X POST https://kronenwerk.org/api/extern/v1/transactions \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: sub_1Q…-2026-09" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Team plan, September 2026 — Beispiel GmbH",
    "customerId": "3f2b…",
    "description": "Stripe subscription sub_1Q…, invoice in_1Q…, 12 seats",
    "dueOn": "2026-09-30"
  }'

Seul title est obligatoire. stage peut désigner une clé d'étape du flux de travail de la société ; s'il est omis, la transaction démarre là où commence le flux de travail. La réponse porte id, number, title, stage, customer, dueOn, archived et createdAt. GET /transactions?search=sub_1Q… permet de la retrouver. Notez qu'il ne s'agit pas d'une écriture comptable : rien n'est comptabilisé tant qu'une facture n'est pas émise ou qu'un paiement n'est pas enregistré dans le produit.

Schéma 3 : un brouillon de facture pour chaque événement de facturation B2B

Pour les clients professionnels qui ont besoin d'une facture en bonne et due forme — une XRechnung pour un acheteur public allemand, un document Peppol pour un acheteur belge, une Factur-X pour un acheteur français — démarrez un brouillon lorsque la période de facturation arrive à échéance. Le brouillon porte la proposition de numérotation du vendeur et les conditions de paiement du client ; une personne ajoute les lignes et l'émet, et le fichier structuré est généré et validé à ce moment-là. La raison pour laquelle la limite est tracée au brouillon est expliquée sur la page de l'API de facturation.

curl -X POST https://kronenwerk.org/api/extern/v1/invoices/drafts \
  -H "Authorization: Bearer greif_live_…" \
  -H "Idempotency-Key: in_1Q…" \
  -H "Content-Type: application/json" \
  -d '{ "customerId": "3f2b…" }'

Utilisez l'identifiant de facture du prestataire comme clé : une facture Stripe, un brouillon KRONENWERK, quel que soit le nombre de fois où le webhook déclencheur est livré. Si votre produit facture des consommateurs plutôt que des entreprises, vous n'aurez peut-être pas besoin d'un brouillon par paiement ; un récapitulatif périodique traité dans le produit convient souvent mieux, et savoir si une vente à un consommateur exige une facture individuelle dans un pays donné requiert une confirmation professionnelle.

Schéma 4 : écouter les webhooks, vérifier, dédupliquer, répondre vite

Enregistrez un endpoint HTTPS sur le port 443 dans le produit et abonnez-vous à invoice.issued, invoice.paid, invoice.cancelled et payment.recorded. Chaque livraison porte KRONENWERK-Signature: t=<seconds>,v1=<hex> — un 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. Le corps est un objet JSON plat dont les valeurs sont des chaînes, avec les clés triées, et event et id toujours présents.

POST /hooks/kronenwerk HTTP/1.1
Content-Type: application/json; charset=utf-8
KRONENWERK-Event: invoice.paid
KRONENWERK-Event-Id: 0d3c…
KRONENWERK-Delivery: 61af…
KRONENWERK-Attempt: 1
Idempotency-Key: 0d3c…
KRONENWERK-Signature: t=1788768000,v1=9f2c…
User-Agent: KRONENWERK-Webhooks/1

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

Les règles de traitement sont celles que Stripe documente pour ses propres webhooks, et pour les mêmes raisons : vérifiez la signature sur le corps brut avant l'analyse, rejetez un horodatage hors de votre tolérance (le vérificateur de KRONENWERK utilise cinq minutes), enregistrez l'identifiant d'événement et ignorez tout ce que vous avez déjà vu, ne comptez pas sur l'ordre, et renvoyez rapidement un 2xx en effectuant le travail dans une file d'attente. La livraison est de type « au moins une fois » avec nouvelles tentatives ; les redirections sont traitées comme des échecs. La description complète figure sur webhooks.

Schéma 5 : rapprocher avec le rapport des encours

GET /reports/outstanding répond à la question « qu'est-ce qui est dû dans chaque sens aujourd'hui » à partir de la même vue d'ensemble que celle affichée sur le tableau de bord du propriétaire, de sorte que votre chiffre et le sien ne peuvent pas diverger.

{
  "asOf": "2026-09-03",
  "currency": "EUR",
  "booksOpen": true,
  "receivables": {
    "outstanding": { "minor": 4237650, "currency": "EUR" },
    "due": { "minor": 1105910, "currency": "EUR" },
    "overdue": { "minor": 318400, "currency": "EUR" },
    "count": 23
  },
  "payables": {
    "outstanding": { "minor": 812000, "currency": "EUR" },
    "due": { "minor": 0, "currency": "EUR" },
    "overdue": { "minor": 0, "currency": "EUR" },
    "count": 4
  }
}

Les deux côtés sont rapportés séparément et jamais compensés : l'argent dû à une entreprise et l'argent qu'elle doit arrivent à échéance à des jours différents, et un chiffre unique serait rassurant précisément au moment où il ne devrait pas l'être. Pour une vue par facture, parcourez GET /invoices?status=OPEN et comparez outstanding et overdue avec votre propre état de facturation. Un écart signifie généralement un paiement arrivé à la banque mais pas encore rapproché dans le produit, ou une facture que votre gestionnaire de webhooks a laissée tomber — le journal des identifiants d'événement vous dit lequel.

Exemple de séquence pour un abonnement facturé via Stripe

  1. Stripe envoie customer.subscription.created. Votre gestionnaire le vérifie, déduplique sur l'identifiant d'événement Stripe, et appelle POST /customers avec Idempotency-Key: account-<id> si aucun client KRONENWERK n'existe encore pour le compte. Stockez l'id renvoyé.
  2. Votre gestionnaire appelle POST /transactions avec Idempotency-Key: sub_<id>-<period>, en plaçant les identifiants d'abonnement et de facture Stripe dans description et la fin de période dans dueOn.
  3. Pour les comptes B2B, votre gestionnaire appelle POST /invoices/drafts avec Idempotency-Key: in_<id>.
  4. Une personne du service financier ouvre le brouillon, ajoute la ligne de la période à partir de la description de la transaction, et l'émet. KRONENWERK calcule le verdict fiscal, vérifie le numéro de TVA, valide le fichier structuré, consomme le numéro et envoie invoice.issued à votre endpoint. Stockez number et invoiceId en regard de la facture Stripe.
  5. Stripe encaisse le paiement par carte et effectue le versement sur le compte bancaire de la société. La connexion bancaire (Enable Banking pour les banques européennes, Plaid pour les banques canadiennes et américaines) affiche le versement ; une personne le rapproche de la facture, ou enregistre le paiement manuellement. payment.recorded et invoice.paid parviennent à votre endpoint.
  6. Si Stripe rembourse le paiement, une personne émet une correction dans le produit ; invoice.cancelled arrive avec cancelledByNumber, et vous rattachez le numéro d'avoir au remboursement.
  7. En fin de mois, comparez GET /reports/outstanding avec vos propres créances ouvertes.

Pièges

Dériver les clés d'idempotence du temps ou du hasard
Une clé qui change à chaque nouvelle tentative ne protège rien. Dérivez-la de l'enregistrement que vous reflétez — identifiant de compte, identifiant d'abonnement plus période, identifiant de facture du prestataire — afin qu'une nouvelle tentative signifie la même opération. Un corps différent sous la même clé répond 409 IDEMPOTENZ_KONFLIKT, ce qui est un défaut de votre code, non une erreur passagère.
Créer des brouillons avant que le client n'existe
Stripe ne garantit pas l'ordre des événements ; invoice.paid peut arriver avant customer.subscription.created. Résolvez d'abord le client KRONENWERK, en le créant de manière idempotente s'il manque, puis créez le brouillon.
Une clé, une société
Une clé d'API KRONENWERK est liée à exactement une société pour toute sa durée de vie. Un SaaS comptant plusieurs entités juridiques (une GmbH allemande et une SAS française, par exemple) a besoin d'une clé par entité et doit router chaque compte vers la bonne ; voir plusieurs sociétés, plusieurs devises.
Considérer invoice.issued comme « envoyée »
Cela signifie qu'un document validé existe et qu'un numéro a été consommé. La remise — e-mail, Peppol via le fournisseur de point d'accès connecté, ou un système national — est une étape distincte dans le produit et n'est pas signalée sur l'API.
Ignorer la limite de débit
Le budget est de 240 requêtes par clé, se rechargeant à environ deux par seconde. Un traitement de fin de mois qui crée mille brouillons d'un coup rencontrera un 429 avec Retry-After ; respectez l'en-tête et étalez le travail. Détails sur limites.
Tester avec la clé de production
Utilisez une clé greif_test_ pendant le développement ; elle fonctionne contre le même hôte en mode test pour la société qui l'a créée. GET /me renvoie environment à SANDBOX ou PRODUCTION, de sorte qu'un contrôle au démarrage peut refuser d'exécuter une version de test avec une clé de production.
Stocker des montants formatés
Les montants sont des entiers en unités mineures avec un code de devise sur l'API, et des chaînes d'unités mineures dans les corps de webhook. N'analysez « 1.059,10 € » nulle part ; il n'y a rien à analyser.

Comment KRONENWERK gère cela

PRIS EN CHARGE AVEC LIMITATIONS Tout ce qui est montré ici fonctionne sur l'API telle qu'elle existe aujourd'hui, sur le plan Enterprise (tarifs) : création idempotente de clients, de transactions et de brouillons de facture ; webhooks signés pour l'émission, le paiement, l'annulation, les achats et les paiements ; le rapport des encours et les lectures paginées de factures. Les limitations sont celles énoncées tout au long de cette page : pas d'émission, pas d'enregistrement de paiement, pas d'annulation et pas de téléchargement de fichier via l'API, et pas d'import automatique des paiements Stripe. Si votre intégration a besoin d'une boucle de facturation sans intervention humaine, l'API de KRONENWERK n'est pas cela. Si elle a besoin que les livres d'une société reflètent ce que votre produit a vendu, les étapes juridiques étant accomplies par une personne selon les règles du pays, c'est la voie prévue. Les pages produit associées sont comptabilité, factures et automatisation ; la comparaison des outils comptables dotés d'une API se trouve sur logiciels de comptabilité avec API.

Questions fréquentes

Puis-je enregistrer un paiement Stripe via l'API ?

Non. L'API n'enregistre pas de paiements. Les versements arrivent dans les livres par la connexion bancaire, ou une personne enregistre le paiement ; payment.recorded et invoice.paid parviennent ensuite à votre endpoint.

Qu'est-ce qu'une « transaction » sur l'API ?

Une unité de travail avec un titre, un client facultatif, une étape issue du flux de travail de la société et une échéance — une commande ou une période d'abonnement. Ce n'est pas une écriture comptable.

Ai-je besoin d'un brouillon pour chaque paiement de consommateur ?

Souvent non. Les brouillons sont destinés aux clients qui ont besoin d'une facture individuelle et structurée. Savoir si les ventes aux consommateurs dans un pays donné en exigent une est une question qui requiert une confirmation professionnelle.

Comment dériver les clés d'idempotence ?

De vos propres identifiants stables : identifiant de compte pour les clients, identifiant d'abonnement plus période pour les transactions, identifiant de facture du prestataire pour les brouillons. Les clés peuvent compter jusqu'à 200 caractères.

Comment tester sans toucher aux livres de production ?

Créez une clé greif_test_. Elle fonctionne contre la même API en mode test pour la société qui l'a créée, et GET /me renvoie "environment" afin que votre version puisse le vérifier.

Sources

  1. KRONENWERK developer documentation consulté le
  2. Stripe — Receive Stripe events in your webhook endpoint (duplicates, ordering, signatures) consulté le
  3. Stripe — Idempotent requests consulté le

Commencer l'intégration

Lire le démarrage rapide Référence

À lire ensuite