Marketplaces / WooCommerce Technical Sccope / WooCommerce Order Management / WooCommerce Ship Orders (through Shipment Tracking

WooCommerce Ship Orders (through Shipment Tracking plugin)

Version Date Created / Updated Notes
v1.0 14/05/2025 Hristiyan Georgiev Initial version

The below documentation is for shipment tracking through a specific WooCommerce plugin which is called Shipment Tracking. Standard shipment is not possible through API without a plugin in WooCommerce. Link for the plugin can be found here - https://woocommerce.com/products/shipment-tracking/

In order to ship orders in WooCommerce we first need to get & store all the available carriers, as when pushing the shipment we need to provide the shipping provider. We also have the possibility to ship with an unlisted courier in WooCommerce and this is sent as custom tracking provider (more explanation below).

Other than that, the shipment process is straightforward - we provide the shipping carrier info, tracking info and dispatch time. With the standard shipment call we are only able to do full shipments so we do not provide product information at all.

This plugin does not currently provide native support for partial shipments via its REST API or built-in features. Partial shipment functionality is typically handled by third-party plugins, which add custom order statuses, shipment tracking, and API endpoints for managing partial shipment. There are many plugins and we will probably have to handle this as we go meaning that we might have to integrate to a couple of “plugins” which handle partial shipment, depending which plugin is used by our customer. This is not part of the scope here.

Get Shipping Providers

Using this call we will be able to store the shipping providers in WooCommerce. We want to display

We also want to introduce Courier mapping, and we will use a dependant table of Courier called WooCommerce Couriers Mapping for this use. In this table we need to have a dropdown field with all the carriers. The field will be called WooCommerce Courier where we will show the names of all the available couriers in WooCommerce.

If WooCommerce adds or removes couriers, we want to respectively add/remove them from the table. We don’t want to truncate the table with each run.

API Call : GET /wp-json/wc-shipment-tracking/v3/shipment-trackings/providers

API Docs : https://woocommerce.com/document/shipment-tracking/

Example response :

{
    "Global": {
        "Aramex": "https://www.aramex.com/track/track-results-new?ShipmentNumber=%1$s"
    },
    "Australia": {
        "Australia Post": "https://auspost.com.au/mypost/track/#/details/%1$s",
        "Fastway Couriers": "https://www.fastway.com.au/tools/track/?l=%1$s",
        "Aramex Australia": "https://www.aramex.com.au/tools/track?l=%1$s"
    },
    "Austria": {
        "post.at": "https://www.post.at/sv/sendungsdetails?snr=%1$s",
        "dhl.at": "https://www.dhl.at/content/at/de/express/sendungsverfolgung.html?brand=DHL&AWB=%1$s",
        "DPD.at": "https://tracking.dpd.de/parcelstatus?locale=de_AT&query=%1$s"
    },
    "Brazil": {
        "Correios": "http://websro.correios.com.br/sro_bin/txect01$.QueryList?P_LINGUA=001&P_TIPO=001&P_COD_UNI=%1$s"
    },
    "Belgium": {
        "bpost": "https://track.bpost.be/btr/web/#/search?itemCode=%1$s&postalCode=%2$s"
    },
    "Canada": {
        "Canada Post": "https://www.canadapost-postescanada.ca/track-reperage/en#/resultList?searchFor=%1$s",
        "Purolator": "https://www.purolator.com/purolator/ship-track/tracking-summary.page?pin=%1$s"
    },
    "Czech Republic": {
        "PPL.cz": "https://www.ppl.cz/main2.aspx?cls=Package&idSearch=%1$s",
        "Česká pošta": "https://www.postaonline.cz/trackandtrace/-/zasilka/cislo?parcelNumbers=%1$s",
        "DHL.cz": "https://www.dhl.cz/cs/express/sledovani_zasilek.html?AWB=%1$s",
        "DPD.cz": "https://tracking.dpd.de/parcelstatus?locale=cs_CZ&query=%1$s"
    },
    "Finland": {
        "Itella": "https://www.posti.fi/itemtracking/posti/search_by_shipment_id?lang=en&ShipmentId=%1$s"
    },
    "France": {
        "Colissimo": "https://www.laposte.fr/outils/suivre-vos-envois?code=%1$s"
    },
    "Germany": {
        "DHL Intraship (DE)": "https://www.dhl.de/de/privatkunden/pakete-empfangen/verfolgen.html?lang=de&idc=%1$s&rfn=&extendedSearch=true",
        "Hermes": "https://www.myhermes.de/empfangen/sendungsverfolgung/sendungsinformation/#%1$s",
        "Deutsche Post DHL": "https://www.dhl.de/de/privatkunden/pakete-empfangen/verfolgen.html?lang=de&idc=%1$s",
        "UPS Germany": "https://wwwapps.ups.com/WebTracking?sort_by=status&tracknums_displayed=1&TypeOfInquiryNumber=T&loc=de_DE&InquiryNumber1=%1$s",
        "DPD.de": "https://tracking.dpd.de/parcelstatus?query=%1$s&locale=en_DE"
    },
    "Ireland": {
        "DPD.ie": "https://dpd.ie/tracking?deviceType=5&consignmentNumber=%1$s",
        "An Post": "https://track.anpost.ie/TrackingResults.aspx?rtt=1&items=%1$s"
    },
    "Italy": {
        "BRT (Bartolini)": "https://vas.brt.it/vas/sped_det_show.hsm?Nspediz=%1$s",
        "DHL Express": "https://www.dhl.it/it/express/ricerca.html?AWB=%1$s&brand=DHL"
    },
    "India": {
        "DTDC": "https://www.dtdc.in/tracking/tracking_results.asp?Ttype=awb_no&strCnno=%1$s&TrkType2=awb_no"
    },
    "Netherlands": {
        "PostNL": "https://postnl.nl/tracktrace/?B=%1$s&P=%2$s&D=%3$s&T=C",
        "DPD.NL": "https://tracking.dpd.de/status/en_US/parcel/%1$s",
        "UPS Netherlands": "https://wwwapps.ups.com/WebTracking?sort_by=status&tracknums_displayed=1&TypeOfInquiryNumber=T&loc=nl_NL&InquiryNumber1=%1$s"
    },
    "New Zealand": {
        "Courier Post": "https://trackandtrace.courierpost.co.nz/Search/%1$s",
        "NZ Post": "https://www.nzpost.co.nz/tools/tracking?trackid=%1$s",
        "Aramex New Zealand": "https://www.aramex.co.nz/tools/track?l=%1$s",
        "PBT Couriers": "http://www.pbt.com/nick/results.cfm?ticketNo=%1$s"
    },
    "Poland": {
        "InPost": "https://inpost.pl/sledzenie-przesylek?number=%1$s",
        "DPD.PL": "https://tracktrace.dpd.com.pl/parcelDetails?p1=%1$s",
        "Poczta Polska": "https://emonitoring.poczta-polska.pl/?numer=%1$s"
    },
    "Romania": {
        "Fan Courier": "https://www.fancourier.ro/awb-tracking/?tracking=%1$s",
        "DPD Romania": "https://tracking.dpd.de/parcelstatus?query=%1$s&locale=ro_RO",
        "Urgent Cargus": "https://app.urgentcargus.ro/Private/Tracking.aspx?CodBara=%1$s"
    },
    "South African": {
        "SAPO": "http://sms.postoffice.co.za/TrackingParcels/Parcel.aspx?id=%1$s",
        "Fastway": "https://fastway.co.za/our-services/track-your-parcel?l=%1$s",
        "EPX": "https://epx.pperfect.com/?w=%1$s"
    },
    "Sweden": {
        "PostNord Sverige AB": "https://portal.postnord.com/tracking/details/%1$s",
        "DHL.se": "https://www.dhl.com/se-sv/home/tracking.html?submit=1&tracking-id=%1$s",
        "Bring.se": "https://tracking.bring.se/tracking/%1$s",
        "UPS.se": "https://www.ups.com/track?loc=sv_SE&tracknum=%1$s&requester=WT/",
        "DB Schenker": "http://privpakportal.schenker.nu/TrackAndTrace/packagesearch.aspx?packageId=%1$s"
    },
    "United Kingdom": {
        "DHL": "https://www.dhl.com/content/g0/en/express/tracking.shtml?brand=DHL&AWB=%1$s",
        "DPD.co.uk": "https://www.dpd.co.uk/apps/tracking/?reference=%1$s#results",
        "DPD Local": "https://apis.track.dpdlocal.co.uk/v1/track?postcode=%2$s&parcel=%1$s",
        "EVRi": "https://www.evri.com/track/parcel/%1$s",
        "EVRi (international)": "https://international.evri.com/tracking/%1$s",
        "ParcelForce": "https://www.parcelforce.com/track-trace?trackNumber=%1$s",
        "Royal Mail": "https://www3.royalmail.com/track-your-item#/tracking-results/%1$s",
        "TNT Express (consignment)": "https://www.tnt.com/express/en_gb/site/shipping-tools/tracking.html?searchType=con&cons=%1$s",
        "TNT Express (reference)": "https://www.tnt.com/express/en_gb/site/shipping-tools/tracking.html?searchType=ref&cons=%1$s",
        "DHL Parcel UK": "https://track.dhlparcel.co.uk/?con=%1$s"
    },
    "United States": {
        "DHL US": "https://www.logistics.dhl/us-en/home/tracking/tracking-ecommerce.html?tracking-id=%1$s",
        "DHL eCommerce": "https://webtrack.dhlecs.com/orders?trackingNumber=%1$s",
        "Fedex": "https://www.fedex.com/apps/fedextrack/?action=track&action=track&tracknumbers=%1$s",
        "FedEx Sameday": "https://www.fedexsameday.com/fdx_dotracking_ua.aspx?tracknum=%1$s",
        "GlobalPost": "https://www.goglobalpost.com/track-detail/?t=%1$s",
        "OnTrac": "https://www.ontrac.com/tracking/?number=%1$s",
        "UPS": "https://www.ups.com/track?loc=en_US&tracknum=%1$s",
        "USPS": "https://tools.usps.com/go/TrackConfirmAction_input?qtc_tLabels1=%1$s"
    }
}

The way we want to store the couriers in MCPro is to concatinate the country and courier name. So an example would be - United States - DHL US, United States - DHL eCommerce etc. We don’t want to store the links.

Add tracking info to order

We want to use the new shipment model through the Order Shipment table. All triggers & validations are per the abstraction -

Order management general requirements

We want to introduce a default courier field which will be in the Channels WooCommerce. The field will be an enum dropdown menu where the user can select the desired default courier. The field should not be required. Even if there is a selected default courier, we should first check if we have mapping from the courier on order with a record in table Courier and pick this with priority. We should only pick the default courier if there is no mapping for the selected courier.

**The mapping will work based on:

  • If Order Shipment > Carrier matches Courier > Name we send the selected courier WooCommerceCourier Mappings > WooCommerce Courier
  • If there is no match or no value in the mapping table we need to go into a third case which is to use our default courier set in the Channel WooCommerce table.
  • If we don’t have a default courier and courier mapping and the user tries to send a courier which is not part of the WooCommerce list, we have the possibility to send the courier as a custom tracking provider (details will be in the mapping below)

API Call : POST /wp-json/wc-shipment-tracking/v3/orders/{orderId}/shipment-trackings API Docs : https://woocommerce.com/document/shipment-tracking/

The orderId we pick from Orders > Marketplace Order ID

It is important to note that with this call we are not shipping the order, but we are adding the tracking info. The order will still be in processing status and we need to mark it as Completed after we have added the tracking info. We mark it as completed with a subsequent call that we want to make after this one (explanation below). As a suggestion, both calls should be incorporated into one cron.

Call Body :

{
  "tracking_provider": "Aramex",
  "custom_tracking_provider": "Bai Ivan",
  "custom_tracking_link": "https://www.speedy.bg/public/bg/track-shipment",
  "tracking_number": "12345678",
  "date_shipped": "2025-05-14"
}

Mapping :

WooCommerce FIeld MCPro Field Notes
tracking_provider Order Shipment > Carrier

OR WooCommerce Courier Mappings > WooCommerce Courier OR Channel WooCommerce > Default Courier | Depends on the conditions mentioned above. We need to trim the country and only send the courier name. If we are sending custom_tracking_provider , we need to exclude this field from the payload | | custom_tracking_provider | Order Shipment > Carrier | This field is only used when we are sending a courier that is not listed on WooCommerce. We need to exclude this from the payload if we are sending a listed courier. | | custom_tracking_link | Order Shipment > Tracking URL OR Courier > Courier URL | We need to include this field only when sending custom_tracking_provider in all other cases we exclude it. Order Shipment is with priority. | | tracking_number | Order Shipment > Tracking Number | | | date_shipped | Order Shipment > Shipped Time | Needs to be send in a format of “YYYY-MM-DD”. This field is optional so if we don’t have it filled, we can exclude it from the payload. |

Example Success Response :

{
    "tracking_id": "f0e366d87f8c6b0e6b34932b9478729a",
    "tracking_provider": "Bai Ivan",
    "tracking_link": "https://www.speedy.bg/public/bg/track-shipment",
    "tracking_number": "12345678",
    "date_shipped": "2025-05-14",
    "_links": {
        "self": [
            {
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc-shipment-tracking/v3/orders/56/shipment-trackings/f0e366d87f8c6b0e6b34932b9478729a",
                "targetHints": {
                    "allow": [
                        "GET",
                        "DELETE"
                    ]
                }
            }
        ],
        "collection": [
            {
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc-shipment-tracking/v3/orders/56/shipment-trackings"
            }
        ],
        "up": [
            {
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc-shipment-tracking/v3/orders/56"
            }
        ]
    }
}

Example Error Response :

{
    "code": "rest_missing_callback_param",
    "message": "Missing parameter(s): tracking_number",
    "data": {
        "status": 400,
        "params": [
            "tracking_number"
        ]
    }
}

From the success response we only want to map the tracking_id into Order Shipment > External Id .

From the error response we want to create a record in Order Error > Type = Shipping and store the message .

If we had a success response, at this point we still don’t want to mark our shipment record from pending to completed. As mentioned above, we need to make an additional call to mark the order as completed on WooCommerce.

Mark order as completed

Ideally we would like to perform this call straight after the previous one. However, if for some reason the previous call is success but this one fails, we want to use the Order Shipment > External Id as trigger so the next time our order ship cron starts, it will see that we have an external id for a specific record and it will skip the first step of adding the tracking and just try to mark the order as completed.

API Call : PUT /wp-json/wc/v3/orders/{orderId}

API Docs : https://woocommerce.github.io/woocommerce-rest-api-docs/?shell#update-an-order

The orderId we pick from Orders > Marketplace Order ID

Call body :

{
  "status": "completed"
}

We just send the status hardcoded as “completed”

Example Success Response :

{
    "id": 52,
    "parent_id": 0,
    "status": "completed",
    "currency": "USD",
    "version": "9.8.5",
    "prices_include_tax": false,
    "date_created": "2025-05-12T11:18:27",
    "date_modified": "2025-05-14T11:26:20",
    "discount_total": "0.00",
    "discount_tax": "0.00",
    "shipping_total": "10.00",
    "shipping_tax": "0.00",
    "cart_tax": "0.00",
    "total": "370.00",
    "total_tax": "0.00",
    "customer_id": 0,
    "order_key": "wc_order_ocLQCVE4FlgYB",
    "billing": {
        "first_name": "Johnkata",
        "last_name": "Doe",
        "company": "",
        "address_1": "969 Market",
        "address_2": "",
        "city": "Sofia",
        "state": "Sofia",
        "postcode": "1700",
        "country": "Bulgaria",
        "email": "john.doe@example.com",
        "phone": "(555) 555-5555"
    },
    "shipping": {
        "first_name": "Johnkata",
        "last_name": "Doe",
        "company": "",
        "address_1": "969 Market",
        "address_2": "",
        "city": "Sofia",
        "state": "Sofia",
        "postcode": "1700",
        "country": "BG",
        "phone": ""
    },
    "payment_method": "bacs",
    "payment_method_title": "Direct Bank Transfer",
    "transaction_id": "",
    "customer_ip_address": "",
    "customer_user_agent": "",
    "created_via": "rest-api",
    "customer_note": "",
    "date_completed": "2025-05-14T11:26:20",
    "date_paid": "2025-05-12T11:18:27",
    "cart_hash": "",
    "number": "52",
    "meta_data": [
        {
            "id": 14,
            "key": "_wc_shipment_tracking_items",
            "value": [
                {
                    "tracking_provider": "aramex",
                    "custom_tracking_provider": null,
                    "custom_tracking_link": null,
                    "tracking_number": "12345678",
                    "date_shipped": 1747210980,
                    "tracking_id": "6738eed4d77cf648608183a8709bb8be"
                }
            ]
        }
    ],
    "line_items": [
        {
            "id": 7,
            "name": "Popover Heavyweight Hooded Sweatshirt in Red",
            "product_id": 17,
            "variation_id": 0,
            "quantity": 2,
            "tax_class": "",
            "subtotal": "240.00",
            "subtotal_tax": "0.00",
            "total": "240.00",
            "total_tax": "0.00",
            "taxes": [],
            "meta_data": [],
            "sku": "",
            "price": 120,
            "image": {
                "id": "23",
                "src": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-content/uploads/2025/05/6dc67-product-4.png"
            },
            "parent_name": null
        },
        {
            "id": 8,
            "name": "Vintage Slub Cotton Crewneck T-shirt",
            "product_id": 18,
            "variation_id": 0,
            "quantity": 3,
            "tax_class": "",
            "subtotal": "120.00",
            "subtotal_tax": "0.00",
            "total": "120.00",
            "total_tax": "0.00",
            "taxes": [],
            "meta_data": [],
            "sku": "",
            "price": 40,
            "image": {
                "id": "25",
                "src": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-content/uploads/2025/05/507df-product-2.png"
            },
            "parent_name": null
        }
    ],
    "tax_lines": [],
    "shipping_lines": [
        {
            "id": 9,
            "method_title": "Flat Rate",
            "method_id": "flat_rate",
            "instance_id": "",
            "total": "10.00",
            "total_tax": "0.00",
            "taxes": [],
            "tax_status": "taxable",
            "meta_data": []
        }
    ],
    "fee_lines": [],
    "coupon_lines": [],
    "refunds": [],
    "payment_url": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/checkout/order-pay/52/?pay_for_order=true&key=wc_order_ocLQCVE4FlgYB",
    "is_editable": false,
    "needs_payment": false,
    "needs_processing": true,
    "date_created_gmt": "2025-05-12T08:18:27",
    "date_modified_gmt": "2025-05-14T08:26:20",
    "date_completed_gmt": "2025-05-14T08:26:20",
    "date_paid_gmt": "2025-05-12T08:18:27",
    "gift_cards": [],
    "currency_symbol": "$",
    "_links": {
        "self": [
            {
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc/v2/orders/52",
                "targetHints": {
                    "allow": [
                        "GET",
                        "POST",
                        "PUT",
                        "PATCH",
                        "DELETE"
                    ]
                }
            }
        ],
        "collection": [
            {
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc/v2/orders"
            }
        ],
        "email_templates": [
            {
                "embeddable": true,
                "href": "https://ecom-delicately-vibrant-shark.wpcomstaging.com/wp-json/wc/v2/orders/52/actions/email_templates"
            }
        ]
    }
}

Example error response :

{
    "code": "rest_invalid_param",
    "message": "Invalid parameter(s): status",
    "data": {
        "status": 400,
        "params": {
            "status": "status is not one of auto-draft, pending, processing, on-hold, completed, cancelled, refunded, failed, and checkout-draft."
        },
        "details": {
            "status": {
                "code": "rest_not_in_enum",
                "message": "status is not one of auto-draft, pending, processing, on-hold, completed, cancelled, refunded, failed, and checkout-draft.",
                "data": null
            }
        }
    }
}

From the success response we want to store the date_completed_gmt into Order Shipment > Shipment Processed Time and mark the order as shipped.

From the error response we want to create a record in Order Error > Type = Shipping and store the details > status >message

Is this article helpful?
0 0 0