Nordlet

← Blog

Building an Accounting API That Survives an Audit

A practical guide to the security and audit controls a financial API needs before Dutch businesses trust it with their books.

Nordlet Team · · 12 min de lecture

Une API de comptabilité qui renvoie un code 200 OK lors de l'enregistrement d'un paiement ne vous apprend pratiquement rien. Elle ne confirme pas que le grand livre (ledger) a enregistré l'écriture, que l'acteur était autorisé à l'effectuer, que le montant a passé la validation, ni qu'une personne habilitée l'a approuvée. Pour les entreprises aux Pays-Bas, où l'administration fiscale exige que les documents soient reconstructibles et conservés pendant sept ans, cet écart entre « la requête a réussi » et « la comptabilité est correcte » est précisément le point où les audits échouent.

Être prêt pour un audit (audit-ready) est un objectif de conception opérationnelle, pas un certificat. Cela signifie que l'API préserve une chaîne complète : acteur authentifié vers action autorisée, puis changement d'état validé, approbation, résultat dans le grand livre et preuves infalsifiables. Tout ce qui suit vise à construire cette chaîne de manière délibérée, plutôt que de supposer que l'authentification et TLS suffisent.

Ce qui rend une API de comptabilité « prête pour l'audit »

Un auditeur qui reconstitue une transaction doit répondre à une séquence précise de questions. Qui l'a initiée ? En avait-il le droit ? La modification a-t-elle passé la validation comptable ? Qui l'a approuvée ? Qu'est-ce que le grand livre a enregistré ? Cet enregistrement peut-il être altéré après coup sans laisser de traces ?

Si votre API ne peut pas répondre à ces six questions à partir de ses propres journaux (logs) et de son modèle de données, elle n'est pas prête pour l'audit, peu importe la propreté du code. La plupart des API gèrent bien la première question et mal le reste.

Les contrôles qui comblent cet écart se répartissent en plusieurs catégories : état comptable explicite, autorisation multicouche, authentification délimitée, écritures idempotentes, validation côté serveur, séparation des tâches et journalisation infalsifiable. Ils se renforcent mutuellement. Une autorisation faible sape un journal d'audit solide, car vous ne pouvez plus garantir que l'acteur enregistré était habilité à effectuer l'action.

Modéliser les états comptables avant de modéliser les points de terminaison

L'erreur de conception la plus fréquente consiste à traiter chaque enregistrement financier comme un objet librement modifiable doté des actions create, read, update, delete. La comptabilité ne fonctionne pas ainsi, et un auditeur remarquera immédiatement si une écriture de journal comptabilisée peut être modifiée en secret.

Chaque ressource ayant un impact financier nécessite une machine à états explicite. Une écriture de journal ou un paiement passe généralement par les étapes suivantes :

draft → submitted → approved → posted → settled

Les corrections ne reviennent pas en arrière sur ce chemin. Une écriture comptabilisée qui est erronée fait l'objet d'une extourne (reversal) liée ou d'un ajustement compensatoire. L'original reste intact.

Un ensemble de règles viables :

  • Les brouillons (drafts) peuvent être modifiés par les utilisateurs autorisés.
  • Les enregistrements soumis ne peuvent être modifiés que par les rôles autorisés, ou renvoyés au statut de brouillon.
  • Les enregistrements approuvés nécessitent une modification contrôlée et une nouvelle approbation.
  • Les enregistrements comptabilisés ne peuvent être ni écrasés ni supprimés, seulement extournés ou ajustés.
  • Les modifications sur des périodes clôturées nécessitent une autorisation renforcée, un motif explicite et un événement d'audit.

Toute tentative de transition illégale, par exemple la modification d'une écriture comptabilisée, doit renvoyer une erreur stable tout en écrivant un événement d'audit. La tentative échouée constitue également une preuve.

C'est là qu'un grand livre en partie double immuable trouve toute sa légitimité. Le grand livre de Nordlet est conçu de telle sorte que chaque transaction arrive sous la forme d'une écriture équilibrée et permanente, l'équilibre étant garanti par un déclencheur (trigger) de base de données au moment de la validation (commit), tandis que les corrections s'effectuent par des extournes plutôt que par des réécritures. Cette contrainte, qui semble restrictive pendant le développement, devient la garantie de confiance pour votre comptable lors d'un audit.

