Naar de inhoud
SyncMyShop

Kennisbank

WooCommerce REST API koppelen: sleutels, eisen en de eerste aanroep

Een koppeling praat met WooCommerce via de REST API onder /wp-json/wc/v3, met een Consumer Key en Consumer Secret die je in de beheeromgeving aanmaakt. Daarvoor moeten de permalinks op iets anders dan Eenvoudig staan en loopt de site over HTTPS; daarna gaat het om de juiste rechten, pagina's van 100 en de tijdzone van je datums.

Bijgewerkt op

Wat je nodig hebt voordat de koppeling kan praten

De REST API zit in WooCommerce zelf; er is geen aparte plugin nodig. De huidige versie heet wc/v3 en staat op https://jouwshop.nl/wp-json/wc/v3. Vier dingen moeten in orde zijn, nagelezen in de documentatie van de REST API op 3 oktober 2026:

Eis Waarde Wat er gebeurt als het mist
WooCommerce 3.5 of hoger voor wc/v3 het endpoint bestaat niet
WordPress 4.4 of hoger de REST-laag van WordPress ontbreekt
Permalinks alles behalve Eenvoudig 404 met rest_no_route
HTTPS aanbevolen; zonder HTTPS geldt OAuth 1.0a sleutels gaan leesbaar over de lijn

In de praktijk liggen de ondergrenzen veel hoger: WooCommerce 11.1.2, de versie van 22 september 2026, vraagt WordPress 7.0 en PHP 7.4. Een winkel die zo ver achterloopt dat wc/v3 ontbreekt, heeft een update nodig voordat er iets te koppelen valt.

Sleutels aanmaken en het juiste recht kiezen

Een sleutel maak je onder WooCommerce, Instellingen, Geavanceerd, REST API. Je kiest een WordPress-gebruiker en een recht: Lezen, Schrijven of Lezen/Schrijven. Drie regels uit WooCommerce's eigen documentatie bepalen hoe je dat doet:

  • Het Consumer Secret wordt één keer getoond. Wie de pagina verlaat zonder het te kopiëren, maakt een nieuwe sleutel.
  • De sleutel volgt de rollen en rechten van de gekozen gebruiker. Een sleutel met Lezen/Schrijven op een gebruiker die geen orders mag zien, leest geen orders.
  • Wordt de gebruiker verwijderd, dan werkt de sleutel niet meer. Sleutels gaan niet over op een andere gebruiker.

Maak de sleutel daarom aan op een eigen gebruiker voor de koppeling, niet op het account van een medewerker die ooit vertrekt. Welk recht per stroom nodig is:

Stroom Endpoint Recht
Orders naar het ERP GET /orders Lezen
Orderstatus en track-and-trace terug PUT /orders/<id> Lezen/Schrijven
Voorraad en prijs naar de shop POST /products/batch Lezen/Schrijven
Klanten naar het ERP GET /customers Lezen

Zodra één stroom terugschrijft, wordt het Lezen/Schrijven. Meer sleutels dan nodig maken het lastiger om bij te houden welke nog in gebruik is; één sleutel per koppeling is overzichtelijk. Een app kan ook zelf een sleutel aanvragen via /wc-auth/v1/authorize, met scope op read, write of read_write en een callback_url die over HTTPS moet lopen. De gebruiker geeft daarvoor in de browser toestemming, en de sleutels gaan in een apart verzoek naar dat adres.

De eerste aanroep en wat er terug kan komen

Over HTTPS gaan de Consumer Key en het Consumer Secret mee als gebruikersnaam en wachtwoord (basic authentication). De eerste test is één order:

GET /wp-json/wc/v3/orders?per_page=1 HTTP/1.1
Host: shop.bakkerinstallatie.example
Authorization: Basic Y2tfNGY...ZWQ=

Komt er een order met id, number en billing terug, dan werken sleutel, permalinks en rechten. Komt er een fout, dan zegt de combinatie van status en code waar het zit:

Antwoord Oorzaak in de praktijk
403 met woocommerce_rest_cannot_view sleutel klopt, maar de gebruiker of het recht laat dit niet toe
401 met "Consumer key is missing" de webserver geeft de Authorization-header niet door
401 met een andere melding verkeerde sleutel, of een sleutel van een verwijderde gebruiker
404 met rest_no_route permalinks op Eenvoudig, of een verkeerd pad of versie
501 Method Not Implemented ModSecurity op de server houdt het verzoek tegen
500 fout in PHP, vaak een plugin die op het verzoek inhaakt

