Skip to content

Waarom onze API overal kan schrijven, niet alleen lezen

Ik heb meer weekenden dan ik wil toegeven besteed aan het aan elkaar plakken van tools met nachtelijke scripts, omdat de API waar ik tegenaan wilde schrijven dat niet toeliet. Stripe stuurt een webhook zodra een abonnement verlengt. Mijn oude facturatie-tool liet me met liefde het klantgegeven inlezen, de factuurtemplate, de tarieven. Een factuur aanmaken vanaf de buitenkant met de juiste BTW-code, de juiste PDF-template, en in een afwijkende status pushen naar het klantenportaal, dat ging niet.

Dus eindigde ik met een script dat ongeveer de helft van het werk deed, de rest exporteerde als CSV, en die CSV vervolgens met de hand in de tool uploadde. Dat is geen automatisering. Dat is een parttime admin-baantje verkleed als cron-expressie.

Als je genoeg van dit soort verhalen hoort zie je het patroon. De meeste “API’s” in de SaaS-wereld zijn eigenlijk lees-API’s met een dun schrijfvlak erbovenop voor de meest voor de hand liggende gevallen: een contact aanmaken, een enkele factuur uit een template genereren, een betaling als ontvangen markeren. Zodra je iets specifiekers wil, zoals een factuur met een eigen nummer, een BTW-code per regel, en een afwijkende e-mailtemplate, raakt het schrijfvlak op. Je kunt eromheen lezen, maar je kunt het niet oplossen. De connector-marketplace dekt veel af voor gangbare integraties, vandaar dat iedereen een Zapier-verhaal heeft, maar je kunt er geen echte custom flow op bouwen.

Ik bouwde Rozuro vanuit het tegenovergestelde uitgangspunt. Elke actie die in de UI bestaat is ook een REST-endpoint. Dezelfde auth, dezelfde validatie, dezelfde ledger-writes. Er is geen schaduw-API die meer kan dan de publieke, en de UI mag niets doen wat de API niet kan. Dat klinkt saai als marketingregel, en dat is het ook. Als engineering-keuze verandert het wat je kunt bouwen.

Het concrete voorbeeld waar ik op blijf terugkomen. Stripe-webhook vuurt op een abonnementsverlenging. Een klein Node-script leest de event, roept de Rozuro-API aan om een nieuwe factuur aan te maken met het juiste nummer in de reeks, de juiste BTW-code op basis van het land van de klant, en een eigen e-mailtemplate die de abonnementsperiode bevat. Hetzelfde script pusht de resulterende PDF-URL terug naar het klantenportaal. Het geheel is veertig regels code en nul spreadsheets. De Rozuro-kant draait door precies dezelfde validatie als wanneer een mens door de UI klikt. De ledger-writes zijn identiek. Komt er over vijf jaar een audit, dan ziet de factuur er niet anders uit dan eentje die ik met de hand had gemaakt.

Het principe dat de waarde oplevert is moeilijker uit te leggen dan het voorbeeld, maar het komt hierop neer: write-parity betekent dat geen enkele interface een voorkeurspositie heeft. De UI is gewoon één van de clients. Je eigen scripts zijn volwaardige gebruikers. Je bouwt de workflow die past bij je bedrijf in plaats van je bedrijf te buigen naar de workflow die de SaaS toevallig ondersteunt. Dat is wat een API zou moeten geven, en wat de meeste stilletjes niet doen.

Er zitten eerlijke gaten in. We hebben nog geen OpenAPI-spec voor elk endpoint (zit in de werken, de schema’s zijn nu stabiel genoeg om te publiceren). Een paar van de meer exotische resources hebben endpoints die nog opgeruimd moeten worden voor ze in de docs komen. Het webhook-signing schema is de standaard HMAC-SHA256 over de raw payload, wat prima is, maar de documentatie rond verificatie kan beter. Geen van die dingen is waarom we het zo gebouwd hebben. Ze staan gewoon op de lijst om af te schaven.

Heb je een automatisering die je altijd had willen bouwen maar die nooit lukte omdat de API tekort schoot, dan is dat precies het gesprek dat ik wil hebben — neem contact op.

Liefs, Marten.