DEV Community

Cover image for How to Automate WooCommerce Order Fulfillment with REST APIs and Webhooks
fulfillbros
fulfillbros

Posted on

How to Automate WooCommerce Order Fulfillment with REST APIs and Webhooks

Running an online store with WooCommerce gives developers and merchants considerable flexibility. You can customize checkout flows, extend product functionality, connect external applications, and manage almost every part of the shopping experience.

But fulfillment is often where that flexibility becomes complicated.

A store might process payments automatically while still relying on spreadsheets, emails, or manual CSV exports to send orders to a warehouse.

That creates a disconnected workflow:

  • A customer places an order.
  • Someone exports the order information.
  • A fulfillment partner receives the details.
  • Warehouse staff locate the products.
  • A shipping label is generated.
  • Someone manually copies the tracking number back into WooCommerce.

This process may be manageable with five orders per day. At 100 orders per day, it becomes an operational bottleneck.

Fortunately, WooCommerce provides REST APIs and webhooks that developers can use to build more reliable fulfillment workflows.

In this tutorial, we'll explore how to design an automated WooCommerce fulfillment pipeline, retrieve orders through the REST API, respond to webhook events, prevent duplicate processing, and synchronize warehouse operations.

We'll also look at some of the challenges involved when orders are fulfilled by an external warehouse, including one located in China.

1. Understanding the WooCommerce Fulfillment Architecture

Before writing code, it helps to understand the systems involved.

A typical ecommerce fulfillment integration includes four components:

  1. WooCommerce Store

The storefront manages products, customers, checkout, payments, and order records.

  1. Integration Layer

A service that receives order events, validates order information, transforms data, and communicates with external systems.

  1. Warehouse Management System (WMS)

The warehouse system handles inventory allocation, picking, packing, and shipment preparation.

  1. Shipping and Tracking Services

Carriers and logistics platforms generate shipping labels, assign tracking numbers, and provide delivery updates.

A simplified architecture looks like this:

+----------------------+
| WooCommerce Store    |
|                      |
| Checkout + Orders    |
+----------+-----------+
           |
           | Webhook / REST API
           v
+----------------------+
| Integration Service  |
|                      |
| - Validate Orders    |
| - Map SKUs           |
| - Prevent Duplicates |
| - Handle Errors      |
+----------+-----------+
           |
           | Warehouse API
           v
+----------------------+
| Warehouse System     |
|                      |
| - Allocate Stock     |
| - Pick and Pack      |
| - Prepare Shipment   |
+----------+-----------+
           |
           v
+----------------------+
| Shipping Provider    |
|                      |
| Carrier + Tracking   |
+----------+-----------+
           |
           | Shipment Update
           v
+----------------------+
| WooCommerce Store    |
|                      |
| Tracking + Status    |
+----------------------+
Enter fullscreen mode Exit fullscreen mode

The important design principle is to separate storefront logic from warehouse operations.

WooCommerce should not need to know how a warehouse organizes its shelves, and a warehouse should not need direct access to the store's database.

An integration layer provides that separation.

2. Getting Started with the WooCommerce REST API

WooCommerce provides a REST API for working with orders, products, customers, and other ecommerce resources.

The current v3 API uses endpoints under:

/wp-json/wc/v3/
Enter fullscreen mode Exit fullscreen mode

For example:

GET /wp-json/wc/v3/orders
Enter fullscreen mode Exit fullscreen mode

retrieves orders, while:

GET /wp-json/wc/v3/orders/123
Enter fullscreen mode Exit fullscreen mode

retrieves a specific order.

Creating API Credentials

In your WordPress dashboard, navigate to:

WooCommerce → Settings → Advanced → REST API

Create credentials for a dedicated integration account.

For an integration that only reads orders, use read-only permissions.

If your integration also updates order information, additional permissions may be required.

Always follow the principle of least privilege.

Never expose WooCommerce API secrets in frontend JavaScript, public repositories, or browser-accessible configuration files.

Example: Fetching WooCommerce Orders with Python