Zo ziet de 404 eruit als de permalinks op Eenvoudig staan:

{
  "code": "rest_no_route",
  "message": "No route was found matching the URL and request method",
  "data": { "status": 404 }
}

Voor de "Consumer key is missing" documenteert WooCommerce een uitweg: de sleutel en het secret als consumer_key en consumer_secret in de URL. Dat werkt, maar dan staan ze in de toegangslogs van de server. Wij laten liever de header doorgeven. Over HTTP vraagt WooCommerce OAuth 1.0a met een handtekening per verzoek, en weigert het verzoeken met een tijdstempel die meer dan 15 minuten afwijkt. Loopt de klok van de server van de koppeling meer dan 15 minuten uit de pas, dan krijgt elk verzoek een 401.

Orders ophalen in pagina's van 100

Een lijst komt standaard terug in pagina's van 10. Met per_page vraag je er meer, tot 100 per pagina in de REST-laag van WordPress. Het totaal staat in de headers X-WP-Total en X-WP-TotalPages, en de link naar de volgende pagina in de Link-header.

Een rekenvoorbeeld. Bij de start haalt de koppeling de orderhistorie op: 18.400 orders.

Aanpak Rekensom Verzoeken
Standaardpagina 18.400 / 10 1.840
per_page=100 18.400 / 100 184
Elk uur alleen gewijzigde orders, 137 stuks 137 / 100, naar boven afgerond 2

Duurt een pagina van 100 op jouw hosting 2 seconden (een aanname; meet het op je eigen server), dan kost de eerste import 184 x 2 = 368 seconden, ruim 6 minuten. Met pagina's van 10 zou hetzelfde 3.680 seconden zijn, ruim een uur, en tien keer zoveel verzoeken die de shop voor bezoekers vertragen.

Gewijzigde orders ophalen uit de WooCommerce REST API in twee pagina's De koppeling vraagt de orders op die sinds de vorige ronde zijn gewijzigd, 100 per pagina. WooCommerce meldt 137 orders in 2 pagina's. De tweede pagina levert de laatste 37. De koppeling bewaart het starttijdstip van deze ronde als begin van de volgende. Koppeling elk uur WooCommerce /wp-json/wc/v3 GET orders ?modified_after=... &per_page=100 200 OK, X-WP-Total: 137 X-WP-TotalPages: 2. Met de standaard van 10 per pagina waren het 14 verzoeken geweest. GET orders ... &page=2 200 OK, 37 orders starttijd ronde opslaan 1 uur later GET orders ?modified_after= <starttijd>
Orders ophalen die sinds de vorige ronde zijn gewijzigd: 2 verzoeken voor 137 orders.

Na de eerste import vraagt de koppeling alleen wat gewijzigd is, met modified_after. Twee instellingen voorkomen dat er orders tussendoor glippen:

  • dates_are_gmt=true. Zonder die parameter leest WooCommerce de datum als tijd van de site. Stuurt de koppeling een tijd in UTC zonder die parameter, dan ligt de grens in de zomertijd 2 uur verkeerd. Ligt hij te vroeg, dan komen orders dubbel binnen; ligt hij te laat, dan mist de ronde de wijzigingen van 2 uur. De order heeft daarom ook twee datumvelden: date_modified in de tijd van de site en date_modified_gmt in GMT. Zie datums en tijdzones.
  • Een vaste sortering. Standaard sorteert de API aflopend op datum. Komt er tijdens het bladeren een order bij, dan schuift alles een plek op en verschijnt dezelfde order op twee pagina's. Met orderby=modified en order=asc komen nieuwe wijzigingen achteraan.

Voor wijzigingen tussen twee rondes heeft WooCommerce webhooks, die op de achtergrond via wp-cron worden verstuurd; hoe je daar een controleronde naast zet staat in wat is een webhook.

Versies, Legacy API en HPOS

Er zijn vier generaties van de API in omloop:

Versie Pad Status
Legacy v1, v2, v3 /wc-api/v3 en ouder uit de kern sinds WooCommerce 9.0; alleen met de losse plugin WooCommerce Legacy REST API
REST API v1, v2 /wp-json/wc/v1, /wp-json/wc/v2 bestaan nog, oudere velden
REST API v3 /wp-json/wc/v3 de huidige versie

