Nordlet

← Blog

Een accounting-API bouwen die een audit overleeft

Een praktische gids voor de beveiligings- en auditcontroles die een financiële API nodig heeft voordat Nederlandse bedrijven hun boekhouding eraan toevertrouwen.

Nordlet Team · · 11 min lezen

Een accounting-API die een 200 OK retourneert op een betalingsopdracht, vertelt je eigenlijk niets. Die respons bevestigt immers niet of de boeking daadwerkelijk in het grootboek is vastgelegd, of de actor bevoegd was om de handeling uit te voeren, of het bedrag de validatie heeft doorstaan, of dat iemand met de juiste autoriteit de boeking heeft goedgekeurd. Voor bedrijven in Nederland, waar de Belastingdienst verwacht dat gegevens te reconstrueren zijn en zeven jaar lang worden bewaard, is de kloof tussen "het verzoek is geslaagd" en "de administratie klopt" precies de plek waar audits misgaan.

Auditklaar zijn is een operationeel Ontwerpdoel, geen certificaat. Het betekent dat de API een volledige keten bewaart: van geauthenticeerde actor tot geautoriseerde actie, gevalideerde toestandsverandering, goedkeuring, grootboekresultaat en fraudebestendig bewijs. Alles hieronder gaat over het weloverwogen bouwen van die keten, in plaats van te vertrouwen op de veronderstelling dat authenticatie en TLS het wel oplossen.

Wat een accounting-API "auditklaar" maakt

Een auditor die een transactie reconstrueert, moet een specifieke reeks vragen kunnen beantwoorden. Wie heeft de transactie gestart? Hadden ze daar toestemming voor? Heeft de wijziging de boekhoudkundige validatie doorstaan? Wie heeft goedkeuring verleend? Wat heeft het grootboek geregistreerd? Kan dat record achteraf worden aangepast zonder sporen achter te laten?

Als je API al deze zes vragen niet kan beantwoorden vanuit de eigen logs en het datamodel, is deze niet auditklaar, hoe netjes de code er ook uitziet. De meeste API's handelen de eerste vraag goed af en de rest een stuk minder.

De controles die dit gat dichten, vallen uiteen in een aantal groepen: expliciete boekhoudkundige statussen, gelaagde autorisatie, afgebakende authenticatie, idempotente schrijfopdrachten, server-side validatie, functiescheiding en fraudebestendige logging. Ze versterken elkaar onderling. Zwakke autorisatie ondermijnt namelijk een sterk auditlogboek, omdat je er dan niet meer op kunt vertrouwen dat de gelogde actor überhaupt bevoegd was om de actie uit te voeren.

Modelleer boekhoudkundige statussen voordat je eindpunten ontwerpt

De meest gemaakte ontwerpfout is het behandelen van elk financieel record als een vrij bewerkbaar object met create, read, update en delete. De boekhouding werkt zo niet, en een auditor zal het meteen opmerken als een definitieve journaalpost stilletjes kan worden overschreven.

Elke financieel materiële bron heeft een expliciete toestandsmachine (state machine) nodig. Een journaalpost of betaling doorloopt doorgaans de volgende stappen:

draft → submitted → approved → posted → settled

Correcties draaien dat pad niet terug. Een geboekte post die niet klopt, krijgt een gekoppelde correctieboeking of een compenserende aanpassing. Het origineel blijft intact.

Een werkbare set regels:

  • Concepten (drafts) kunnen worden bewerkt door geautoriseerde gebruikers.
  • Ingediende records kunnen alleen worden bewerkt door rollen met de juiste rechten, of worden teruggestuurd naar de conceptfase.
  • Goedgekeurde records vereisen een gecontroleerde wijziging en een nieuwe goedkeuring.
  • Geboekte records kunnen niet worden overschreven of verwijderd, maar alleen worden gecorrigeerd of aangepast.
  • Wijzigingen in een afgesloten periode vereisen verhoogde autorisatie, een opgegeven reden en een auditevent.

Een poging tot een illegale overgang, zoals het bewerken van een geboekte post, moet een stabiele foutmelding retourneren en toch een auditrecord wegschrijven. Die mislukte poging is immers ook bewijs.

Hier bewijst een onveranderlijk dubbel boekhoudkundig grootboek (immutable double-entry ledger) zijn waarde. Het grootboek van Nordlet is zo opgebouwd dat elke transactie landt als een sluitende, permanente boeking, waarbij de balans op het moment van commit door een databasetrigger wordt afgedwongen. Correcties vinden plaats via correctieboeking in plaats van overschrijving. Die beperking voelt tijdens de ontwikkeling soms streng aan, maar verandert in de praktijk in het onderdeel waar je accountant tijdens een audit blind op durft te vertrouwen.