The following example retrieves processing orders using Python.

import os
import requests

STORE_URL = os.environ["WC_STORE_URL"].rstrip("/")
CONSUMER_KEY = os.environ["WC_CONSUMER_KEY"]
CONSUMER_SECRET = os.environ["WC_CONSUMER_SECRET"]

endpoint = f"{STORE_URL}/wp-json/wc/v3/orders"

response = requests.get(
    endpoint,
    auth=(CONSUMER_KEY, CONSUMER_SECRET),
    params={
        "status": "processing",
        "per_page": 20,
    },
    timeout=15,
)

response.raise_for_status()

orders = response.json()

for order in orders:
    print({
        "order_id": order["id"],
        "status": order["status"],
        "items": len(order["line_items"]),
    })
Enter fullscreen mode Exit fullscreen mode

This example assumes your store uses HTTPS and supports standard WooCommerce REST API authentication.

It also assumes the required environment variables have already been configured.

For production use, you should additionally implement pagination, retries, request logging, and rate-limit handling where applicable.

3. Why Webhooks Are Better Than Constant Polling

One way to detect new orders is to request the WooCommerce Orders API every few minutes.

That approach works, but it has limitations.

If your integration polls too frequently, it generates unnecessary requests.

If it polls too slowly, orders may wait before reaching the warehouse.

Webhooks provide an event-driven alternative.

Instead of constantly asking WooCommerce whether something has changed, your integration receives a notification when a configured event occurs.

For example:

Customer Checkout
       |
       v
WooCommerce Order Created
       |
       v
Webhook Notification
       |
       v
Integration Service
       |
       v
Order Validation
       |
       v
Warehouse Submission
Enter fullscreen mode Exit fullscreen mode

Configuring a WooCommerce Webhook

In WooCommerce, navigate to:

WooCommerce → Settings → Advanced → Webhooks

Create a webhook with settings such as:

Name: Order Fulfillment Integration

Status: Active

Topic: Order updated

Delivery URL:
https://your-integration.example/webhooks/woocommerce

Secret:
A strong, randomly generated secret
Enter fullscreen mode Exit fullscreen mode

The order-updated event can help detect status transitions, but your integration must still inspect the order and determine whether it is eligible for fulfillment.

For example, an order in pending status should generally not be shipped simply because it exists.

4. Receiving WooCommerce Webhooks with Python

Let's build a small webhook receiver using Flask.

First, install the required package:

pip install flask
Enter fullscreen mode Exit fullscreen mode

Next, create a webhook endpoint.

import os
import hmac
import hashlib
import base64

from flask import Flask, request, abort

app = Flask(__name__)

WEBHOOK_SECRET = os.environ["WC_WEBHOOK_SECRET"]


def verify_signature(payload, received_signature):
    digest = hmac.new(
        WEBHOOK_SECRET.encode("utf-8"),
        payload,
        hashlib.sha256,
    ).digest()

    expected_signature = base64.b64encode(
        digest
    ).decode("utf-8")

    return hmac.compare_digest(
        expected_signature,
        received_signature,
    )


@app.post("/webhooks/woocommerce")
def receive_webhook():
    payload = request.get_data()

    signature = request.headers.get(
        "X-WC-Webhook-Signature",
        "",
    )

    if not verify_signature(payload, signature):
        abort(401)

    event = request.get_json(silent=True)

    if not isinstance(event, dict):
        abort(400)

    order_id = event.get("id")

    if order_id is None:
        abort(400)

    print(f"Received WooCommerce event: {order_id}")

    # Production implementation:
    # 1. Persist the event in a durable queue.
    # 2. Deduplicate the event.
    # 3. Fetch the current order state.
    # 4. Process fulfillment asynchronously.

    return {"received": True}, 200
Enter fullscreen mode Exit fullscreen mode

This demonstrates how to verify the webhook signature and inspect an incoming event.

Important: This is an educational receiver, not a complete production integration.

A production service should validate request sizes, use HTTPS, store accepted events durably, avoid logging customer personal information, and acknowledge events only after reliable persistence.

