Een goede API is voorspelbaar, geversioneerd en gedocumenteerd. Kies REST voor de meeste CRUD-platforms en GraphQL alleen als clients sterk wisselende datavormen nodig hebben. Beveilig met OAuth2 of token-auth, voeg rate-limiting toe vanaf dag een, versioneer via de URL (/v1/) en documenteer met OpenAPI. Bij NedDev draaien API's op Laravel 12, met Sanctum voor auth en automatische OpenAPI-specs.
Negen van de tien API-problemen die wij in audits tegenkomen, gaan niet over snelheid. Ze gaan over inconsistentie. Een endpoint geeft 200 bij een fout, een ander gooit een lege null, en versie-breuken landen ongemerkt in productie. Een API is een contract tussen jou en iedereen die hem aanroept. Behandel het zo, en het overgrote deel van je integratie-ellende verdwijnt.
De meeste platforms die wij bouwen draaien op REST. Het is voorspelbaar, cachebaar via HTTP, en elke developer begrijpt het zonder uitleg. Voor ClaimHandler was REST de logische keuze: dossiers, documenten en gebruikers zijn duidelijk afgebakende resources met voorspelbare relaties. Je weet precies welke URL welke data teruggeeft.
GraphQL pakt een echt probleem aan, maar een heel specifiek probleem: clients die sterk wisselende datavormen nodig hebben en je anders tien round-trips zou laten maken. Denk aan een mobiele app, een dashboard en een widget die elk een andere subset van dezelfde data willen ophalen. In dat scenario voorkomt GraphQL over-fetching en under-fetching. Zonder dat probleem voegt GraphQL vooral complexiteit toe: HTTP-caching werkt niet meer vanzelf, rate-limiting op basis van query-kosten is een vak apart, en een onbedoeld zware query kan je database platleggen.
Een tussenweg die we steeds vaker zien: REST voor het merendeel, met een enkel GraphQL-endpoint voor het dashboard dat echt flexibele queries nodig heeft. Je hoeft niet religieus voor één kamp te kiezen.
Versioneer vanaf de eerste regel code. Wij zetten de versie in de URL: /api/v1/dossiers. Dat is zichtbaar, debugbaar in logs, en je kunt v2 naast v1 draaien zonder bestaande clients te breken. Header-based versioning klinkt eleganter maar is in de praktijk lastiger te debuggen: je ziet in een logregel niet meteen welke versie werd aangeroepen. Houd het simpel en zichtbaar.
Een breaking change verdient een duidelijke deprecation-strategie. Kondig v1 aan als verouderd, geef clients een termijn van bijvoorbeeld zes maanden, en stuur in die periode een Deprecation-header mee zodat integrators het in hun eigen logs zien aankomen. Stilletjes een veld verwijderen is de snelste manier om het vertrouwen van je integratiepartners te verspelen.
Voor authenticatie gebruiken wij in Laravel 12 standaard Sanctum voor first-party clients en token-auth of OAuth2 voor third-party integraties. De regel is hard: geen enkel endpoint is publiek tenzij dat expliciet de bedoeling is. Default deny, niet default allow. Een vergeten autorisatie-check op één endpoint is genoeg voor een datalek, dus wij testen autorisatie net zo serieus als functionaliteit.
Rate-limiting hoort er vanaf dag een in, niet als het misgaat maar ervoor. Een paar concrete grenzen die in de praktijk werken:
Retry-After header, zodat goedbedoelende clients netjes kunnen wachten in plaats van te blijven hameren.Een ongedocumenteerde API kost je elke integratie dubbel zoveel tijd. Wij genereren OpenAPI-specs automatisch uit de code, zodat de documentatie nooit veroudert ten opzichte van de werkelijkheid. Het grootste gevaar bij handgeschreven docs is precies dat: ze raken achter, een developer vertrouwt erop, en de integratie faalt op een manier die uren kost om te vinden. Een integrerende developer kan met een actuele OpenAPI-spec binnen een uur zijn eerste call maken in plaats van een halve dag te raden.
Error-responses moeten consistent zijn. Eén vorm, altijd. Bijvoorbeeld een error-object met een machine-leesbare code, een mens-leesbare message en optioneel details per veld. Gebruik HTTP-statuscodes zoals bedoeld: 400 voor validatiefouten, 401 voor ontbrekende auth, 403 voor onvoldoende rechten, 404 voor niet bestaande resources, 422 voor semantische validatie. Een 200 met een foutmelding verstopt in de body is een bug die elke client dwingt om de body te parsen voordat hij weet of iets gelukt is.
Logging hoort erbij. Wij loggen elke server-side fout met context: welke gebruiker, welk endpoint, een hash van de payload. Zo is een klant-melding traceerbaar zonder dat je gevoelige data in je logs zet. Bij Lexi en IndexNu bespaart die discipline uren debugwerk per incident, omdat je niet hoeft te reconstrueren wat er gebeurde maar het gewoon kunt teruglezen.
Een productie-klare API als onderdeel van een SaaS-platform zit bij NedDev in de range van €15.000 tot €60.000, afhankelijk van het aantal domeinen, de complexiteit van de autorisatie en het aantal externe integraties. Een losse API-laag bovenop een bestaand systeem is aanzienlijk goedkoper. De grootste kostenbesparing zit niet in de bouw maar in het onderhoud: een API die vanaf het begin geversioneerd, gedocumenteerd en consistent is, kost jaren later een fractie aan onderhoud vergeleken met een API die organisch is gegroeid. Wil je weten welke aanpak bij jouw systeem past? Bekijk onze API-development dienst of vraag een audit aan.
Nee, het is anders. GraphQL lost het probleem op van clients die wisselende datavormen nodig hebben en anders veel round-trips zouden maken. Voor de meeste CRUD-platforms met stabiele resources is REST simpeler, beter cachebaar en makkelijker te beveiligen. Wij starten standaard met REST en migreren alleen waar GraphQL echt waarde toevoegt.
Zet de versie in de URL, bijvoorbeeld /api/v1/. Wanneer een breaking change nodig is, draai je v2 naast v1 en geef je bestaande clients tijd om te migreren met een duidelijke deprecation-datum. Zo blijven oude integraties werken terwijl nieuwe features beschikbaar komen.
Zonder rate-limiting is je API kwetsbaar voor brute-force en kan een enkele client je server platleggen. Achteraf toevoegen betekent dat je clients moet bijsturen die al gewend zijn aan onbeperkte calls. Begin met grenzen zoals 60 requests per minuut en strengere limieten op login-endpoints.