Autoriseer elk verzoek, verifieer niet alleen de authenticatie

Authenticatie bewijst wie er belt. Het zegt echter niets over de vraag of die beller een specifieke factuur, journaalpost of rechtspersoon mag inzien of bewerken. Het OWASP API Security Project plaatst gebrekkige autorisatie op objectniveau (broken object-level authorization) bovenaan zijn risicolijst, juist omdat API's object-ID's blootstellen die toegang over tenants heen vergemakkelijken als controles ontbreken.

Elk verzoek aan een financiële API moet worden geautoriseerd op basis van een combinatie van factoren, niet slechts op een token:

  • geauthenticeerde actor
  • clienttoepassing of serviceaccount
  • tenant
  • rechtspersoon
  • bron-ID (resource ID)
  • gevraagde bewerking
  • huidige status van de bron
  • bedrag of transactiedrempel

Twee praktische regels zijn belangrijker dan de rest. Ten eerste: leid de context van de tenant en de gebruiker af uit de geauthenticeerde identiteit en verwijs elke door de client aangeleverde tenant- of rolclaim die daarmee in conflict is direct naar de prullenbak. Een aanroeper mag nooit zelf kunnen bepalen voor welk bedrijf die optreedt. Ten tweede: hanteer een 'deny-by-default'-beleid. Als geen enkel beleid een actie expliciet toestaat, mislukt deze.

Test beide richtingen. Zowel horizontale toegang, waarbij de ene tenant bij de data van een andere tenant kan komen, als verticale toegang, waarbij een gewone gebruiker bij goedkeurings-, boekings- of exportfuncties kan komen. Beide komen veel voor en beide zijn catastrofaal voor boekhoudgegevens.

Het rolmodel van Nordlet, met rollen voor eigenaar, beheerder, accountant, manager, ontwikkelaar en kijker verdeeld over meerdere bedrijven onder één account, is ontworpen om deze scheiding afdwingbaar te maken in plaats van vrijblijvend. Een ontwikkelaarsrol die conceptfacturen mag aanmaken, moet nu eenmaal geen betalingen kunnen vrijgeven.

Koppel tokens aan bedrijfscapaciteiten, niet aan CRUD-werkwoorden

Gebruik voor gedelegeerde toegang de huidige beveiligingsrichtlijnen voor OAuth 2.0 in plaats van herbruikbare wachtwoorden of brede, statische API-sleutels. RFC 9700 geldt als de huidige Best Current Practice en stelt duidelijke eisen aan clients en autorisatieservers: gevalideerde redirect-URI's, PKCE waar van toepassing, controle op uitgever (issuer) en doelgroep (audience), korte levensduur van accesstokens en de rotatie van refreshtokens inclusief intrekking (revocation).

De beslissing over scopes laat zien hoe specifiek er over boekhouding is nagedacht. Algemene scopes zoals read en write zijn nagenoeg nutteloos voor functiescheiding. Scopes moeten gekoppeld zijn aan specifieke capaciteiten:

  • journal:create en journal:approve zijn afzonderlijke scopes.
  • Het aanmaken van een betalingsopdracht verleent geen toestemming om deze vrij te geven.
  • Exportrechten staan los van leesrechten, omdat bulkexport een potentieel lek voor data-exfiltratie vormt.

Wees nauwkeurig over waar een product zich op die schaal bevindt. De API-sleutels van Nordlet bevatten scopes per module, zoals sales:read en sales:write, die bij elke actie worden gecontroleerd. Dit scheidt modules en lees- van schrijfrechten, maar nog niet het aanmaken van het goedkeuren. Waar je die fijnmazigere splitsing vandaag de dag nodig hebt, dien je dat in je eigen service voorafgaand aan de aanroep af te dwingen.

Voor hoogwaardige operaties is het de moeite waard om te beoordelen of het FAPI 2.0 Security Profile van toepassing is. Dit profiel is ontworpen voor API's die gevoelige financiële gegevens beschermen en biedt sterkere garanties dan de standaard OAuth. De meeste mkb-boekhoudintegraties hebben dit volledige profiel niet direct nodig, maar voor betalingsvrijgaven en bankkoppelingen is het zeker het overwegen waard.