It should also handle WooCommerce's initial webhook test request appropriately.

For more details, consult the official WooCommerce webhook documentation.

5. Never Fulfill an Order Without Checking Its Status

One of the most common integration mistakes is assuming that every new order should immediately be sent to the warehouse.

That can lead to unpaid or cancelled orders being shipped.

A safer approach is to define fulfillment eligibility rules.

For example:

def is_fulfillment_eligible(order):
    if order.get("status") != "processing":
        return False

    if not order.get("date_paid"):
        return False

    if not order.get("line_items"):
        return False

    shipping = order.get("shipping", {})

    required_fields = [
        "address_1",
        "city",
        "postcode",
        "country",
    ]

    return all(
        shipping.get(field)
        for field in required_fields
    )
Enter fullscreen mode Exit fullscreen mode

This is a basic example.

Real-world systems also need to account for:

  • Payment gateway behavior
  • Fraud review
  • Digital versus physical products
  • Shipping destination restrictions
  • Customer address corrections
  • Preorders
  • Backorders
  • Product compliance requirements

The date_paid check is appropriate only when the merchant's payment workflow reliably populates that field. Manually approved or alternative payment workflows may need different rules.

The integration should also use current order data rather than relying entirely on a potentially outdated webhook payload.

6. Mapping WooCommerce Products to Warehouse SKUs

SKU mapping is one of the most important parts of fulfillment automation.

Consider a store selling T-shirts.

The product might have these variations:

Product Variation Store SKU Warehouse SKU
Cotton T-Shirt Black / Small TSH-BLK-S TSH-BLK-S
Cotton T-Shirt Black / Medium TSH-BLK-M TSH-BLK-M
Cotton T-Shirt White / Large TSH-WHT-L TSH-WHT-L

If the integration sends only the product name, the warehouse may not know which variation to ship.

A reliable integration should use stable identifiers and explicit SKU mappings.

Example: Mapping Order Items

SKU_MAPPING = {
    "TSH-BLK-S": "WH-1001",
    "TSH-BLK-M": "WH-1002",
    "TSH-WHT-L": "WH-1003",
}


def map_order_items(order):
    warehouse_items = []

    for item in order["line_items"]:
        store_sku = item.get("sku")

        if store_sku not in SKU_MAPPING:
            raise ValueError(
                f"Unknown SKU: {store_sku}"
            )

        warehouse_items.append({
            "sku": SKU_MAPPING[store_sku],
            "quantity": item["quantity"],
        })

    return warehouse_items
Enter fullscreen mode Exit fullscreen mode

This approach works for simple products and variations with correctly configured SKUs.

However, more complex stores may need additional logic for:

  • Product bundles
  • Personalized products
  • Engraving instructions
  • Subscription orders
  • Product add-ons
  • Multi-item kits

Custom product metadata must be included when it affects physical fulfillment.

Otherwise, the warehouse may receive an order that looks technically valid but lacks important packing instructions.

7. Preventing Duplicate Fulfillment

Webhooks and distributed systems introduce an important challenge: duplicate events.

A webhook might be delivered more than once.

A network timeout might occur after the warehouse has already accepted an order.

An integration might retry a request because it never received a response.

Without proper safeguards, the same customer order could be shipped twice.

The solution is idempotency.

An idempotent fulfillment operation produces the same intended result even when the request is repeated.

A useful idempotency key is:

store_identifier + woo_order_id
Enter fullscreen mode Exit fullscreen mode

For example:

store-001:order-10582
Enter fullscreen mode Exit fullscreen mode

The integration should store this key in a database with a unique constraint.

A basic processing model could look like:

RECEIVED
   |
   v
VALIDATED
   |
   v
SUBMISSION_PENDING
   |
   v
SUBMITTED
   |
   v
ACCEPTED_BY_WAREHOUSE
   |
   v
SHIPPED
Enter fullscreen mode Exit fullscreen mode

If the same order event arrives again, the integration checks the existing record instead of blindly creating another warehouse order.