Autoriser chaque requête, pas seulement l'authentifier

L'authentification prouve qui émet l'appel. Elle ne dit rien sur le droit de cet appelant à toucher une facture, un journal ou une entité juridique en particulier. Le projet de sécurité des API de l'OWASP place l'autorisation brisée au niveau des objets en tête de sa liste des risques, précisément parce que les API exposent des identifiants d'objets qui facilitent l'accès entre locataires (tenants) en l'absence de contrôles.

Chaque requête adressée à une API financière doit être autorisée sur la base d'une combinaison de facteurs, et non d'un simple jeton (token) :

  • acteur authentifié ;
  • application cliente ou compte de service ;
  • locataire (tenant) ;
  • entité juridique ;
  • identifiant de la ressource ;
  • opération demandée ;
  • état actuel de la ressource ;
  • montant ou seuil de transaction.

Deux règles pratiques l'emportent sur le reste. Premièrement, déduisez le contexte du locataire et de l'utilisateur à partir de l'identité authentifiée, et rejetez toute revendication (claim) de rôle ou de locataire fournie par le client qui serait en contradiction. Un appelant ne doit jamais pouvoir affirmer de lui-même quelle entreprise il représente. Deuxièmement, appliquez le refus par défaut (deny-by-default). Si aucune politique n'autorise explicitement une action, celle-ci échoue.

Testez les deux directions. L'accès horizontal, où un locataire accède aux données d'un autre locataire, et l'accès vertical, où un utilisateur ordinaire accède à des fonctions d'approbation, de comptabilisation ou d'exportation. Ces deux failles sont fréquentes et catastrophiques pour des données comptables.

Le modèle de rôles de Nordlet, qui propose des rôles de propriétaire (owner), administrateur (admin), comptable (accountant), gestionnaire (manager), développeur (developer) et lecteur (viewer) répartis sur plusieurs entreprises au sein d'un même compte, a précisément pour but de rendre cette séparation effective plutôt que théorique. Un rôle de développeur capable de créer des factures à l'état de brouillon ne doit pas pouvoir émettre des paiements.

Délimiter les jetons aux capacités métier, et non aux verbes CRUD

Pour les accès délégués, suivez les recommandations de sécurité actuelles d'OAuth 2.0 plutôt que d'utiliser des mots de passe réutilisables ou de larges clés API statiques. La norme RFC 9700 constitue la meilleure pratique actuelle (Best Current Practice) et fixe des exigences claires pour les clients et les serveurs d'autorisation : URI de redirection validées, utilisation de PKCE le cas échéant, vérifications de l'émetteur et de l'audience, durées de vie courtes des jetons d'accès et rotation des jetons de rafraîchissement (refresh tokens) avec révocation.

C'est au moment de définir les périmètres (scopes) que la réflexion proprement comptable s'exprime. Les périmètres génériques tels que read et write s'avèrent presque inutiles pour la séparation des tâches. Les périmètres doivent correspondre à des capacités métiers :

  • journal:create et journal:approve constituent des périmètres distincts.
  • La création d'un ordre de paiement ne confère pas le droit de l'exécuter.
  • L'autorisation d'exportation est distincte de celle de lecture, car l'exportation en masse représente un vecteur de fuite de données.

Soyez précis quant à la position de votre produit sur cette échelle. Les clés API de Nordlet intègrent des périmètres par module, tels que sales:read et sales:write, vérifiés à chaque action. Cela sépare les modules et les opérations de lecture de celles d'écriture, sans toutefois distinguer la création de l'approbation. Si vous avez besoin d'une telle finesse aujourd'hui, appliquez-la dans votre propre service en amont de l'appel.

Pour les opérations à forte valeur, il convient d'évaluer si le profil de sécurité FAPI 2.0 s'applique. Conçu pour les API protégeant des données financières sensibles, il offre des garanties supérieures à celles d'OAuth de base. La plupart des intégrations comptables pour PME n'auront pas besoin de tout le profil, mais les flux de décaissement et de connexion bancaire justifient qu'on s'y intéresse.