De wachtwoordloze aanmeldmethode van Nordlet via eenmalige e-maillinks lost het probleem van herbruikbare wachtwoorden voor menselijke gebruikers op, wat weer een set inloggegevens minder betekent om te roteren, te laten lekken of te verifiëren via phishing.

Maak financiële schrijfopdrachten idempotent

Netwerken vallen midden in een verzoek uit. Een client verstuurt een betalingsopdracht, de verbinding verbreekt voordat het antwoord binnen is, en de client probeert het opnieuw. Zonder bescherming heb je nu per ongeluk twee betalingen uitgevoerd.

Idempotentiesleutels (idempotency keys) lossen dit op. De client stuurt een unieke sleutel mee met elke schrijfopdracht; de server slaat de sleutel en het bijbehorende resultaat op. Een nieuwe poging met dezelfde sleutel retourneert het oorspronkelijke resultaat in plaats van een tweede invoer aan te maken. Nordlet accepteert een Idempotency-Key-header bij elke muterende aanroep, speelt de opgeslagen respons opnieuw af bij een herhalingspoging met dezelfde payload, en wijst dezelfde sleutel met een gewijzigde payload resoluut af. Elke accounting-API die deze functie overslaat, produceert vroeg of laat dubbele grootboekposten die iemand handmatig recht moet breien.

Combineer dit met server-side validatie. Vertrouw er nooit op dat de client controleert of debet en credit gelijk zijn, dat een btw-tarief geldig is voor het betreffende land en de periode, of dat een grootboekrekening daadwerkelijk bestaat. Validatie vindt plaats op de server, voorafgaand aan de statusovergang, en een afgewezen schrijfopdracht levert een stabiele foutmelding en een auditrecord op.

Fraudebestendige auditlogs en de Nederlandse bewaarplicht

Het auditlogboek vormt de bewijslaag en stelt andere eisen dan reguliere bedrijfsdata. Het hoeft geen geheimen of volledige betalingsgegevens te bevatten, maar legt wel de autorisatiebeslissing, de beleidsversie, de actor, het object, de bewerking, de vorige en nieuwe status en de reden (reason code) vast.

De cruciale eigenschap hierbij is fraudebestendigheid (tamper-evidence). Als een beheerder stilletjes auditrecords kan bewerken of verwijderen, bewijst het logboek helemaal niets. Append-only opslag, cryptografische aaneenschakeling (chaining) of write-once-retention (WORM) zijn stuk voor stuk oplossingen hiervoor. Het punt is dat elke wijziging aantoonbaar moet zijn.

De bewaarplicht verdient een eigen beleid, los van het reguliere verwijderen van bedrijfsdata. In Nederland geldt voor administratieve gegevens een algemene bewaartermijn van zeven jaar, en voor gegevens met betrekking tot onroerende zaken loopt dit op tot tien jaar. Je reguliere workflows voor dataverwijdering en AVG-verzoeken (GDPR) mogen er absoluut niet toe leiden dat records of auditbewijs worden vernietigd waar nog een wettelijke bewaarplicht op rust. Definieer regels voor wettelijke bewaring (legal hold), archivering en verwijdering van auditbewijs onafhankelijk van elkaar en koppel ze aan de rechtsgebieden waarin je actief bent.

Blokkering van periodes (period locking) ondersteunt dit op boekhoudkundig niveau. Zodra een maand is afgesloten, kunnen de boekingen daarin niet meer worden gewijzigd zonder verhoogde autorisatie en een gelogde reden. Nordlet dwingt periodeblokkering af, zodat afgesloten maanden ook echt gesloten blijven. Elke boeking met een datum binnen een vergrendelde periode wordt geweigerd, zelfs via de API. Dit is een van de eerste dingen die een Nederlandse auditor controleert.

Beveilig de randen: webhooks, exports en integraties

De kern-API is doorgaans het best verdedigde onderdeel van een systeem. De randen lekken daarentegen vaak.

Webhooks vormen een risico op vervalste verzoeken (forged requests). Een event zoals sale_invoice.paid moet worden ondertekend zodat de ontvanger kan verifiëren dat het daadwerkelijk van jou afkomstig is. Ontvangers moeten leveringen behandelen als at-least-once en de event-ID gebruiken voor ontdubbeling (deduplication). Nordlet ondertekent elke webhooklevering met een HMAC-handtekening over de ruwe body en stuurt mislukte leveringen opnieuw in met exponentiële backoff. Een ontvanger moet de handtekening dus verifiëren en ontdubbelen op basis van de event-ID in plaats van uit te gaan van exactly-once delivery.