For stronger reliability, the destination warehouse API should also support an idempotency key or an equivalent unique external order reference.

A local database check alone cannot guarantee exactly-once shipment when requests fail between systems.

8. Handling Warehouse API Failures

A warehouse API can become temporarily unavailable.

A request may fail because of:

  • Network timeouts
  • Authentication errors
  • Invalid product data
  • Missing inventory
  • Unsupported shipping destinations
  • Temporary server failures

Not all errors should be retried automatically.

For example, a temporary server error may be recoverable.

A missing SKU mapping usually requires manual correction.

A useful error-handling strategy is:

Error Recommended Action
Network timeout Check submission status before retrying
Temporary server error Retry with exponential backoff
Invalid API credentials Alert administrator
Unknown SKU Send to manual review
Insufficient inventory Hold order and notify operations
Unsupported destination Request alternative shipping method

Retries should be bounded and observable.

You should also maintain a reconciliation process that periodically compares WooCommerce orders with accepted warehouse orders.

This helps detect missing submissions even when webhook delivery fails.

9. Synchronizing Tracking Numbers Back to WooCommerce

Once the warehouse ships an order, the integration should receive shipment information.

A typical shipment record might contain:

{
  "order_id": 10582,
  "carrier": "Example Carrier",
  "tracking_number": "TRACK123456789",
  "tracking_url": "https://tracking.example/123456789",
  "shipped_at": "2026-10-20T10:30:00Z"
}
Enter fullscreen mode Exit fullscreen mode

This is an illustrative payload, not a standardized WooCommerce response.

WooCommerce stores may use different tracking plugins or fulfillment extensions.

Therefore, your integration must understand how the store expects shipment data to be recorded.

Depending on the implementation, you might need to:

  1. Update a compatible shipment-tracking extension.
  2. Create a fulfillment record using a supported API.
  3. Save tracking information through an approved custom integration.
  4. Trigger the appropriate customer notification.

Do not assume that adding an arbitrary metadata field automatically makes tracking information visible to customers.

Also, avoid marking an order as completed before confirming that your store's shipping and notification workflow is configured correctly.

10. Inventory Synchronization: Physical Stock vs Available Stock

Inventory synchronization becomes especially important when a WooCommerce store uses an external warehouse.

Imagine a warehouse reports:

Physical inventory: 100 units

Reserved inventory: 15 units

Damaged inventory: 5 units
Enter fullscreen mode Exit fullscreen mode

The quantity available for sale is:

100 - 15 - 5 = 80 units
Enter fullscreen mode Exit fullscreen mode

Sending the physical quantity of 100 units directly to WooCommerce could cause overselling.

A better inventory model distinguishes:

  • Physical stock
  • Reserved stock
  • Unavailable stock
  • Available-to-sell stock

Example Calculation

def available_to_sell(
    physical,
    reserved,
    unavailable
):
    return max(
        0,
        physical - reserved - unavailable
    )


available = available_to_sell(
    physical=100,
    reserved=15,
    unavailable=5,
)

print(available)  # 80
Enter fullscreen mode Exit fullscreen mode

For multi-channel sellers, the inventory problem becomes more complex.

The same warehouse stock might support orders from WooCommerce, Shopify, and online marketplaces.

Without a clear source of truth, two storefronts may promise the same inventory to different customers.

A robust architecture should define which system owns inventory reservations and how updates propagate to each sales channel.

11. Special Considerations for Fulfillment from China

The integration architecture becomes more interesting when the warehouse is located in a different country from the customer.

For example, a WooCommerce merchant may sell to US customers while keeping inventory in China.

The technical workflow still involves order import, inventory allocation, picking, packing, and tracking synchronization.

However, additional operational considerations become important.

Shipping Route Selection

The system may need to select shipping services based on:

  • Destination country
  • Package weight
  • Product dimensions
  • Product category
  • Delivery requirements
  • Customs restrictions

Product Compliance

Some products require additional checks before shipment.

Batteries, liquids, supplements, and other regulated goods may not qualify for every shipping service.

