Shopify koppelen aan je TMS: 6 stappen
Shopify stap voor stap koppelen aan je TMS via Admin API, webhooks en Fulfillment Orders: orders, labels en tracking automatisch synchroniseren.
Waarom Shopify nu op het bordje van elk logistiek team ligt
Als je de afgelopen twaalf maanden een nieuwe NL-webshop hebt zien lanceren, draait die met grote waarschijnlijkheid op Shopify. Uit een analyse van ShopRank onder 324.000 in 2025 gelanceerde webshops blijkt dat in Nederland 54,3 procent van de starters op het platform draait, met Nederland als koploper in Europa. WooCommerce verliest ondertussen terrein: het aandeel daalde van 34,7 procent naar 25,8 procent van de 2025-starts. Voor operations- en IT-teams bij verladers betekent dit dat Shopify niet langer een rand-case is, maar het platform waar je structureel orders uit moet trekken naar je TMS, in plaats van los CSV-werk of handmatige labelruns.
Deze handleiding beschrijft hoe je Shopify koppelt aan een transportmanagementsoftware via de Admin API, orderwebhooks en de Fulfillment Orders API. Aan het eind stromen bestellingen automatisch door naar labels, tracking en terugkoppeling naar de klant, zonder dat iemand een export hoeft te draaien.
Wat je nodig hebt voordat je begint
Je hebt vijf dingen op orde voordat je gaat bouwen. Zonder deze basis loop je na een paar uur vast op scoperechten of een ontbrekende endpoint.
- Shopify-winkel met admin-toegang. Sinds 1 januari 2026 maak je custom apps aan via het Dev Dashboard, niet meer rechtstreeks vanuit de winkeladmin. Je klikt in Instellingen > Apps op "Apps ontwikkelen" en vervolgens op "Apps bouwen in Dev Dashboard".
- Een TMS met een inkomend API-endpoint of webhook-ontvanger. Voorbeelden van partijen met een kant-en-klare of goed gedocumenteerde Shopify-koppeling zijn Cargoson, Sendcloud, ShippyPro en Shipmondo.
- Een publiek bereikbare HTTPS-callback-URL voor webhooks en fulfillment-requests. Shopify levert alleen af op HTTPS, geen uitzonderingen.
- Shopify Advanced-abonnement of hoger als je ook rate shopping bij checkout wilt via de Carrier Service API.
- Een testbestelling en een development store om de koppeling te verifiëren zonder live orders te raken.
Shopify koppelen aan je TMS in zes stappen
Stap 6: Testen en verifiëren
Plaats een testorder in je development store en controleer drie dingen: of de webhook binnen enkele seconden aankomt (zichtbaar in Instellingen > Notificaties > Webhooks in de Shopify admin, inclusief delivery-logs), of de fulfillment request in je TMS verschijnt, en of het label met tracking terugkomt in de orderdetail. Herhaal dit met een order die meerdere fulfillment locations raakt, en met een annulering na acceptatie, om de cancellation-flow te testen.
Stap 5 (optioneel): Carrier Service API voor rate shopping in checkout
Wil je tijdens checkout live tarieven van meerdere vervoerders tonen, dan heb je de Carrier Service API nodig. Deze is inbegrepen in het Advanced Shopify-plan of hoger; op lagere plannen kun je ‘m tegen een maandelijks bedrag bijkopen of activeren via jaarlijkse facturering. Je registreert een CarrierService-endpoint dat POST-rate-requests beantwoordt met een lijst tarieven per vervoerder, gebaseerd op gewicht, afmetingen en bestemming. Voor NL/BE multi-carrier shipping zie je dit type koppeling onder meer terug bij nShift, Sendcloud, ShippyPro en Cargoson.
Stap 4: Tracking terugschrijven naar Shopify
Zodra je TMS een label genereert, maak je een fulfillment aan met de mutatie fulfillmentCreate, inclusief trackingInfo (nummer, vervoerder, URL). Shopify stuurt vervolgens automatisch de trackingmail naar de klant en zet de orderstatus op "fulfilled". Dit is het moment waarop je weet dat de koppeling end-to-end werkt: order komt binnen via webhook, wordt geaccepteerd via de Fulfillment Orders API, en het label verschijnt terug in de Shopify-orderdetail zonder menselijke tussenkomst.
Stap 3: Fulfillment Orders API koppelen
Zodra een order binnenkomt, wijst Shopify het werk toe aan een fulfillment location. Als je TMS als fulfillment service is geregistreerd, ontvang je een fulfillment request. Je accepteert die met de GraphQL-mutatie fulfillmentOrderAcceptFulfillmentRequest, die het argument id van de fulfillment order vereist en optioneel een message en estimatedShippedAt. Deze mutatie vereist de toegangsscope write_assigned_fulfillment_orders, naast de juiste gebruikersrechten. Afwijzen kan met fulfillmentOrderRejectFulfillmentRequest, met een reden voor de merchant.Een belangrijk detail: zodra je als fulfillment service een verzoek hebt geaccepteerd, kan de merchant of order management app dit niet meer annuleren; er moet dan een apart cancellation request worden ingediend. Bouw dit scenario dus bewust in, want klanten annuleren orders ook ná acceptatie.
Stap 2: Orderwebhooks registreren
Je registreert webhooks op de topics orders/create en orders/paid, zodat je TMS een order ziet zodra die binnenkomt en nogmaals zodra betaling rond is. Dat kan via de GraphQL-mutatie webhookSubscriptionCreate met topic ORDERS_CREATE en een callbackUrl naar je TMS-endpoint. Let op: sinds 1 april 2025 moeten alle nieuwe publieke apps uitsluitend op de GraphQL Admin API worden gebouwd, de REST-variant geldt als legacy. Voor een interne custom app kun je in de praktijk nog met REST wegkomen, maar bouw nieuw bij voorkeur direct in GraphQL.Elke binnenkomende webhook bevat de header X-Shopify-Hmac-SHA256, een base64-gecodeerde HMAC-SHA256 van de ruwe request body. Verifieer die handtekening voordat je de payload verwerkt: bereken zelf een HMAC-SHA256 over de ongewijzigde raw body met je app-secret als sleutel, encodeer in base64, en vergelijk met een timing-safe comparison. Zonder deze stap accepteert je endpoint in theorie elke POST die eruitziet als een Shopify-order.
Stap 1: Custom app en scopes instellen
Ga naar Instellingen > Apps > Apps ontwikkelen > Apps bouwen in Dev Dashboard, en maak daar een nieuwe app aan. Je definieert een app-URL (bij een niet-embedded app volstaat de standaard-URL) en kiest de Webhooks API-versie. Vervolgens stel je de scopes in: read_orders voor het uitlezen van orderdata, write_fulfillments om labels en tracking terug te schrijven, en read_assigned_fulfillment_orders plus write_assigned_fulfillment_orders zodra je als fulfillment service werkt met de Fulfillment Orders API. Na het releasen van de app krijg je een permanent access token dat je bewaart als geheim, niet in een repo.
Veelvoorkomende faalmodus: HMAC-mismatch en scope-fouten
De meest voorkomende storing is een 401 op je webhook-endpoint terwijl Shopify wel degelijk aflevert. De oorzaak is bijna altijd dezelfde: een JSON body-parser die vóór je verificatiecode draait en de raw bytes al heeft omgezet naar een JavaScript-object. Je berekent dan een HMAC over een geserialiseerde, maar niet-identieke, versie van de body, en die komt nooit overeen met de header. De oplossing is de raw body apart vastleggen (bijvoorbeeld met een verify-callback in je body-parser) vóórdat enige parsing plaatsvindt, en pas na een geslaagde HMAC-check de JSON te parsen.
Een tweede faalmodus is een 403 op de Fulfillment Orders API met een melding dat de fulfillment service "van het type api" moet zijn. Dat betekent dat je app niet als fulfillment service is geregistreerd op de juiste locatie, of dat de scope write_assigned_fulfillment_orders ontbreekt. Controleer dit in de app-instellingen in het Dev Dashboard en herinstalleer de app na een scope-wijziging, anders blijft het oude token actief met de oude rechten.
De derde faalmodus duikt pas op bij piekmomenten zoals Black Friday: rate limiting. De GraphQL Admin API rekent in cost points per seconde in plaats van aantal requests, met een plafond dat oploopt naarmate je Shopify-plan hoger ligt. Elke mutatie, zoals het accepteren van een fulfillment request, kost standaard 10 punten, en connectievelden met veel items kosten meer naarmate je meer regels per query opvraagt. Bouw daarom een lokale teller die de throttleStatus uit de response-extensions uitleest, en vertraag zelf voordat Shopify je met een throttle-fout terugstuurt. Voor grote historische syncs is een bulk operation efficiënter dan duizenden losse queries.
Kant-en-klaar of zelfbouw: een korte vergelijking
Niet elk team hoeft zelf tegen de GraphQL Admin API te bouwen. Een aantal partijen levert een kant-en-klare Shopify-connector die het grootste deel van bovenstaande stappen al heeft dichtgetimmerd.
| Partij | Shopify-connector | Sterk in | Zelfbouw nodig voor |
|---|---|---|---|
| Cargoson | Ja, koppeling op order- en labelniveau | Multi-carrier TMS met NL/BE-vervoerderskoppelingen naast Shopify | Maatwerk fulfillment-regels per locatie |
| Sendcloud | Ja, native app in Shopify App Store | Parcel-heavy e-commerce, snelle labelflow | Complexe B2B pallet-scenario's |
| ShippyPro | Ja, native app | Multi-channel verladers met meerdere marktplaatsen | Diepe ERP-koppelingen |
| Shipmondo | Ja, native app | Benelux- en Scandinavische vervoerders | Grootschalige carrier service rate shopping |
Kant-en-klaar is logischer als je snel live wilt en een standaard parcel-flow hebt. Zelfbouw op de Admin API en Fulfillment Orders API loont als je een TMS gebruikt dat zelf als fulfillment service optreedt, of als je afwijkende acceptatielogica nodig hebt per magazijnlocatie. Voor een dieper overzicht van multi-carrier koppelingen in de praktijk is de Cargoson-documentatie een nuttig vertrekpunt naast de Shopify dev-docs zelf.
Volgende stap
Begin met de scopes en een testwebhook op orders/create in een development store, niet in productie. Zodra die ene order betrouwbaar doorkomt met correcte HMAC-verificatie, breid je uit naar de Fulfillment Orders API en pas daarna naar tracking-terugkoppeling. Ga pas live op je echte winkel als je ook de annuleringsflow na acceptatie hebt getest, want dat is het scenario dat de meeste koppelingen in de praktijk breekt.