bol.com automation

Bouw je eigen retour analyse met de bol API

Maandelijks een overzicht van al je retouren, gekoppeld aan redenen per EAN, gesorteerd op prioriteit. Zodat je ziet welke producten daadwerkelijk je marge opvreten, en waarom.

node.js bol retailer api google sheets maandelijkse cron

Van ruwe API data naar een bruikbare sheet

Vier stappen die je eenmalig opzet en daarna elke maand automatisch draait. Geen handmatige exports meer uit het Partnerplatform.

01
Retouren ophalen via de bol Retailer API
Het script authenticeert via OAuth2 en haalt alle retouren van de afgelopen 30 dagen op. Het blijft pagineren tot een lege response, zo mis je niks.
02
Groeperen per EAN en filteren op drempelwaarde
Alle retouren worden geteld per product. Je stelt zelf de drempel in, bijvoorbeeld meer dan 5 retouren in 30 dagen.
03
Retourredenen mappen naar leesbare tekst
De API geeft codes terug zoals DEFECT of NOT_AS_EXPECTED. Die worden omgezet naar Nederlands, met de frequentie per reden per product.
04
Resultaat in Google Sheet, gesorteerd op prioriteit
Eén tab met alle producten boven de drempel, gesorteerd op aantal retouren. Klaar om door te zetten naar je inkoop of content team.

Een maandelijks overzicht waar je team direct mee aan de slag kan

Geen SaaS abonnement, geen vendor lock-in. Je eigen pipeline, op je eigen infrastructuur, met je eigen data die je zelf houdt.

01
Geprioriteerde lijst
Producten boven je drempel, automatisch gesorteerd op meeste retouren. Je team weet direct waar te beginnen.
02
Redenen in gewone taal
Geen API codes in je sheet, maar leesbare Nederlandse redenen met frequentie per product.
03
Eigen Google Sheet
Vertrouwde interface voor je team. Iedereen kan filteren, sorteren en comments achterlaten zonder training.
04
Automatische maandelijkse run
Eenmaal opgezet draait het script zelf. Je krijgt elke maand een nieuw overzicht zonder dat iemand er naar omkijkt.

De bouwstenen voor deze setup

Bol Retailer API toegang. Via het Partnerplatform aan te vragen. Wordt gekoppeld aan je verkoper account.
Google Cloud account. Voor het aanmaken van een service account dat naar je Sheets kan schrijven. Gratis tier volstaat.
Een Google Sheet. Als bestemming voor de output. Iedereen in je team met toegang kan meekijken.
Server of lokale machine. Een Mac Mini, VPS of cloud scheduler. Iets dat maandelijks iets kan draaien zonder jouw tussenkomst.
Ontwikkelkennis. Ervaring met API integraties, OAuth flows en foutafhandeling. Of iemand die dit voor je bouwt.

De data die je terug krijgt

Dit zijn de kolommen die in je Google Sheet komen te staan. Alles direct leesbaar voor je team.

kolom
EAN en productnaam
Om het product direct te koppelen aan je PIM of content systeem.
kolom
Aantal retouren (30 dagen)
Het totaal aantal retourmeldingen per EAN in de laatste 30 dagen. Dit bepaalt de sortering.
kolom
Retourredenen met frequentie
Bijvoorbeeld: "product defect (4x), voldoet niet aan verwachting (2x), te groot (1x)". Direct leesbaar.
kolom
Fulfilment methode
FBR of FBB, zodat je weet of je zelf of bol de retour afhandelt.
optioneel
Retour ratio
Aantal retouren gedeeld door verkopen in dezelfde periode, als je je verkoop data ook in Sheets hebt staan.
optioneel
Datum van de run
Handig als je historie wilt opbouwen in een losse tab per maand.

Zeven lagen die samen je retour overzicht bouwen

Dit is de architectuur die je script volgt, van authenticatie tot output. Elke laag heeft zijn eigen valkuilen. De meeste problemen ontstaan in de tussenlagen, niet bij het begin of eind. Als een van deze lagen stilletjes faalt, blijft je sheet zich vullen maar met verkeerde data. Dat is gevaarlijker dan een crash.