Time Zones and Warehouse Cutoffs

An order placed during US business hours may arrive during the following calendar day in China.

Your integration should use explicit time zones and account for warehouse operating hours.

Tracking Events

International shipments may pass through multiple logistics providers.

A tracking system should distinguish between label creation, carrier acceptance, international transit, customs processing, and final delivery.

Address Validation

Incorrect postal codes, incomplete apartment numbers, and unsupported destinations should be identified before the parcel is dispatched.

These operational rules belong in the fulfillment workflow, not just in the storefront.

12. Choosing Between Plugins, Middleware, and Custom APIs

Not every WooCommerce merchant needs to build a custom integration.

The best approach depends on the business.

Integration Method Best For Main Limitation
Manual CSV Export Very small stores Manual work and errors
Fulfillment Plugin Supported standard workflows Plugin compatibility
Middleware Moderate customization Connector and platform limitations
Custom REST API Integration Complex workflows Development and maintenance

For a store with a few daily orders, a supported plugin may be sufficient.

For a larger business with custom bundles, multiple warehouses, and inventory reservations, a dedicated integration service may be more appropriate.

Regardless of the method, confirm that the warehouse system actually supports the required connection.

WooCommerce's API capabilities do not automatically mean every fulfillment provider offers a ready-made integration.

13. Production Checklist

Before deploying a WooCommerce fulfillment integration, verify the following:

  • [ ] API credentials use appropriate permissions.
  • [ ] All connections use HTTPS.
  • [ ] Webhook signatures are validated.
  • [ ] Events are persisted before acknowledgment.
  • [ ] Orders are checked for payment and fulfillment eligibility.
  • [ ] Product variations map to correct warehouse SKUs.
  • [ ] Duplicate submissions are prevented.
  • [ ] Network failures have safe retry behavior.
  • [ ] Warehouse acceptance is recorded.
  • [ ] Tracking updates use a supported integration.
  • [ ] Inventory reservations have a defined source of truth.
  • [ ] Customer data is handled securely.
  • [ ] Failed orders appear in a monitoring dashboard.
  • [ ] A reconciliation process detects missing orders.
  • [ ] Cancellation and address-change rules are documented.

Test these workflows in a staging environment before processing live customer orders.

14. A Note on China-Based Fulfillment Operations

At FulfillBros, we work with ecommerce businesses on China sourcing, warehousing, order fulfillment, and international shipping.

Our operational services include product sourcing through Chinese supplier channels, inventory handling, packing, and access to more than 30 logistics partners.

For merchants using WooCommerce, the appropriate order exchange method depends on the store configuration and the integration capabilities available for the specific account.

The architecture discussed in this article is a general implementation pattern, not a claim that every feature is available through a prebuilt FulfillBros connector.

If you're evaluating the operational side of an integration, you can learn more about our China-based ecommerce fulfillment services.

Conclusion

Automating WooCommerce fulfillment is not simply about connecting two APIs.

A reliable system must handle the entire order lifecycle:

Order creation → Payment validation → SKU mapping → Warehouse submission → Inventory allocation → Shipment tracking → Reconciliation

REST APIs provide access to ecommerce data.

Webhooks make event-driven workflows possible.

But the reliability of the integration depends on how developers handle duplicate events, failed requests, inventory changes, and warehouse exceptions.

Start with a simple architecture, define clear ownership of data, and test failure scenarios before scaling.

When these foundations are in place, WooCommerce can support a more efficient fulfillment workflow without relying on manual spreadsheets and repeated data entry.


Further Reading

This article is an expanded technical adaptation of a guide originally published on the FulfillBros blog. The code examples are educational and should be adapted and tested before production deployment.

_About FulfillBros

FulfillBros helps Shopify sellers and DTC brands manage sourcing, China warehousing, order fulfillment, custom packaging and international shipping from one workflow.

If you're moving from supplier-direct dropshipping to stocked fulfillment, you can learn more about our China fulfillment services or talk with our team about your current order volume and SKU setup._
https://www.fulfillbros.com/

Top comments (0)