Platforms
WooCommerce integration with your ERP, warehouse and suppliers
WooCommerce gives an integration the REST API v3: 100 objects per batch, webhooks that are switched off after 5 failed deliveries, and one stock number per product. We build the integration to your ERP around those rules and your plugins, then host and run it.
What WooCommerce is and who runs it
WooCommerce is an open-source commerce plugin for WordPress. It runs on the merchant's own hosting, next to the theme and every other plugin on the site. For an integration that means three things: the API speed is your server's speed, plugins change what an order looks like, and the WordPress and WooCommerce versions are yours to choose. Version 11.1.2 needs WordPress 7.0 and PHP 7.4.
Since WooCommerce 8.2, new installations store orders in their own tables (high-performance order storage) instead of WordPress posts. A store set up before that may still have the posts tables as its working tables, with the new tables as backup or the other way around. The REST API hides the difference, but a plugin or a direct database query does not, which is one reason we keep the integration on the API.
What connects to WooCommerce
WooCommerce owns the order and the checkout payment. The ERP is the system of record for items, prices and stock. These are the flows we build as part of an e-commerce ERP integration:
| Flow | Direction | REST endpoint (/wp-json/wc/v3) |
|---|---|---|
| Orders | WooCommerce to ERP | /orders |
| Customers | both ways | /customers |
| Products | ERP or PIM to WooCommerce | /products, /products/batch |
| Variations and their stock | ERP to WooCommerce | /products/<id>/variations/batch |
| Order status and tracking | ERP or WMS to WooCommerce | /orders/<id>, Shipment Tracking endpoint |
| Refunds | both ways | /orders/<id>/refunds |
An order arrives as JSON with number, status, customer_id, billing and shipping addresses, line_items with sku, quantity, total and total_tax, and meta_data for everything plugins add. The order status says what already happened to the stock: at Processing the payment is in and the stock is reduced; at On hold the stock is reduced and the payment still has to be confirmed. The integration sends an order to the ERP at the status you choose, usually Processing, and maps the other statuses to the ERP's own set; see order status mapping.
How WooCommerce exposes data
REST API keys
The integration authenticates with a consumer key and a consumer secret, created under WooCommerce, Settings, Advanced, REST API with Read, Write or Read/Write access. Over HTTPS they go as basic authentication. The secret is shown once. The keys belong to one WordPress user and stop working when that user is deleted.
GET /wp-json/wc/v3/orders?modified_after=2026-10-03T06:00:00&per_page=100&page=1
Host: shop.example.com
Authorization: Basic Y2tfMWE0Zjp...
HTTP/1.1 200 OK
X-WP-Total: 238
X-WP-TotalPages: 3
Pages and batches
| Limit | Value | Above it |
|---|---|---|
| Items per page | 10 by default, 100 with per_page |
next page, totals in X-WP-Total |
| Objects per batch call | 100 | HTTP 413 |
| Variations per batch call | those of one parent product | one call per parent |
| Failed webhook deliveries in a row | 5 | webhook set to disabled |
Requests per minute on /wc/v3 |
none documented | your hosting decides |
The batch endpoint for variations sits under each parent product, and that decides the time a stock sync takes.
Worked through for 3,000 simple products: 3,000 / 100 = 30 batch calls. For 3,000 variable products with 4 variations each, the 12,000 variations need one call per parent, so 3,000 calls. At 2 seconds per call (an assumption; it depends on your hosting and plugins) that is 1 minute against 100 minutes. The integration therefore sends only the variations whose stock changed since the last run, which on a normal day is a few hundred calls. Integration throughput has the method.
The REST API documents no rate limit. WooCommerce's built-in rate limiting is for the Store API used by the storefront and checkout, covers POST requests only and is off by default. Your hosting sets the limit, and a security plugin or web application firewall that blocks bursts is the most common cause of failed calls. We measure it on your store before we set the number of workers.
Webhooks through wp-cron
WooCommerce sends webhooks for topics such as order.created and product.updated, signed in X-WC-Webhook-Signature as a base64 HMAC-SHA256 of the body. Delivery runs in the background through wp-cron, and wp-cron only runs when the site gets a page request. After 5 consecutive deliveries without a 2xx response, the webhook is set to disabled and stays off until someone sets it back. WooCommerce documents no retry of a failed delivery.
The integration therefore polls /orders with modified_after next to the webhooks, checks the webhook status, and sets a disabled webhook back to active. See webhooks are not a guarantee.
Where a WooCommerce integration gets stuck
One stock number and no location
A product or variation has manage_stock, stock_quantity (an integer), stock_status (instock, outofstock, onbackorder) and backorders (no, notify, yes). There is no location. An ERP with three warehouses has to decide which count for the store, and the integration sends their sum. An ERP that allows decimal quantities, such as 2.5 meters, has to be converted to a whole sales unit first, because stock_quantity takes integers only. See multi-location inventory.
Prices as strings, tax set per store
regular_price and sale_price are strings, and the REST API has no price per customer or customer group. B2B prices come from a plugin, and the integration writes to that plugin's fields. Tax is calculated by WooCommerce from the store's tax settings, with a setting that rounds at subtotal level instead of per line. When the ERP rounds per line and the store rounds the subtotal, the two totals differ by a cent on many orders. The integration compares the order total with the ERP's total and posts the difference as a rounding line or flags it; see money, tax and rounding.
Plugins in the order
Fields such as a VAT number, a PO number or a delivery date come from plugins and arrive in meta_data under keys each plugin chooses. A plugin update can rename a key. The integration maps each key explicitly and reports an order where an expected key is missing, instead of sending it to the ERP without the PO number.
Systems we integrate with WooCommerce
- WooCommerce NetSuite integration: variable products against matrix items, one stock number against stock per location, webhooks against NetSuite's concurrency limit.
- WooCommerce ERP integration: the general case for other ERPs.
- WooCommerce EDI integration: orders from retail trading partners.
The system side is on NetSuite, Business Central and SAP Business One.
We build the integration for a fixed price, then host it, monitor it and adjust it when a WooCommerce or plugin update changes the data, for a monthly fee. Before go-live it runs as a dry run that writes nothing: you see per product which stock and price it would set, and per order what the ERP would receive. Every integration comes with a dashboard, logs and a per-run diff. Tell us which plugins run in your checkout and which ERP you have.
Frequently asked questions
Which WooCommerce version does the integration need?
The REST API v3 needs WooCommerce 3.5 and WordPress 4.4 or later, and pretty permalinks: with the Plain permalink setting the endpoints do not work. Filtering on modified_after came in WooCommerce 5.8. The legacy REST API left WooCommerce core in version 9.0, so a store that still relies on it needs the separate extension or a move to v3.
Does WooCommerce limit the number of API requests?
The REST API documents no rate limit of its own. The rate limiting WooCommerce ships covers the Store API that the storefront and checkout use, applies to POST requests only and is off by default. The real ceiling for the REST API is your hosting: PHP workers, memory and a firewall or security plugin that blocks bursts.
Can the integration push stock per warehouse to WooCommerce?
Not into WooCommerce core. A product or variation has one stock_quantity and no location field. The integration sends the sum of the warehouses that count for the store, or writes to the fields of a multi-location plugin when you run one. Which locations count is a decision we record per integration.
Where does the tracking number go?
The order schema in the REST API has no tracking field. The Shipment Tracking extension adds an endpoint for provider, tracking number and date per order, and the integration writes there. Without it, tracking goes into an order note or meta_data that your email template reads.
How do you keep guest customers from becoming duplicate debtors?
A guest order has customer_id 0, so WooCommerce gives no customer key. The integration matches the ERP debtor on the billing email and, for business customers, on company name and VAT number in meta_data, and creates a debtor only when nothing matches. See duplicate customers and orders.
Who in our company has to create the API keys?
An administrator, under WooCommerce, Settings, Advanced, REST API, with Read/Write access. The keys belong to the WordPress user they are created for and stop working when that user is deleted. We ask for a dedicated user for the integration, so the keys do not disappear when a staff account is removed.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase