Bol.com Retailer API koppelen aan je TMS
Stap voor stap bol.com's Retailer API v10 koppelen aan je TMS: OAuth2-token, labels aanmaken, zendingen bevestigen en FAILURE-status oplossen.
Bol.com heeft de oude Plaza API definitief uitgefaseerd: wie verkoopt via bol.com, moet nu via de Retailer API v10. Voor verladers die FBR-orders (Fulfilment by Retailer) automatisch willen omzetten naar verzendklare labels in hun TMS, betekent dit vier blokken werk: authenticatie, orders ophalen, labels aanvragen en de asynchrone bevestiging verwerken. Dit artikel loopt dat hele traject door, inclusief wat je doet als een process-status FAILURE of TIMEOUT teruggeeft — het stuk waar de meeste koppelingen op vastlopen.
Wat je vooraf nodig hebt
Je hebt vier dingen klaar nodig voordat je begint te bouwen. Zonder deze vier loop je binnen een uur vast op een 403 of een lege orderslijst.
- Een actief bol.com seller-account met toegang tot het Partner Platform, waar je onder Instellingen > API Instellingen de Client credentials voor de Retailer API aanmaakt.
- Een Client ID en Client Secret specifiek voor de Retailer API v10 — bol.com documenteert dit als de Client Credentials Flow, bedoeld voor service-naar-service authenticatie zonder tussenkomst van een gebruiker.
- Een TMS of multicarrier-platform dat bol.com als verzendkanaal ondersteunt naast PostNL, DPD NL, GLS en bpost.
- Toegang tot de demo-omgeving van bol.com om je koppeling te testen zonder live orders te raken.
Platforms als Sendcloud, nShift, ShipStation en Cargoson bouwen deze koppeling al voor je — kom daar later in dit artikel op terug. Deze tutorial is voor wie het zelf wil bouwen, of wil begrijpen wat er achter de schermen gebeurt als je TMS het al doet.
Stap 1 – OAuth2-token ophalen
Je vraagt een token aan bij de SSO-server van bol.com en stuurt die vervolgens mee als Bearer-token bij elke volgende aanroep. Zonder geldig token kom je geen stap verder dan een 403.
The Retailer API is secured with OAuth2. For all secured endpoints, users need to log into the SSO server at https://login.bol.com and retrieve a token. De aanvraag zelf gebruikt Basic authenticatie: de authorization header is de concatenatie van de Client ID, een dubbele punt en de Client Secret, base64-encoded. In de praktijk stuur je dus een POST naar het token-endpoint met header Authorization: Basic <base64 client_id:client_secret> en grant_type client_credentials.
- Bouw de Basic-auth header met je Client ID en Client Secret, base64-encoded.
- Stuur de POST naar het token-endpoint van login.bol.com.
- Lees het access token uit de respons — dit is een JWT.
- Zet dit token als
Authorization: Bearer <token>header bij elke volgende call.
Voor alle endpoints die authenticatie vereisen, is het verplicht een Authorization header mee te sturen met de string Bearer, gevolgd door het token. Vergeet dit niet, want het ontbreken van de Authorization header of het niet voorvoegen met "Bearer " resulteert direct in een 403-foutmelding. Tokens zijn kortlevend. Bouw daarom een refresh-mechanisme in je TMS-koppeling dat automatisch een nieuw token aanvraagt voordat het oude verloopt, in plaats van te wachten tot een call faalt.
Stap 2 – Open orders ophalen
Je haalt openstaande orders op met een GET-call naar het orders-endpoint, gefilterd op status OPEN. Dit endpoint is synchroon: je krijgt direct antwoord, geen process-status nodig.
Get a list of orders retrieves een lijst van alle open en afgehandelde orders, gesorteerd op aanmaakdatum in aflopende volgorde. De respons bevat het orderId, details van de items in een order, en datum/tijd waarop de order geplaatst is. Gebruik dit orderId om de volledige orderdetails op te halen: je kunt het orderId gebruiken als inputparameter voor Get an order by order id om alle informatie over een enkele order te krijgen.
In de volledige orderrespons zie je per orderItem een orderItemId, de shipmentDetails (naam, adres, postcode) en een fulfilment-blok met het veld method. Staat dat op FBR, dan moet jij het label aanvragen en de zending bevestigen. Staat het op FBB, dan handelt bol.com de verzending af en loop je via dezelfde Shipments-endpoints mee om de status terug te zien, maar hoef je zelf geen label aan te vragen.
Stap 3 – Verzendopties en label aanvragen
Je vraagt eerst verzendopties op per order-item, kiest een offer-id, en vraagt daarmee het label aan. Dit zijn twee losse calls, in die volgorde — je kunt niet direct een label aanvragen zonder eerst de opties te hebben opgehaald.
- POST naar
/retailer/shipping-labels/delivery-optionsmet een array van orderItems (orderItemId + quantity). - Lees de respons: een lijst
deliveryOptions, elk met eenshippingLabelOfferId,transporterCode,labelTypeenlabelPrice. - Kies de gewenste offer en POST naar
/retailer/shipping-labelsmet dieshippingLabelOfferIden dezelfde orderItems. - Je krijgt een
processStatusIdterug — bewaar die, want je hebt hem nodig in stap 5.
In de demo-respons van bol.com zie je twee duidelijk verschillende aanbiedingen voor hetzelfde order-item: een optie met transporterCode TNT, labelType PARCEL en labelDisplayName "PostNL & bol.com - Pakket", gemarkeerd als recommended, naast een optie met transporterCode TNT_BRIEF, labelType MAILBOX_LIGHT, labelDisplayName "PostNL & bol.com - Brievenbus" met labelPrice 2.88 en packageRestrictions van maximaal 2 kg en 38 x 26,5 x 3,2 cm. Voor een lichte order (boek, kabel, kledingstuk) kan het brievenbuspakket dus goedkoper zijn dan het standaardpakket — maar alleen als het binnen de maatrestricties past. Je TMS moet deze keuze automatisch maken op basis van gewicht en afmetingen uit je WMS, niet standaard de goedkoopste optie pakken zonder validatie.
Stap 4 – Zending bevestigen in bol.com
Je bevestigt de zending met een POST naar het shipments-endpoint. Sinds v10 is dit één endpoint voor het hele verzendproces, in plaats van de losse PUT-call uit oudere versies.
Het endpoint om een order-item te verzenden is in v10 veranderd van PUT /retailer/orders/shipment naar POST /retailer/shipments, met als voordeel dat je nu meerdere items in één request kunt verzenden en meerdere zendingen kunt aanmaken voor één order-item. Er zijn twee manieren om dit te doen: als je met je eigen shipping label verzendt, moet je transportinformatie meesturen — een transporterCode en een trackAndTraceCode. De trackAndTraceCode mag je optioneel leeg laten als je die later wilt nasturen via het Add transport information-endpoint, maar dat is niet nodig als je alle data in één keer meestuurt.
Gebruik dat aparte transport-endpoint alleen als je echt nog geen track&trace hebt op het moment van verzenden. Bevestig eerst de zending via het shipment-endpoint zonder het transport-deel, en voeg de trackingcode later toe via het transport-endpoint zodra je die van je vervoerder ontvangt — je kunt dit maar één keer doen, want het endpoint voegt alleen informatie toe en werkt niets bij. Met andere woorden: als je per ongeluk de verkeerde trackingcode meestuurt, kun je die niet meer corrigeren via de API. Controleer dit veld dus voordat je verzendt, niet erna.
Stap 5 – Process-status pollen en resultaat verifiëren
Elke POST, PUT of DELETE op de Retailer API is asynchroon. Je krijgt direct een processStatusId terug, maar moet die status apart opvragen om te weten of de actie echt gelukt is.
Na een request waarbij data wordt aangepast is het belangrijk altijd een process status op te vragen, want die geeft aan of de wijziging daadwerkelijk succesvol verwerkt is binnen de bol-omgeving. Er zijn vier mogelijke statussen: SUCCESS, FAILURE, PENDING of TIMEOUT. Achter de schermen werkt dit als een wachtrij: elk data-wijzigend request wordt asynchroon verwerkt en eerst in een interne wachtrij geplaatst, die continu wordt afgewerkt.
Je weet dat het gelukt is als je deze drie dingen ziet:
- De process-status call geeft
status: SUCCESSterug, met een gevuldeentityId— pas als de process status SUCCESS wordt, ontvang je de entityId; daarvoor was de actie nog niet uitgevoerd of continu mislukt. - De zending verschijnt in het Partner Platform onder "verzonden" bij de betreffende order.
- Je TMS toont de zending terug gekoppeld aan de orderstatus, met het juiste track&trace-nummer zichtbaar voor de klant.
Let op de bewaartermijn: bol.com verkort de opslagduur van de process-status van 2 dagen naar 1 dag, en na 30 minuten is de status altijd definitief SUCCESS, FAILURE of TIMEOUT en verandert hij niet meer. Bouw je polling dus met een redelijke timeout van pakweg 30 tot 60 minuten, niet met een oneindige retry-lus.
Faalmodus – wat te doen bij FAILURE of TIMEOUT
Bij FAILURE lees je het foutbericht en pas je de request aan voordat je opnieuw stuurt. Bij TIMEOUT poll je dezelfde processStatusId opnieuw in plaats van een nieuwe shipment aan te maken — anders krijg je dubbele labels en dubbele kosten.
FAILURE betekent dat het request niet succesvol verwerkt is; bol.com geeft altijd een verklaring waarom de wijziging mislukte, en die verklaring gebruik je om de request aan te passen. Meestal gaat het om een orderItemId dat al verzonden of geannuleerd is, of een shippingLabelOfferId die inmiddels verlopen is (de offer heeft een validUntilDate). Vraag in dat geval opnieuw delivery-options op voor hetzelfde order-item en gebruik de nieuwe offer-id. Blind retrien met dezelfde payload lost niets op.
TIMEOUT werkt anders. Wanneer een request lange tijd in de pending-status blijft hangen, zet bol.com de status op TIMEOUT, omdat de downstream service niet alle requests binnen een bepaalde tijd kon verwerken. Dit wil niet per se zeggen dat de actie mislukt is — soms is hij alsnog doorgekomen. Bij FAILURE of TIMEOUT kun je de actie opnieuw proberen uit te voeren, tenzij het foutbericht duidelijk aangeeft dat dit niet zal lukken. Controleer daarom eerst via de Shipments-lijst of de zending er al staat voordat je een nieuw shipment-request stuurt. Bouw hiervoor een idempotency-check op orderItemId in je TMS-koppeling: sla lokaal op welke orderItemId's al een geslaagde shipment hebben, en skip een nieuwe aanvraag als die er al is.
Dit is geen theoretisch scenario. Bol.com heeft zelf incidenten gehad waarbij orderbevestigingen waar de process status eindigde in timeout, alsnog verwerkt werden, met het advies om open orders dubbel te checken. Bouw je koppeling dus altijd zo dat een TIMEOUT een waarschuwing triggert voor handmatige controle, niet een automatische herhaling zonder check.
Waar een TMS dit voor je overneemt
Een multicarrier-platform abstraheert deze vijf stappen tot één knop "label aanmaken", inclusief de polling en de foutafhandeling op de achtergrond. Het verschil tussen platformen zit in hoe diep de koppeling gaat en welke carriers ernaast ondersteund worden.
| Platform | Bol.com als kanaal | Overige NL/BE carriers | Focus |
|---|---|---|---|
| Sendcloud | Ja | PostNL, DPD, GLS, bpost | E-commerce, webshop-integraties |
| nShift | Ja | PostNL, DPD, GLS, bpost | Enterprise, multi-brand verzendlogica |
| ShipStation | Ja | PostNL, DPD, GLS | Internationale e-commerce, marketplace-focus |
| Cargoson | Ja | PostNL, DPD, GLS, bpost | TMS met pallet/B2B-koppelingen naast parcel |
Voor een parcel-heavy webshop die vooral via bol.com en een eigen site verkoopt, is het verschil vaak te vinden in hoe het platform omgaat met de FAILURE/TIMEOUT-afhandeling: toont het de ruwe foutmelding van bol.com, of vertaalt het die naar een bruikbare actie voor je fulfilment-team? Als je ook B2B-palletvracht naast je bol.com-parcelstroom draait, loont het te kijken naar een platform dat beide naast elkaar afhandelt in plaats van losse tools per kanaal — zie bijvoorbeeld hoe Cargoson carrier-koppelingen voor gemengde verzendprofielen opzet.
Begin in elk geval met de demo-omgeving van bol.com voordat je live gaat: test alle vier eindstatussen (SUCCESS, FAILURE, PENDING, TIMEOUT) met de gedocumenteerde test-entity-id's, zodat je foutafhandeling al werkt voordat de eerste echte order vastloopt.