La connexion sans mot de passe de Nordlet via des liens e-mail à usage unique élimine le problème du mot de passe réutilisable pour les utilisateurs humains, ce qui réduit d'autant le nombre d'identifiants à renouveler, risquant la fuite ou ciblés par hameçonnage.

Rendre les écritures financières idempotentes

Les réseaux connaissent des pannes au milieu des requêtes. Un client envoie un ordre de paiement, la connexion est coupée avant que la réponse n'arrive, et le client relance sa requête. Sans protection, vous disposez désormais de deux paiements.

Les clés d'idempotence (idempotency keys) résolvent ce problème. Le client envoie une clé unique avec chaque écriture ; le serveur enregistre la clé et son résultat. Une nouvelle tentative avec la même clé renvoie le résultat d'origine au lieu de créer un second enregistrement. Nordlet accepte un en-tête Idempotency-Key sur chaque appel de modification, rejouant la réponse stockée lors d'une nouvelle tentative avec la même charge utile (payload) et rejetant la même clé si la charge utile a changé. Toute API de comptabilité qui fait l'impasse sur cette fonctionnalité finira par générer des doublons dans le grand livre que quelqu'un devra démêler à la main.

Associez cela à une validation côté serveur. Ne faites jamais confiance au client pour vérifier que les débits égalent les crédits, qu'un taux de TVA est valide pour le pays et la période, ou qu'un compte existe. La validation s'exécute sur le serveur, avant la transition d'état, et toute écriture rejetée produit une erreur stable ainsi qu'un enregistrement d'audit.

Pistes d'audit infalsifiables et conservation aux Pays-Bas

Le journal d'audit constitue la couche de preuve et obéit à des exigences différentes de celles des données commerciales ordinaires. Il doit enregistrer la décision d'autorisation, la version de la politique, l'acteur, l'objet, l'opération, l'état précédent, le nouvel état et le code de motif, sans jamais stocker de secrets ou d'informations de paiement complètes.

La propriété critique est l'infalsificabilité (tamper-evidence). Si un administrateur peut modifier ou supprimer discrètement des journaux d'audit, le journal ne prouve plus rien. Le stockage en mode ajout seul (append-only), le chaînage cryptographique ou la conservation inscriptible une seule fois (write-once) répondent à ce besoin. L'essentiel est qu'une modification puisse être détectée.

La conservation (retention) mérite sa propre politique, indépendante de la suppression des données commerciales. Aux Pays-Bas, la période de conservation générale des documents administratifs est de sept ans, et s'élève à dix ans pour les documents relatifs à des biens immobiliers. Vos processus habituels de suppression de données et de mise en conformité RGPD ne doivent pas pouvoir détruire des documents ou des preuves d'audit couverts par une règle de conservation légale. Définissez de manière autonome les règles de gel légal (legal hold), d'archivage et de suppression pour les preuves d'audit, et alignez-les sur les juridictions dans lesquelles vous exercez.

Le verrouillage des périodes (period locking) soutient cette démarche au niveau comptable. Une fois un mois clôturé, les écritures qu'il contient ne peuvent plus être modifiées sans une autorisation renforcée et un motif journalisé. Nordlet applique le verrouillage des périodes afin que les mois clôturés restent fermés, rejetant toute écriture datée d'une période verrouillée, y compris via l'API. C'sé l'un des premiers points vérifiés par un auditeur néerlandais.

Sécuriser les frontières : webhooks, exportations et intégrations

L'API principale constitue généralement la partie la mieux défendue du système. Les failles se situent aux frontières.

Les webhooks comportent un risque de requête falsifiée. Un événement comme sale_invoice.paid doit être signé pour que le destinataire puisse vérifier qu'il provient bien de vous. Les destinataires doivent traiter la livraison comme étant au moins unique (at-least-once) et utiliser l'identifiant de l'événement pour la déduplication. Nordlet signe chaque livraison de webhook avec une signature HMAC sur le corps brut (raw body) et relance les livraisons échouées avec un recul exponentiel (exponential backoff). Le destinataire doit donc vérifier la signature et procéder à la déduplication par identifiant d'événement plutôt que de supposer une livraison exactement unique (exactly-once).