1
Authenticatie laag met token lifecycle management
De bol API werkt met OAuth2 client credentials flow. Je applicatie wisselt credentials in voor een kortstondig bearer token dat je met elke request meestuurt als Authorization header. De token heeft een TTL van een paar minuten. Bij langere runs of als je pauzeert tussen API calls, verloopt het token midden in je flow. Je script moet zelf bijhouden wanneer het token expiry nadert en proactief een nieuwe requesten, niet reactief na een 401.
Edge case die de meesten missen: bol geeft op het oauth endpoint ook een andere rate limit dan op de resource endpoints. Als je bij elke API call een nieuwe token requestet (de "veilige" aanpak) ben je binnen 5 minuten geblokkeerd. Token caching met een buffer van 60 seconden voor expiry is de enige werkbare balans, maar die buffer moet je wel configureerbaar maken want bol past de TTL af en toe aan.
2
Data ophalen met cursor based paginering
De returns endpoint geeft data in porties terug via page parameters, niet via cursors. Je script paginaert tot de response signaleert dat er niks meer komt. Dat klinkt simpel, maar de API geeft geen totaal aantal pagina's of een "has more" flag mee. Je moet zelf detecteren: de pagina bevat minder items dan de maximale batch grootte, of de pagina is leeg. Beide condities moeten afgevangen worden, want ze gedragen zich anders bij edge cases.
Klassieke stille fout: script stopt na pagina 1 omdat die al 50 items bevat, of pagineert door tot pagina 20 omdat elke pagina precies 50 items geeft maar er in werkelijkheid maar 47 retouren zijn (de laatste pagina kreeg een fill van oudere records). Resultaat: of je mist 200 retouren, of je telt er 150 dubbel. Beide problemen zie je niet terug in errors, alleen in totalen die niet kloppen met het Partnerplatform als je ze vergelijkt.
3
Datum filtering en window bepaling
De API biedt geen server-side filtering op datum bereik voor retouren, dus je moet alle retouren ophalen en daarna zelf filteren. Let op: er zijn drie verschillende datum velden per retour (registratiedatum van de klant, ontvangstdatum bij jou, verwerkingsdatum). Welke je als anchor gebruikt bepaalt of je 30 dagen volgende maand vergelijkbaar is met 30 dagen deze maand. Kies je verkeerd, dan lijkt het alsof retouren dalen terwijl ze alleen nog niet verwerkt zijn.
Subtiliteit: bol administratief verschuift af en toe retouren van status. Een retour die vorige maand in je window zat kan deze maand uit je window vallen omdat de registratiedatum is bijgewerkt. Dit is zeldzaam maar gebeurt. Als je historie wilt opbouwen moet je beslissen: snapshots bevriezen (reproduceerbaar maar soms verouderd) of live queries (accuraat maar je getallen van vorige maand veranderen). Allebei werken, maar je moet expliciet kiezen, anders krijg je inconsistenties.
4
Retourreden normalisatie en mapping tabel
De API geeft per retour twee velden: een hoofdreden en een detail reden. Er zijn meer dan 20 combinaties mogelijk. Sommige combinaties zijn inhoudelijk bijna identiek maar tellen apart in de API ("niet wat ik verwachtte" vs "voldoet niet aan beschrijving"). Als je ze 1 op 1 mapt krijg je een onleesbare lijst per product. Als je ze te agressief groepeert verlies je nuance die je team nodig heeft om actie te ondernemen. De balans ligt ergens rond 8 tot 10 categorieën, maar die zijn per categorie product verschillend: voor kleding is maatvoering cruciaal, voor elektronica juist defect.
Wat veel mensen over het hoofd zien: bol voegt stilzwijgend nieuwe reden codes toe zonder deprecation waarschuwing. Je mapping moet een default hebben voor onbekende codes plus logging, anders crasht je script of sluipen nieuwe codes ongemerkt je data in als "overig". Beide zijn slecht. En je mag je script ook niet laten crashen want dan heb je die maand geen data. Dus: graceful degradation plus monitoring, niet gewoon een throw.
5
Aggregatie en enrichment per product
Per EAN wil je meer dan alleen een teller. Je wilt: totaal aantal retouren, welke redenen voorkomen, frequentie per reden, en idealiter ook productnaam en categorie. De productnaam zit niet standaard in de returns response, dus die moet je verrijken via een aparte endpoint of je eigen PIM. Dat verdubbelt het aantal API calls en brengt je dichter bij rate limits. Caching per EAN over meerdere runs is nodig, maar dan moet je invalidatie regelen als productnamen veranderen. Een product met 8 retouren waarvan er 6 om defect gaan is een ander gesprek dan 8 retouren met 8 verschillende redenen, dus die nuance moet leesbaar in je output komen.
6
Google Sheets batch writes en rate limits
Sheets heeft een eigen authenticatie flow via een service account met gescopete permissions. Dat account krijgt toegang tot specifieke sheets door ze expliciet te delen. De valkuil zit in de API limieten: de standaard quota is 60 write requests per user per minuut en 300 per project per minuut. Als je per rij een losse update doet zit je binnen 2 minuten op de limiet bij een normale catalogus. Je wilt batch writes doen met het values.batchUpdate endpoint, maar die hebben een andere payload structuur dan individuele updates en de limieten per batch zijn anders geconfigureerd.
Verborgen gotcha: als je een tab overschrijft moet je eerst de oude data wissen, anders blijven oude rijen onderaan staan als de nieuwe dataset korter is. Maar clear plus write is twee API calls, dus je verdubbelt je rate limit verbruik. De elegante oplossing is een range specifieke update die precies overschrijft, maar dan moet je vooraf weten hoeveel rijen je gaat schrijven. Dat klinkt triviaal tot je merkt dat je aggregatie stap dynamisch is en soms 47 en soms 312 rijen oplevert.
7
Scheduling, idempotency en foutafhandeling
Maandelijks draaien betekent dat als er iets mis gaat, je het pas over een maand merkt. Of erger, je merkt het nooit omdat de sheet bijgewerkt is met gedeeltelijke data. Goede foutafhandeling betekent: je script kent zijn eigen baseline (bijvoorbeeld 50 tot 500 retouren per maand), alerteert bij afwijkingen, en is idempotent zodat een herstart halverwege niet dubbele data oplevert. Dat laatste is niet triviaal omdat sheets geen transacties hebben. Je moet een tussenlaag hebben (staging tab, lock bestand of database) die garandeert dat je nooit halve state in je productie tab krijgt.
Waar de meeste setups stranden: de happy path werkt na een dag bouwen. Wat ontbreekt is observability. Als je script in maand 3 stilletjes 0 retouren terugstuurt (omdat de token refresh logic faalde na een bol API update), bijvoorbeeld, dan is je sheet leeg en denkt je team dat er geen problemen zijn. Juist dat soort false negatives zijn duur. Alerting op afwijkingen, structured logging, en een heartbeat check zijn geen nice-to-haves, ze zijn de helft van het werk.