Exports zijn een kanaal voor bulk-data-exfiltratie. Rapportage-exports in XLSX, PDF of JSON halen in één handeling grote hoeveelheden financiële data op, en vereisen daarom hun eigen permissies, limieten (rate limits) en auditlogging. Externe integraties die je afneemt, moeten worden behandeld als niet-vertrouwde invoer en worden gevalideerd op dezelfde manier als je directe clientverzoeken controleert.

Audit-gereedheidschecklist voor een Nederlandse accounting-API

Gebruik deze lijst voordat je beweert dat een integratie auditklaar is:

  • Expliciete toestandsmachine op elk financieel object; geboekte posten kunnen niet worden overschreven
  • Autorisatie op objectniveau en rechtspersoonniveau bij elk verzoek, deny-by-default
  • Tenant- en rolcontext afgeleid uit het token, niet uit clientclaims
  • OAuth 2.0 volgens RFC 9700; scopes op basis van capaciteiten; gescheiden aanmaak- en goedkeuringsrechten
  • Functiescheiding afgedwongen in rollen, niet alleen op papier gedocumenteerd
  • Idempotentiesleutels op alle financiële schrijfopdrachten
  • Server-side boekhoud- en btw-validatie voorafgaand aan statusovergangen
  • Append-only, fraudebestendig auditlogboek voorzien van redenen (reason codes)
  • Bewaar- en legal-hold-regels gekoppeld aan Nederlandse perioden (zeven jaar, tien jaar voor onroerend goed)
  • Periodesluiting op afgesloten maanden
  • Ondertekende webhooks met ontdubbeling; afgeschermde, gelimiteerde en gelogde exports

Wat wij als eerste zouden bouwen

Als we morgen accounting in een Nederlands platform zouden inbouwen, begonnen we met het toestandsmodel en de autorisatie op objectniveau, nog voordat we een enkel bedrijfseindpunt schreven. Die twee beslissingen leggen namelijk al het onderliggende vast, en ze later achteraf inbouwen in een systeem dat grootboekposten behandelde als bewerkbare rijen is ronduit pijnlijk. Idempotentie en het auditlogboek komen daarna, omdat ze vroeg in het proces goedkoop zijn toe te voegen en achteraf, wanneer er al data stroomt, juist duur.

De rest — afgeschermde tokens, ondertekende webhooks, periodeblokkering — volgt een stuk eenvoudiger zodra het fundament staat. Je kunt dit alles bovendien uitvoeren tegen een sandbox-bedrijf voordat er ook maar één productiegegeven wordt aangeraakt.

FAQ

Betekent een auditklare API dat het bedrijf ook direct compliant is?

Nee, en het is goed om hier nauwkeurig in te zijn. Audit-gereedheid is een ontwerpeigenschap van het systeem: het grootboek, de controles en de bewijsketen zijn zo opgebouwd dat een audit succesvol kan verlopen. Naleving van een specifiek belasting-, boekhoud- of beveiligingsframework is een afzonderlijke beoordeling die die controles koppelt aan een benoemde standaard. Een goed gebouwde API maakt het nalevingstraject een stuk eenvoudiger, maar vervangt het niet.

Hoe lang moeten administratieve gegevens in Nederland worden bewaard?

De algemene verplichting is zeven jaar voor administratieve gegevens, oplopend tot tien jaar voor gegevens die gekoppeld zijn aan onroerende zaken. Bouw bewaar- en legal-hold-regels die je reguliere verwijderingsworkflows niet kunnen overschrijven.

Is een statische API-sleutel voldoende voor een financiële integratie?

Voor server-to-server-automatisering met een zeer beperkte scope kan het werken, maar herbruikbare statische sleutels zijn moeilijk te roteren en gevaarlijk als ze uitlekken. Voor gedelegeerde toegang en elke stroom waar mensen bij betrokken zijn, heeft OAuth 2.0 met kortlevende tokens en beperkte scopes de voorkeur.

Waarom is idempotentie zo belangrijk specifiek voor de boekhouding?

Omdat een dubbele schrijfopdracht in de meeste systemen hoogstens irritant is, terwijl een dubbele schrijfopdracht in de boekhouding een fout bedrag in de boeken oplevert dat iemand met de hand moet opsporen en corrigeren. Idempotentiesleutels maken herhalingspogingen veilig in plaats van risicovol.

Verder lezen