Les exportations représentent un vecteur de fuite de données en masse. Les rapports exportés au format XLSX, PDF ou JSON rassemblent de grands volumes de données financières en une seule opération ; ils nécessitent par conséquent des permissions spécifiques, des limites de débit (rate limits) et une journalisation d'audit dédiée. Les intégrations tierces que vous consommez doivent être traitées comme des données non fiables et validées de la même manière que les requêtes directes de vos clients.

Liste de contrôle de préparation à l'audit pour une API de comptabilité néerlandaise

Vérifiez ces points avant d'affirmer qu'une intégration est prête pour l'audit :

  • Machine à états explicite sur chaque ressource financière ; impossibilité d'écraser les écritures comptabilisées
  • Autorisation au niveau des objets et de l'entité juridique sur chaque requête, avec refus par défaut
  • Contexte du locataire et du rôle dérivé du jeton, et non des revendications (claims) du client
  • OAuth 2.0 selon la RFC 9700 ; périmètres basés sur les capacités ; séparation de la création et de l'approbation
  • Séparation des tâches appliquée dans les rôles, et pas seulement documentée
  • Clés d'idempotence sur toutes les écritures financières
  • Validation comptable et de TVA côté serveur avant les transitions d'état
  • Journal d'audit infalsifiable en mode ajout seul, doté de codes de motifs
  • Règles de conservation et de gel légal alignées sur les périodes néerlandaises (sept ans, dix pour l'immobilier)
  • Verrouillage des périodes sur les mois clôturés
  • Webhooks signés avec déduplication ; exportations ciblées, limitées en débit et journalisées

Ce que nous construirions en premier lieu

Si nous devions intégrer la comptabilité dans une plateforme néerlandaise dès demain, nous commencerions par le modèle d'états et l'autorisation au niveau des objets, avant d'écrire le moindre point de terminaison métier. Ces deux décisions conditionnent tout le reste, et les intégrer a posteriori dans un système qui traitait les lignes du grand livre comme des tableaux modifiables s'avère extrêmement difficile. L'idempotence et le journal d'audit viennent ensuite, car il est peu coûteux de les ajouter tôt et très onéreux de le faire une fois que les données circulent.

Le reste (jetons délimités, webhooks signés, verrouillage des périodes) s'installe plus naturellement une fois les fondations en place. L'ensemble peut être testé sur une entreprise bac à sable (sandbox company) avant le moindre contact avec des données de production.

FAQ

Est-ce qu'une API prête pour l'audit garantit la conformité de l'entreprise ?

Non, et il convient d'être précis sur ce point. La préparation à l'audit est une propriété de conception du système : le grand livre, les contrôles et la chaîne de preuves sont construits pour qu'un audit puisse aboutir. La conformité à un cadre fiscal, comptable ou de sécurité spécifique constitue une évaluation distincte qui associe ces contrôles à une norme nommée. Une API bien conçue facilite le travail de conformité, elle ne le remplace pas.

Pendant combien de temps les documents comptables doivent-ils être conservés aux Pays-Bas ?

L'obligation générale est de sept ans pour les documents administratifs, et s'étend à dix ans pour les documents liés à des biens immobiliers. Mettez en place des règles de conservation et de gel légal que vos processus de suppression ordinaires ne peuvent pas contourner.

Une clé API statique suffit-elle pour une intégration financière ?

Pour de l'automatisation de serveur à serveur avec un périmètre restreint, cela peut fonctionner, mais les clés statiques réutilisables sont difficiles à renouveler et dangereuses en cas de fuite. Pour les accès délégués et tout flux impliquant un utilisateur humain, OAuth 2.0 avec des jetons à courte durée de vie et délimités par capacités constitue une option bien plus solide.

Pourquoi l'idempotence est-elle si importante en comptabilité ?

Parce qu'une écriture en double dans la plupart des systèmes n'est qu'une nuisance, tandis qu'en comptabilité, elle fausse les comptes et nécessite un travail de recherche et d'extourne. Les clés d'idempotence rendent les nouvelles tentatives sûres plutôt que risquées.

Pour aller plus loin