Dit script is een startpunt, geen eindpunt

Zodra je de data uit bol hebt, koppel je er toe wat je al gebruikt. Een paar veelvoorkomende combinaties.

returnless
Retour portaal integratie
Als je Returnless gebruikt voor je bol retouren, haal dan ook de data uit Returnless op naast de bol API. Zo zie je per product niet alleen de bol retourreden, maar ook de extra context die klanten invullen in het retourformulier.
fulfilment
WMS of fulfilment portaal
Fulfilment tools zoals Picqer, GoedGepickt, Channeldock of MyParcel hebben vaak hun eigen retour API. Koppel die aan hetzelfde script zodat je ook weet wat er fysiek binnenkomt, inclusief staat van het product bij ontvangst.
slack
Slack melding per run
Voeg een Slack webhook toe die na elke maandelijkse run een bericht stuurt naar een kanaal met de top 5 producten van die maand. Zodat je team niks hoeft te openen om de belangrijkste signalen te zien.
database
Supabase of Postgres voor historie
Google Sheets is prima voor het maandelijkse overzicht, maar voor trend analyse over meerdere maanden werkt een echte database beter. Schrijf dezelfde data ook naar een database en je kunt retouren per maand per EAN trekken in seconden.
reviews
Review data per product
Combineer de retour data met je product reviews. Als een product met veel retouren ook lage reviews heeft met specifieke klachten, weet je direct waar je moet beginnen met verbeteren.
ads
Advertising pauze trigger
Koppel aan de bol Advertising API: producten met een retour ratio boven een drempel (bijvoorbeeld 20 procent) krijgen een flag zodat je ze kunt pauzeren in Sponsored Products. Anders betaal je voor clicks die geld kosten.

Wat je in de gaten houdt

🔑
API credentials kunnen worden ingetrokken
Als iemand in je team de API key verwijdert in het Partnerplatform, stopt het script met werken. Zet dit op de checklist bij personeelswissels.
🔃
API versie up to date houden
Bol deprecated regelmatig oude API versies. Hou de developer changelog in de gaten en upgrade binnen 12 maanden na een nieuwe release.
Cron herstarten na herstart van de machine
Als je het script lokaal draait op een Mac: check na een reboot of de cron nog actief is. Een VPS is daarvoor stabieler.
strategie call

Wil je dit of een ander systeem verder personaliseren en automatiseren?

Het bouwen is één ding, het goed laten draaien op lange termijn iets anders. We kijken samen welke aanpak bij jouw team, volume en huidige stack past. En wat je verder nog uit je data kunt halen.

JL
Job Lenselink
Job Lenselink
oprichter SolidDeploy
Boek een gratis strategie call
30 minuten, gratis.
ik kijk mee wat er bij jou te automatiseren valt