Een koppeling of webhook die nog op de Legacy API draait, stopt bij een update naar 9.0 of hoger tenzij die plugin geïnstalleerd is. Dat is een van de eerste dingen die we nakijken als we een bestaande koppeling vervangen.

Sinds WooCommerce 8.2 (oktober 2023) staat High-Performance Order Storage standaard aan bij nieuwe installaties. Orders staan dan in eigen tabellen zoals wp_wc_orders. Voor de REST API verandert er niets. Een script dat orders rechtstreeks met SQL uit de tabel met berichten leest, vindt na de overstap niets meer en meldt geen fout: het ziet nul nieuwe orders.

Wat betekent dit voor je koppeling?

De verbinding zelf is een sleutel en een adres. Het werk zit in wat er omheen hoort: een eigen gebruiker met precies de rechten die de stromen nodig hebben, ophalen in pagina's van 100 met een vaste sortering en GMT-datums, een tempo dat de shop niet vertraagt, en een controleronde naast de webhooks. Dat bouwen wij als onderdeel van de koppeling, en daarna draaien en bewaken we hem. Elke ronde staat met zijn verzoeken en antwoorden in de log van het dashboard.

Wat we verder met WooCommerce koppelen, van btw in vier decimalen tot gastbestellingen, staat op de pagina over de WooCommerce koppeling. De orderstroom naar ERP en boekhouding staat bij orders, klanten en verzending. Vertel welke WooCommerce-versie en welke systemen je gebruikt, dan kijken we welke stromen met welke rechten nodig zijn.

Veelgestelde vragen

Waar maak ik een WooCommerce API-sleutel aan?

Onder WooCommerce, Instellingen, Geavanceerd, REST API, met de knop Sleutel toevoegen. Je kiest een omschrijving, de WordPress-gebruiker waar de sleutel bij hoort en het recht: Lezen, Schrijven of Lezen/Schrijven. Het Consumer Secret staat daarna één keer op het scherm; kopieer het voordat je de pagina verlaat.

Waarom krijg ik een 404 met rest_no_route?

Meestal staan de permalinks op Eenvoudig. Dan bestaan de adressen onder /wp-json/ niet en vindt WordPress geen route. Zet de permalinks onder Instellingen, Permalinks op een andere optie, bijvoorbeeld Dag en naam. Een tikfout in het pad, zoals wc/v3/order in plaats van wc/v3/orders, of een methode die het endpoint niet kent, geeft dezelfde fout.

Wat betekent "Consumer key is missing" terwijl de sleutel klopt?

Dan geeft de webserver de Authorization-header niet door aan PHP. WooCommerce noemt dit zelf een serverprobleem. De oplossing aan de kant van de server is de header doorgeven; de uitweg die WooCommerce documenteert is de sleutel en het secret als parameters in de URL meesturen, alleen over HTTPS.

Heeft de WooCommerce REST API een rate limit?

De documentatie van de REST API noemt er geen. De rate limiting die WooCommerce documenteert hoort bij de Store API van winkelwagen en checkout en staat standaard uit. De grens voor een koppeling is je hosting: PHP-processen, geheugen, een beveiligingsplugin of een firewall die bij veel verzoeken blokkeert.

Werkt de oude Legacy REST API nog?

Niet zonder extra plugin. WooCommerce heeft de Legacy REST API in versie 9.0 uit de kern gehaald. Een koppeling of webhook die er nog op draait, werkt alleen met de losse plugin WooCommerce Legacy REST API. Een nieuwe koppeling gebruikt wc/v3.

Vertel wat je nodig hebt

Vertel welke systemen je gebruikt en wat je wilt verbeteren. Je krijgt binnen één werkdag een persoonlijk antwoord. We helpen je de werkzaamheden helder te krijgen en spreken de prijs en planning af voordat je iets toezegt.

  • Je weet de prijs en de doorlooptijd voordat je iets toezegt
  • Wij zoeken uit welke koppeling het werk uit handen neemt
  • Wij verzorgen de bouw, hosting, bewaking en het onderhoud
  • Je team krijgt minder overtypwerk en minder uitzoekwerk

Leveranciers, producten, orders per dag, een ruwe schatting is prima.

Of mail direct: carsten@syncmyshop.com