Plugin documentation

Advance Partial Shipment for WooCommerce

Ship one WooCommerce order in several parcels, with a provider, tracking number and status for each, customer emails, a tracking page, a Fulfillment Report, a REST endpoint and webhooks.

Version 3.4.0 WooCommerce plugin Paid plugin Requires WordPress 6.4 Requires PHP 7.4 Tested up to 7.1 Updated 6 Oct 2026

1. Overview

Advance Partial Shipment for WooCommerce lets you ship one WooCommerce order in several parcels. For each parcel you choose which items and how many of each, then record a provider, a tracking number, a status, dates and notes. The original order is never split or edited. The plugin keeps track of what has shipped, what is left, and tells the customer.

It is for shops that often cannot send a whole order in one go: backorders, made-to-order items, stock in several places, or orders that are too big for one parcel. The owner works in a box on the order screen. The customer sees the parcels, with a four-step timeline, on their order page, and can look a parcel up by tracking number on a page you publish with a shortcode.

The plugin is listed on the Plugins screen as "Advance Partial Shipment for WooCommerce". This page describes version 3.4.0.

How it works

  1. On every order edit screen a Partial Shipment box appears in the sidebar, below Order actions.
  2. You add a shipment: pick a provider, type the tracking number, set the quantity of each item and save. The quantities you can enter never exceed what is still unshipped (ordered minus refunded minus already shipped).
  3. The plugin recalculates the order status. With the defaults, a partly shipped order becomes Partially Shipped and a fully shipped one becomes Completed.
  4. The customer gets a New Partial Shipment email with the items, the provider, the tracking link and a QR code. Later changes to the parcel can send a Partial Shipment Update email.
  5. You move each parcel through Ready, Picked, Dispatched and Delivered with one click. The customer's timeline follows.

At a glance

Parcels with tracking

Any number of shipments per order. Each has its own items, provider, tracking number, status, shipment date, estimated delivery date, customer note and internal note.

Providers by country

58 built-in providers for 20 countries, your own providers with a tracking URL template (offered on every order), or any custom tracking URL for one shipment.

Customer emails

Two WooCommerce emails, HTML and plain text. Send the first one when the shipment is created or only when it is first marked Picked.

Statuses that follow the shipment

Optional "Partially Shipped" order status and optional automatic completion. Quantities are net of refunds.

Customer views

Item badges and a shipment timeline on the order page, and a public tracking lookup page with the [wphub_shipment_tracking] shortcode.

Reports and integrations

Fulfillment Report with CSV export, bulk shipments, REST endpoint, signed webhooks, packing slips and delivery notes, data retention, and CSV or XML import with the paid add-on.

How the three plugins fit together

Three WpExperts Hub plugins work with the same shipment data. Each of the three documentation pages carries this same section, so you can read it on whichever page you start from.

PluginPlugin folderNeedsWhat it does on its own
Partial Shipment for WooCommerce (the free plugin)wc-partial-shipmentWooCommerceRecords how many units of each order item have shipped. It has no tracking numbers, providers or shipment statuses. It adds item badges, the optional "Partially Shipped" order status, automatic completion and one email that you send by hand.
Advance Partial Shipment for WooCommerce (Advance, paid)wphub-partial-shipmentWooCommerceSplits an order into parcels. Each parcel has its own items, provider, tracking number, status, dates and notes, and its own customer emails. It also adds a tracking page, a Fulfillment Report, a REST endpoint and webhooks.
Advance Partial Shipment Extension for WP All Import (the add-on, paid)wpai-shipmentAdvance, WP All ImportNothing without Advance. With Advance it imports parcels from a CSV or XML file through WP All Import. The Plugins screen lists it as "Advance Partial Shipment — WP All Import Add-On".

Shared data

The free plugin and Advance keep their records in the same two database tables, partial_shipment and partial_shipment_items (each with your WordPress table prefix, for example wp_partial_shipment). They also share the order status wc-partial-shipped ("Partially Shipped"), the WooCommerce settings tab wxp_partial_shipping_settings (shown as Partial Shipment) and three option keys: partially_shipped_status, partially_auto_complete and partially_enable_status_popup. A value you save with one of the two plugins is the value the other one reads.

DataFree pluginAdvanceAdd-on
Rows in partial_shipmentOne row per order, always with shipment_id 1 and no tracking number.One row per parcel. shipment_id counts 1, 2, 3 within the order. Tracking number, provider link, status, dates and notes belong to the parcel.None of its own. It asks Advance to create or update parcels.
Rows in partial_shipment_itemsOne row per order item, holding the total quantity shipped.One row per item in each parcel.None of its own.
Creating the tablesCreates both tables with a unique key on order_id, so one row per order.Creates them when missing. On upgrade it removes that unique key and adds the columns for status, dates, notes and email tracking.Creates no tables.

Only one of the free plugin and Advance runs at a time

If both are active, the free plugin does nothing. When its file loads, the free plugin checks whether Advance (wphub-partial-shipment/wphub-partial-shipment.php) is active, on the current site or network-wide. If it is, the free plugin registers none of its screens, settings or hooks. Advance also switches the free plugin off. On the next request to wp-admin it silently deactivates wc-partial-shipment/woocommerce-partial-shipment.php and shows a one-time notice. On multisite, WordPress 7.1.2 deactivates it this way only when it is network-activated. A copy that is activated on a single site stays active but idle, and Advance still shows its "was deactivated" notice on each wp-admin page of that site until you deactivate the free plugin yourself. Neither step deletes shipment data. Deactivating Advance later does not switch the free plugin back on; activate it yourself on the Plugins screen.

Switching between the two

From the free plugin to Advance. Activate Advance. It keeps the existing rows, so every order the free plugin recorded now has one parcel, Shipment #1, with no provider and no tracking number. The free plugin stores no shipment status, so that parcel shows as Ready (as "Ordered" on the customer's order page) until you change it. On activation Advance also changes the tables: it removes the unique key on order_id so an order can have several parcels, removes the old shipment_primary_id column and adds the new columns. Advance can also create Delivered parcels for older Completed orders in the background; that one-time run is on by default in Advance.

From Advance back to the free plugin. Deactivate Advance, then activate the free plugin. It adds up each item's quantity over all parcels and shows that total in its Shipment popup and badges. It ignores tracking numbers, providers, statuses and notes, and leaves them in the table. When you save new quantities in the free plugin's popup, the difference is applied to the order's first parcel. When a total is lowered, the most recent parcels are reduced first.

What the add-on needs

The add-on works only together with Advance and WP All Import. It does not work with the free plugin, because it creates and updates parcels through Advance, and the free plugin has no parcels, tracking numbers or statuses. The add-on names Advance in its Requires Plugins header, so WordPress 7.1.2 refuses to activate it while Advance is missing or inactive. An add-on that is already active switches itself off on the next request to wp-admin and shows a notice.

What it does not do

  • It never contacts a carrier. It does not check tracking numbers, fetch tracking events or change a status by itself. Statuses change when you click, edit, or use the REST endpoint or an import.
  • It does not create shipping labels, shipping rates or pickups.
  • It does not split an order into several WooCommerce orders. The order stays whole and the parcels are separate records.
  • It does not mark items as shipped when you set an order to Completed by hand. The free plugin does that; Advance does not.
  • It does not add "Partially Shipped" to WooCommerce's list of paid statuses. The free plugin does; Advance does not. WooCommerce 11.1.2 grants download access for Completed orders, and for Processing orders only when Grant access to downloadable products after payment is on. Advance changes none of this.
  • It makes no PDF files itself. Packing slips and delivery notes need the free PDF Invoice for WooCommerce plugin.
  • It registers no privacy exporter or eraser for personal data tools (see Privacy).
  • Nothing in its code reads or writes the separate order fulfilments feature that ships with WooCommerce 11.1.2.

2. Requirements

ItemRequirementNotes
WordPress6.4 or laterFrom the Requires at least header. The readme says tested up to 7.1.
PHP7.4 or laterFrom the Requires PHP header.
WooCommerce8.4 or later, tested up to 11.1From WC requires at least and WC tested up to. The header also says Requires Plugins: woocommerce, so from WordPress 6.5 WordPress will not let you activate the plugin without WooCommerce. On a single site the plugin applies WordPress's active_plugins filter to the list of active plugins and, if woocommerce/woocommerce.php is not in it, loads nothing and shows no message. On multisite it loads without checking.
Order storageHigh-Performance Order Storage or legacy storageThe plugin declares compatibility with custom_order_tables, cart_checkout_blocks and product_block_editor. It reads and writes orders through the WooCommerce order API. It adds nothing to the cart or checkout.
DatabaseMySQL or MariaDB with GET_LOCK()Creating and editing a shipment takes a named database lock for the order and waits up to 15 seconds for it. If the lock cannot be taken the shipment is not saved ("Unable to save shipment.").
PDF Invoice for WooCommerceOptionalNeeded only for the Packing Slip and Delivery Note buttons. Without it the buttons are hidden. The plugin passes a file name to PDF Invoice; the code comment says PDF Invoice 1.6 or later uses it and older versions ignore it.
Action SchedulerOptional (bundled with WooCommerce)Runs the background "mark existing orders as shipped" job in batches of 25 orders. If Action Scheduler were missing, the plugin would process a single batch of 25 orders inside the current request and would not continue afterwards. WooCommerce always bundles it, so this matters only if it has been removed.
WP All Import and the add-onOptionalOnly for importing shipments from a file. See the add-on's own page.
User permissionedit_others_shop_orders and manage_woocommerceThe Partial Shipment box, its buttons and the packing slip links need edit_others_shop_orders. The settings tab, Fulfillment Report, backfill, API key and webhook test need manage_woocommerce. WooCommerce gives both to Administrators and Shop managers. The licence screen needs manage_options.
Working WooCommerce emailsRequired for customer emailsThe two emails are standard WooCommerce emails. If your site cannot send email, no shipment email arrives.
Outbound HTTPSNeeded for licence and updates onlyOptional. See Privacy. The plugin works without it.

3. Installation

  1. Download the plugin zip from your account on wpexpertshub.com.
  2. In WordPress open Plugins → Add New Plugin → Upload Plugin, choose the zip file, click Install Now and then Activate.
  3. Open Plugins → WpExperts Hub Licences, paste your licence key and click Activate licence. This is optional for using the plugin and needed for updates. See Licence and updates.
  4. Open WooCommerce → Settings → Partial Shipment and check the settings. A Settings link is also shown under the plugin name on the Plugins screen.
  5. Open any order that has physical items. The Partial Shipment box is in the sidebar.
Activation can mark old orders as shipped.On the first wp-admin page load after activation, the plugin starts a one-time background run that creates a Delivered shipment for every unshipped physical item on Completed orders placed before the activation (no customer email and no webhook). It is on by default. To prevent it, create the option wphub_backfill_completed with the value no before you activate the plugin, or untick Automatic run on the settings screen as early as you can. See Mark existing orders as shipped.

Licence and updates

The plugin bundles the WpExperts Hub licence and update client (licence/class-wpxh-licence-client.php, version 2.0.0). It works as follows.

  • The screen. Plugins → WpExperts Hub Licences lists every WpExperts Hub plugin that bundles this client on your site, one card each, with an Active or Not active label and the installed version. You need manage_options to open it. Advance's own link under the plugin name on the Plugins screen reads Activate License or Deactivate License and opens the same screen.
  • Activate. Paste the key from your purchase email (also shown in My Account → Downloads on wpexpertshub.com) and click Activate licence. Only letters, digits and hyphens are kept; anything else you type is dropped. The key and an "active" status are stored on your site only when the licence server says yes.
  • Deactivate. Click Deactivate licence on the card (the key is shown masked, for example the first four and last four characters). Do this before you move the plugin to another live site. The key is removed from your site even when the licence server cannot be reached, so the site is never stuck.
  • Lost your key. On a card without an active licence, open Can't find your key? Email it to me, enter the email address used for the purchase and click Send licence key. The server sends the email.
  • Updates. New versions arrive through the normal Dashboard → Updates and Plugins screens. The update information is requested from the licence server in one batched request and cached for 12 hours (one hour after a failed request). The client installs whatever package address the server returns. According to the client's own documentation, the server returns an address only for sites with an active licence. Without one, WordPress shows "Automatic update is unavailable for this plugin. Activate your licence to enable updates."
  • The plugin works without a licence. No feature of the plugin checks the licence. Its status is read only by the licence client itself (the screen, the reminder and the update requests) and by the link text under the plugin name. The key only unlocks update packages.
  • Reminder. On the Plugins screen, administrators see a notice, "Activate your WpExperts Hub licence to receive updates for: ...", while any plugin using the client has no active licence. It has a Manage licences link and cannot be dismissed.

What is sent to wpexpertshub.com, and when, is listed in Privacy.

What activation creates

  • Two database tables, partial_shipment and partial_shipment_items (with your table prefix), created only if missing and then brought up to date. See Database tables.
  • Two options: wphub_partial_shipment_db_version (the schema number, currently 3) and wphub_partial_shipment_activated (the activation time, written once).
  • No roles, no pages and no capabilities. No cron event until you choose a data retention period. No background job until the first backfill run starts.

Upgrading from the free plugin

If the free Partial Shipment for WooCommerce is active, Advance deactivates it on the first request to wp-admin and keeps its data. The rules, and what the existing records look like afterwards, are in How the three plugins fit together. The three options the two plugins share keep their values. The settings screen is the same tab (WooCommerce → Settings → Partial Shipment) with more cards.

Updating

Update through the normal WordPress screens. On the first request after an update (any request, including REST and cron, not only wp-admin) the plugin compares the stored schema number with the schema number it expects (currently 3) and runs the table upgrade steps when they differ. Schema 2 added the delivered_date column (version 3.2.1). Schema 3 made the order_id index non-unique for tables first created by the free plugin (version 3.3.0). Your settings and shipments are kept. Licence activations made with the older licence client are kept, because the new client reads the same option names.

Multisite

The plugin can be activated on one site or network-wide. The tables use the table prefix of each site, so every site has its own shipments, and each site creates its tables on its first request after activation (the schema check runs on init). Settings and the licence are stored per site. The licence screen is added to a site's admin Plugins menu; the client adds nothing to the network admin. On multisite WordPress 7.1.2 deactivates the free plugin on behalf of Advance only when the free plugin is network-activated (see How the three plugins fit together).

Deactivating and deleting

Deactivating removes the daily retention cron event and the pending background backfill actions. All shipments, options and tables stay. Advance has no uninstall routine, so deleting the plugin from the Plugins screen removes only its files. The tables, the options listed under Options and the licence options stay in your database until you remove them yourself. Back up first if you do.

4. Quick start

  1. Install and activate Advance. Optionally activate your licence under Plugins → WpExperts Hub Licences.
  2. Open WooCommerce → Settings → Partial Shipment. Check Shipment Email Trigger (default: email at once when a shipment is created) and the other defaults. Click Save changes.
  3. Optional: under Shipping Providers add your own carriers, one per line, as Name|https://example.com/track/%1$s.
  4. Open an order. In the Partial Shipment box, under Add a Shipment, choose a provider, type the tracking number, adjust the quantities and click Save Shipment.
  5. Use Mark Picked, Mark Dispatched and Mark Delivered on the shipment as it moves along.
  6. Check the emails under WooCommerce → Settings → Emails (New Partial Shipment and Partial Shipment Update).
  7. Optional: create a page with the shortcode [wphub_shipment_tracking] so customers can look up a parcel by tracking number.

5. Features

Where a feature depends on WordPress or WooCommerce code, this page says so and names the version that was checked (WordPress 7.1.2 and WooCommerce 11.1.2).

The Partial Shipment box

Open any order at WooCommerce → Orders. In the right-hand column, directly below Order actions, is the Partial Shipment box. The plugin keeps it in that position even if you have rearranged the boxes before. The box appears on both the High-Performance Order Storage screen and the legacy order screen. Only users with edit_others_shop_orders see its contents.

  • A new order that has not been saved yet shows "Save the order first, then add its shipments here."
  • No shipments yet shows "No shipments yet — add one below."
  • Shipment history lists every shipment, oldest first, under a progress line such as "3 of 5 items shipped" with a bar. The numbers are physical units, net of refunds.
  • Each shipment shows its number ("Shipment #2"), a status badge and these buttons: Packing Slip and Delivery Note (only when the PDF Invoice for WooCommerce plugin is usable), Edit and Delete. Below are the shipment date, the provider and the tracking number (a link when a tracking link can be built), the estimated delivery date when set, the three Mark buttons, the customer note and the internal note when they exist, and the list of items with quantities.
  • Add a Shipment is the form at the bottom. When the order status is Pending payment, Cancelled, Refunded or Failed it is replaced by "Shipments cannot be added while the order is "Pending payment"." (with the real status name). Existing shipments on such an order can still be edited and deleted.

Everything in the box works without reloading the page. After each action the box redraws itself, WooCommerce's order items table above reloads (so the shipment badges update) and the order status field in the Order details box changes to the status the plugin has just set. A line under the box shows the result, for example "Shipment added successfully." or "Something went wrong.". When the plugin had to reduce your quantities it adds "(quantities reduced to what is available)". Pressing Enter inside a form field saves that form.

Adding a shipment

FieldRequiredWhat it does
Shipment ProviderNoA list of providers: N/A (no provider) (the default), then the built-in providers for the order's shipping country (the billing country when there is no shipping country), then your custom providers, then Other…. Other… shows a Tracking URL box where you can type any link, with %1$s where the tracking number goes. When no provider list exists for the order (no built-in list for that country and no custom providers) the list is replaced by a plain Tracking URL box.
Tracking NumberYesText, stored in a column of 100 characters. The form refuses to save without it ("Enter a tracking number to save the shipment."), and so does the server ("A tracking number and at least one item quantity are required.").
Items to shipAt least one item above zeroOne number box for each physical line item that still has something to ship, already filled with the remaining quantity. The box accepts 0 up to the remaining quantity and shows "remaining of ordered (net of refunds)", for example "2 of 5". Ship remaining next to a box sets it to its maximum. A line set to 0 is left out of the shipment.
StatusNoReady (default), Picked, Dispatched or Delivered.
Shipment dateNoA date, filled with today. Stored as a day (midnight) and shown in your site's date format.
Estimated deliveryNoA date, stored as Y-m-d. Empty means none.
Internal note (admin only)NoNever shown to customers.
Customer NoteNoShown on the delivery note, in the shipment emails and on the customer's order page.

Click Ship all items to fill every box with its maximum, then Save Shipment. The two buttons are hidden when nothing is left to ship ("No shippable items left for this order.").

Each shipment gets a visible number: the highest number already used on the order plus one. Deleting the newest shipment frees its number for the next one. Numbers are never renumbered.

Quantities are checked on the server.Whatever the form sends, each item is reduced to what is still available. Items that belong to another order, virtual items and quantities of zero or less are dropped. A request with no valid item is refused.

Editing and deleting a shipment

Edit opens the form "Edit shipment #N" in place of the shipment. It has the same fields as the Add form. Each item box goes from 0 to what this shipment already holds plus what is still unshipped on the order, and shows "current of maximum". Click Update to save or Cancel to close the form.

  • The provider list preselects the stored provider. When the stored link matches no provider in the list (for example a custom link), Other… is preselected and the link is shown in the box.
  • Unlike the Add form, an edit does not insist on a tracking number.
  • Setting every item to 0 is refused: "A shipment needs at least one item. Delete the shipment instead." If none of the items you entered has anything left, you see "None of those items has any quantity left to ship."
  • The shipment date field carries only a day. Saving the same day again keeps the time of day the shipment already had.
  • On success: "Shipment updated successfully."
  • Which edits email the customer is explained under Customer emails.

Delete asks "Delete this shipment? This cannot be undone." and then removes the shipment and its item rows ("Shipment deleted successfully."). The order status is recalculated. The webhook, if configured, receives a deleted event.

Shipment statuses

Every shipment has one of four statuses. The names differ slightly between what you see and what the customer sees.

You seeCustomer seesStored valueNotes
ReadyOrdered (step 1 of the timeline)readyThe default for a new shipment. Shipments with no stored status, such as those recorded by the free plugin, are shown as Ready.
PickedPicked (step 2)pickedWith the email trigger set to "When shipment is marked as Picked", the first time a shipment reaches this status sends the New Partial Shipment email.
DispatchedOut for delivery (step 3)dispatchedNever sends an email by itself.
DeliveredDelivered (step 4)deliveredThe first time a shipment is marked Delivered through a Mark button, an edit, the REST endpoint or an import, its delivery date is recorded in delivered_date and shown to the customer as "Delivered" with that date. The date is kept if the status is changed back.

To change a status in one click, use Mark Picked, Mark Dispatched or Mark Delivered in the shipment. The status the shipment already has is shown as a plain label instead of a button. There is no Mark Ready button; to move a shipment back to Ready use Edit and change Status. The Mark buttons report "Shipment status updated." or "Invalid shipment or status." They change only the status and its delivery date. They do not change the order status, because no quantity changes.

A shipment that was added with the status Delivered selected in the form, or created by the one-time background run, has no delivered_date. The customer then sees its shipment date as the delivery date.

Tracking numbers, providers and tracking links

A shipment stores two things: the tracking number, and a tracking URL template. Choosing a provider stores that provider's URL template. The provider's name is not stored separately. Wherever the name is shown (the box, emails, the customer page, the REST read response, webhooks), the plugin finds it by comparing the stored URL with its provider lists, first for the order's country and then for every country and your custom providers. If you later change or delete a custom provider, older shipments that used it keep their link but lose the name: they show the tracking number with its link, without a provider line.

A tracking link is the template with %1$s (or %s) replaced by the tracking number, URL-encoded. A template without a placeholder is used as it is. A template with a placeholder but an empty tracking number gives no link.

Built-in providers

The built-in directory has 58 providers for 20 countries. The list offered on an order is the one for the order's shipping country, or its billing country when there is no shipping country. Orders for any other country get only your custom providers.

CountryProviders
Australia (AU)Australia Post; Fastway Couriers
Austria (AT)post.at; dhl.at; DPD.at
Belgium (BE)bpost
Brazil (BR)Correios
Canada (CA)Canada Post; Purolator
Czechia (CZ)PPL.cz; Česká pošta; DHL.cz; DPD.cz
Finland (FI)Itella
France (FR)Colissimo
Germany (DE)DHL Intraship (DE); Hermes; Deutsche Post DHL; UPS Germany; DPD.de
India (IN)DTDC
Ireland (IE)DPD.ie; An Post
Italy (IT)BRT (Bartolini); DHL Express
Netherlands (NL)DPD.NL; UPS Netherlands
New Zealand (NZ)Courier Post; NZ Post; Aramex; PBT Couriers
Poland (PL)InPost; DPD.PL; Poczta Polska
Romania (RO)Fan Courier; DPD Romania; Urgent Cargus
South Africa (ZA)SAPO; Fastway
Sweden (SE)PostNord Sverige AB; DHL.se; Bring.se; UPS.se; DB Schenker
United Kingdom (GB)DHL; DPD.co.uk; InterLink; ParcelForce; Royal Mail; TNT Express (consignment); TNT Express (reference); DHL Parcel UK
United States (US)Fedex; FedEx Sameday; OnTrac; UPS; USPS; DHL US

The tracking addresses in this list are fixed in the plugin. Carriers change their tracking pages from time to time; if one stops working, add a corrected provider with the same name under Custom Providers. A custom provider with the same name as a built-in one replaces it. Developers can change the whole list with the wphub_shipment_tracking_providers filter.

Your own providers

Under WooCommerce → Settings → Partial Shipment → Shipping Providers, type one provider per line as Provider Name|Tracking URL, for example My Courier|https://example.com/track/%1$s. Custom providers appear on every order, whatever the country. When you save, a line without a name, without the pipe or without an address starting with http:// or https:// is dropped and a notice says how many lines were ignored.

Quantities, refunds and virtual items

  • Net quantity. For each order line, the quantity that can ship is the ordered quantity minus the refunded quantity. What is still available is that number minus what other shipments of the order already hold.
  • Virtual items. A line whose product is virtual is never shipped, never counted in the progress line, in the order status calculation or in the Fulfillment Report, and never shown on the customer's shipment cards. A line whose product was deleted after the order was placed still counts as a physical item.
  • Over-shipping is prevented. Creating or editing a shipment first takes a lock for the order. Two people (or an import and a person) shipping the same order at the same moment can neither ship more than was ordered nor receive the same shipment number.
  • Refunds after shipping. After a refund the shipped total is capped at the net quantity. When a refund removes the units that were still waiting to ship, the plugin re-checks the order and, with the defaults, completes it.

Order status automation

With the plugin active, the order status follows the shipments. The plugin recalculates after every shipment is added, edited or deleted, after the bulk action and the backfill, and after a refund on an order that already has a shipment. It does not recalculate after a Mark button, after the daily data retention clean-up, or after a refund on an order with no shipments.

SituationWhat happens
The order is Refunded, Cancelled, Failed, a checkout draft, Draft or in the trashNothing, ever. Developers can change this list with wphub_shipment_status_skip_statuses.
The order has no physical quantity left (everything virtual or fully refunded)Nothing.
Part of the net quantity has shippedThe order becomes Partially Shipped, from any status that is not in the list above, but only while Add Status "Partially Shipped" is on (the status must exist).
All of the net quantity has shipped and Mark auto "completed" is onThe order becomes Completed.
All has shipped, Mark auto "completed" is off, and the order is Partially ShippedThe order goes back to Processing, so you can complete it yourself.
Nothing is shipped (for example you deleted the last shipment) and the order is Partially Shipped or ProcessingA Partially Shipped order goes back to Processing. A Processing order stays. Completed, On hold and Pending payment orders are never moved back.

Each change adds an order note that starts with "Order Partially Shipped by advance partial shipment.", "Order marked auto Completed by advance partial shipment." or "Order Processing by advance partial shipment.", followed by WooCommerce's usual "Order status changed from ... to ...". Because the plugin only moves an order to a status that exists, switching Add Status "Partially Shipped" off never turns orders into "Pending payment".

The automation also moves Completed orders.If you delete a shipment, or lower its quantities, on an order that is Completed and some quantity stays shipped, the order becomes Partially Shipped. If that leaves nothing shipped at all, a Completed order stays Completed. Orders in Pending payment or On hold are moved too when the quantities change (new shipments are blocked on Pending payment orders, but editing or deleting existing ones is not). A fully shipped On hold order becomes Completed when automatic completion is on.

Item badges

Each physical item gets a badge that tells how much of it has shipped. Virtual items get none. You can change the four labels under Status Labels (see Settings).

Badge (default label)When it showsNumber after the label
ShippedThe shipped quantity equals the ordered quantity.The shipped quantity.
Partially ShippedSomething has shipped but less than was ordered.The shipped quantity.
Not ShippedNothing has shipped.The quantity still to ship (ordered minus refunded).
RefundedThe refunded quantity covers the whole ordered quantity.None.

Badges compare the shipped quantity with the quantity ordered. They do not subtract a partial refund, so an item with 3 ordered, 1 refunded and 2 shipped shows "Partially Shipped: 2" even though nothing more is owed. The order status calculation does use the net quantity.

  • On the order screen a Shipment column is added to WooCommerce's order items table, with the badge ("Shipped: 2") on every product line.
  • In the order preview popup on the Orders list, a Status column shows a coloured badge with the shipped quantity (the label is in its tooltip). This is controlled by Display status in order popup.
  • On the Orders list a Shipment column follows Status. It shows one badge for the whole order (Not Shipped, Partially Shipped, Shipped or Refunded) calculated from the sum of the physical quantities, or a dash when the order has no physical items.
  • For customers the badges appear next to each item on their order page, only after the order has at least one shipment. See What customers see.

Bulk action: Create shipment for all items

On the Orders list, tick orders, open Bulk actions, choose Create shipment for all items and click Apply. For each selected order that is not Pending payment, Cancelled, Refunded or Failed and still has something to ship, the plugin creates one shipment holding every remaining physical item. A notice then says "1 shipment created." or "N shipments created.".

These shipments have no tracking number and no provider, and they are not silent.The status is Ready. With the email trigger on "Immediately", every customer in the batch receives a New Partial Shipment email, and the webhook, if set, receives a created event for each. Set the trigger to "When shipment is marked as Picked" first if you do not want that. Orders with nothing left to ship are skipped without a message.

Mark existing orders as shipped

This tool creates a Delivered shipment for every unshipped physical item on orders with the statuses you choose. It is meant for orders that were shipped before you installed the plugin. It is silent: no customer email and no webhook. It does run the order status calculation, so an order in a status you selected can be moved (for example Processing to Completed when automatic completion is on, which makes WooCommerce send its usual email).

  • Automatic run (on by default). On the first wp-admin page load after activation, the plugin schedules one background run for orders created before the activation time, using the selected statuses (Completed unless you choose others). A site that upgrades from an older Advance version, which has no recorded activation time, treats the time of the first admin page load after the upgrade as the activation time. The run finishes once and is not repeated, unless you change Automatic run or Order statuses and save, which arms it again. The first time you save this screen counts as a change, because the statuses list is stored then for the first time. It is safe to repeat: it only covers quantities that no shipment holds yet.
  • Run now. Mark orders as shipped now starts a run for orders of any date, using the statuses currently selected in the box above it, even if you have not saved them. If a run is already in progress you see "A backfill is already running. It will continue in the background."
  • How it runs. Through WooCommerce's Action Scheduler (group wphub-partial-shipment, hook wphub_partial_shipment_backfill_worker), 25 orders per batch with a 30-second pause between batches. Progress is shown under the button: "Running in the background — N order(s) processed so far." and later "Done. Marked N order(s) shipped and created N shipment(s)." You can watch the queue under Tools → Scheduled Actions.
  • It adds, it does not duplicate. Only the remaining quantity of each item is shipped. Orders that are fully shipped get nothing.
Choose statuses carefully.The selector lists every order status, including Pending payment. The tool does not apply the "no shipments on Pending, Cancelled, Refunded or Failed orders" rule. Select only statuses of orders that really did ship.

Customer emails

Advance adds two customer emails to WooCommerce. Both go to the order's billing email address, are enabled by default, and can be edited, disabled or switched between HTML, plain text and multipart under WooCommerce → Settings → Emails. The settings screen shows each email's state with a Manage email button.

EmailDefault subjectDefault headingPurpose
New Partial Shipment (wphub_partial_shipment)"Your {site_title} order is shipped partially!", or "Your {site_title} order is completed!" when the order is Completed at the moment the email is built"Your order is partially shipped." or "Your order is completed."Tells the customer a parcel is on its way.
Partial Shipment Update (wphub_partial_shipment_update)"Your {site_title} partially shipped order is updated!""Your partially shipped order is updated"Tells the customer a parcel was changed.

What is in the email

A greeting with the billing first name, a sentence such as "Just to let you know — we've partially shipped your order #123, and it is now being processed:" (or "we've shipped your order" when the order is Completed; the update email says "we've made some modification in your partially shipped order"), a heading with the order number and date, a table of the shipment's items (product name, the SKU in brackets when there is one, and the quantity), a table with the provider, the tracking number and the tracking link, the customer note when there is one, and a "Track your shipment" block with a "View live tracking →" link and a QR code of the tracking link. When no tracking link can be built the block links to the customer's order page ("View your order →") instead. WooCommerce's usual order-meta and customer-details blocks and the email's "Additional content" follow.

The plain-text version has the same shipment information as text (the tracking link on a "Track your shipment:" line) and no QR code. It also lists the order's totals (the rows WooCommerce builds for an order, such as subtotal, shipping, payment method and total) and the customer's order note. The QR code in the HTML email is an image loaded by the customer's email program from https://api.qrserver.com, a third-party service, with the tracking link in the address. The wphub_shipment_email_qr_url filter changes the image address; return an empty string to leave the QR code out.

When an email is sent

The setting Shipment Email Trigger decides. Shipments created or changed silently never send an email. The background backfill and an import set to "Never send emails" are silent. The box, the bulk action and the REST endpoint are not.

What happensTrigger: Immediately when shipment is created (default)Trigger: When shipment is marked as Picked
A shipment is created (box, REST update or ship_all, bulk action, import)New Partial Shipment email at once.The email is sent only if the shipment is created with the status Picked. Otherwise nothing yet. The created webhook still fires.
A shipment is edited and something the customer can see changes (items or quantities, provider link, tracking number, status, shipment date, estimated delivery, customer note, delivery date)Partial Shipment Update email.No update email. If the edit moves the status to Picked and the New email was not sent before, the New email is sent once.
A shipment is edited and only the internal note changesNo email.No email.
A Mark button, or the REST status actionNo email.Mark Picked sends the New email once if it was not sent before. Dispatched and Delivered never send.

Each shipment records that its New email was triggered (email_sent), even when the email is disabled or the order has no billing address, so the Picked rule fires only once.

What customers see

On My Account → Orders → View, below the order details table, each shipment appears as a card, oldest first:

  • A title "Shipment #N" with the shipment date and time, and a status badge (Ordered, Picked, Out for delivery or Delivered).
  • "Delivered" with a date for delivered shipments (the delivery date, or the shipment date when none was recorded), or "Expected Delivery" with the estimated delivery date for the others, when one is set.
  • A four-step timeline: Ordered, Picked, Out for delivery, Delivered. Steps already passed are marked done and the current one is highlighted.
  • The provider and the tracking number as a link to the carrier. When the provider is not recognised, the tracking number and, if a link can be built, a "Tracking URL" line.
  • A table of the items in the shipment (Product, Qty), without virtual items, and the customer note when there is one.

Next to each physical item in the order's item list, once the order has at least one shipment, the customer also sees the item badge with your labels (for example "Shipped: 2"). The plugin adds this on pages where the item list is shown through WooCommerce's order details template and the page is a WordPress page, which includes the View order page, the order received page and the pay-for-order page. The front-end stylesheet loads only on My Account and order-received pages (and wherever the tracking shortcode is used). The internal note is never shown to customers. Customers can follow a parcel without logging in only through the tracking page below.

The tracking page: [wphub_shipment_tracking]

Create a page, add a Shortcode block with [wphub_shipment_tracking] and publish it. Visitors type a tracking number and see the matching shipment as the same card that appears on the order page.

  • The form. A box labelled "Track a shipment by tracking number" (hint "e.g. ZXZ123456789") and a Track button. It sends a normal form post to the same page and needs no login and no nonce, so cached pages work.
  • Matching. The number must match a stored tracking number exactly. The final match is case-sensitive, so type it exactly as in the email.
  • A number used on several orders. The visitor sees "This tracking number is used on more than one order. Please also enter your order number." and an Order number box appears. The order number (or the order ID) must match one of the orders. This stops one customer seeing another customer's order.
  • One order. When the number belongs to one order and no order number was typed, that order's matching shipment is shown.
  • Rate limit. By default 20 lookups per visitor address per 10 minutes. Over the limit the visitor sees "Too many lookups. Please wait a few minutes and try again." until 10 minutes after the last counted lookup. Developers change it with the wphub_tracking_rate_limit filter (see Filters).
  • Messages. "Please enter a tracking number.", "No shipment found for that tracking number." and "No shipments found for this order."
  • Attribute order_id. [wphub_shipment_tracking order_id="123"] shows every shipment of that order under the form when the page loads, before any lookup. The page is public, so use this only where showing that order to every visitor is intended.

The page shows items, quantities, provider, tracking number, dates and the customer note of the matching shipment. It does not show the customer's name or address.

Packing slips and delivery notes

When the free PDF Invoice for WooCommerce plugin is active, each shipment in the box has Packing Slip and Delivery Note buttons. Each opens a PDF for that shipment in a new tab (the file name is, for example, packing-slip-1234-56.pdf: the order number and the shipment's database id). Your company details, logo and footer note come from the PDF Invoice settings.

  • Packing Slip. Bill to and ship to, order number and date, a shipment information bar (shipment number, shipment date, provider and tracking number, only those that exist), a table of this shipment's items (number, item name with SKU and item options, quantity), and the order's shipping method and payment method.
  • Delivery Note. Ship to and bill to, the same shipment information bar, a table of all physical lines of the order with Ordered, Prev. Shipped (earlier shipments of the order), This Note and Remaining (net of refunds), and a box with the customer note.
  • The links need edit_others_shop_orders and a valid security token. If something is missing you see "The PDF Invoice for WooCommerce plugin is required to print packing slips and delivery notes. Please install and activate it." or "Shipment not found for this order."
  • A theme can override the two layouts (see Templates).

Fulfillment Report

Open WooCommerce → Fulfillment Report (needs manage_woocommerce; switch it off under Enable Fulfillment Report). It shows how your orders are being fulfilled in a date window.

  • Filters. Status (All statuses or one order status), From, To and Order ID, with Apply and Reset. With no dates the window is the last 30 days up to today, in your site's time zone and in whole days. A reversed range is swapped and impossible dates are ignored. All statuses leaves out Cancelled, Refunded, Failed, trashed and draft orders (a developer filter, wphub_report_excluded_statuses, changes this); you can still pick Cancelled, Refunded or Failed one at a time. Trashed and draft orders are not in the Status list.
  • Cards. Orders in scope, Complete, Partial, Not shipped, Total shipments, Backlog (unshipped qty), Avg days to first shipment, Avg days to completion, and "At risk (unshipped/partial > 7 days)" with its backlog in units.
  • Table. Order (linked, with the customer name), Created, Status, Shipments, Ordered, Shipped, Backlog, State (Complete, Partial or Not shipped), Days since order and Days to first ship, 50 orders per page.
  • How it counts. Only physical items count. Backlog is the net quantity (ordered minus refunded) minus what has shipped, never below zero. "Avg days to completion" averages (last shipment date minus order date) over orders whose status is Completed (or the custom statuses "shipped" or "delivered" if you have them) and that have shipments. Orders with nothing physical left to ship and no shipments are left out.
  • Limit. The report covers at most the 500 most recent orders of the window and says so ("The report covers the 500 most recent orders of this window. Narrow the date range or the status to see the rest.").
  • CSV. Download CSV exports the same filtered orders (up to 500) as wphub-fulfillment-YYYYMMDD-HHMMSS.csv with the columns Order, Customer, Created, Status, Shipments, Ordered, Shipped, Backlog, State, Days since order and Days to first shipment. Customer names that start with a character a spreadsheet could read as a formula (=, +, -, @, tab or carriage return) get a leading apostrophe.

Data retention

Under Data Retention you can have old shipments deleted in the background. The default is Do not delete. With 3 months, 6 months, 1 year or 2 years chosen, a daily job (wphub_partial_shipment_cleanup) deletes shipments whose shipment date is older than 90, 180, 365 or 730 days, up to 200 per run, with their item rows. The first run is about an hour after you save the setting.

It looks at the shipment date, not at when the shipment was created.A shipment you create or import with an old shipment date is deleted at the next run. Deleting does not change order statuses, so an order can keep its status while its shipments are gone and its badges go back to Not Shipped. Each deletion fires the deleted webhook. Deleted shipments cannot be restored.

REST endpoint

The endpoint lets another system read, create, change, re-stage or delete shipments. It is off by default. Turn on Enable API, open the settings screen to see the API Key, and send the key in the X-WPX-Key header (or as Authorization: Bearer KEY) to the address shown under API Endpoint, /wp-json/wxp-shipment-data/wxp-data/. Regenerate creates a new key and the old one stops working. Parameters, responses and examples are in REST endpoint (reference).

Outgoing webhooks

Enter an address under Outgoing Webhook URL and the plugin posts a signed JSON message whenever a shipment is created, updated or deleted. Click Send a test event to check your receiver; the result is shown as "Test event delivered: your server answered HTTP 200." (or the code your server returned). Delivery is not retried, and addresses on your own network (private or loopback addresses, or ports other than 80, 443 and 8080) are refused by WordPress's safe HTTP function. The payload and the signature check are in Webhook (reference).

Importing shipments with WP All Import

The separate paid add-on, Advance Partial Shipment Extension for WP All Import, imports parcels from a CSV or XML file. It calls the same functions as the box, so the quantity checks, order status automation, emails and webhooks all apply.

6. Settings

All settings are on one screen: WooCommerce → Settings → Partial Shipment. It needs manage_woocommerce. The screen starts with a header card (the plugin name and version, short links to Documentation, Support, the Fulfillment Report when it is enabled, and the licence screen, and a counter of Partially Shipped orders with a "View orders" link), followed by one card per group below. Click Save changes at the bottom to save every card at once. Checkbox settings are shown as switches.

Three of the keys below (partially_shipped_status, partially_auto_complete and partially_enable_status_popup) are shared with the free plugin and keep their values when you switch between the two.

Shipment Status

Controls how and when orders are marked as shipped.

SettingKeyDefaultWhat it does
Add Status "Partially Shipped"partially_shipped_statusOnAdds the order status "Partially Shipped" (wc-partial-shipped) to WooCommerce, including the status list and the Orders list filter. Allowed values: yes or no. When off, the automation never moves an order to it. Orders already in that status are not touched when you switch it off.
Mark auto "completed"partially_auto_completeOnWhen every physical item has shipped, set the order to Completed. When off, a fully shipped Partially Shipped order goes back to Processing instead.
Display status in order popuppartially_enable_status_popupOnAdds a Status column with the shipped quantity to the order preview popup on the Orders list.

Status Labels

Customises the labels of the item badges. A live Preview row shows the four badges as they are currently saved, with sample numbers (Shipped: 2, Partially Shipped: 1, Not Shipped: 3, and Refunded). Change the wording, save, and the preview follows. The labels are used on the order screen, the Orders list, the order preview, the customer's order page and the preview itself. They do not rename the "Partially Shipped" order status, and the shipment statuses (Ready, Picked, Dispatched, Delivered) are not editable here.

SettingKeyDefaultWhat it does
Label "Shipped"partially_shipped_customShippedText for an item that is fully shipped. Any text. The box is pre-filled with the default word until you change it, and an empty box falls back to that word.
Label "Not Shipped"partially_not_shipped_customNot ShippedText for an item with nothing shipped. The box is pre-filled with the default word.
Label "Partially Shipped"partially_shipped_label_customPartially ShippedText for an item that is partly shipped. The box is pre-filled with the default word.
Label "Refunded"partially_refunded_customRefundedText for an item that is fully refunded. The box is pre-filled with the default word.

Shipping Providers

SettingKeyDefaultWhat it does
Custom Providerswphub_custom_providersEmptyOne provider per line as Provider Name|Tracking URL. The %1$s in the address is replaced by the tracking number. Providers appear on every order. On save, lines with no name, no pipe or an address that does not start with http:// or https:// are dropped with the notice "N custom provider line(s) were ignored: each line needs a name, a pipe and a URL starting with http:// or https://." The box shows the example My Courier|https://example.com/track/%1$s as a placeholder.

Email Settings

SettingKeyDefaultWhat it does
Shipment Email Triggerwphub_shipment_email_triggerimmediatelyTwo values. immediately ("Immediately when shipment is created"): the New Partial Shipment email goes out when a shipment is created and the Update email when a customer-visible detail is edited. on_picked ("When shipment is marked as Picked"): no email on create or edit; the New email is sent once, the first time the shipment becomes Picked. Any other stored value counts as immediately. The full rules are in Customer emails.
Emails(display only)-Shows whether each of the two emails is Enabled or Disabled, with a Manage email button to its WooCommerce settings. Subject, heading, colours and plain text or HTML are set under WooCommerce → Settings → Emails.

Fulfillment Report

SettingKeyDefaultWhat it does
Enable Fulfillment Reportenable_fulfillment_reportOnShows WooCommerce → Fulfillment Report. When off the menu item and the page are not registered, the CSV export is refused and the header link disappears.

Data Retention

SettingKeyDefaultWhat it does
Delete old shipment datawphub_shipment_data_retentionno_deleteAllowed values: no_delete ("Do not delete"), 3_months (90 days), 6_months (180 days), 1_year (365 days), 2_year (730 days). Any other value counts as "Do not delete". The daily job deletes shipments whose shipment date is older than the period. See Data retention.

API & Webhooks

SettingKeyDefaultWhat it does
Enable APIenable_wxp_apiOffWhile off, every request to the REST endpoint is answered with HTTP 403 "API is disabled."
API Endpoint(display only)Your site's /wp-json/wxp-shipment-data/wxp-data/ addressA read-only box with a Copy button. The note beside it says to send the key in the X-WPX-Key header or as Authorization: Bearer {key} and to keep it out of URLs.
API Keywxp_api_keyGenerated automaticallyA 32-character key, created the first time the settings screen is displayed. The box is read-only with Copy and Regenerate buttons. Regenerate asks "Generate a new API key? Every integration that uses the current key (and every receiver that verifies webhook signatures) must be updated." and then shows a warning notice. The same key signs outgoing webhooks.
Outgoing Webhook URLwphub_webhook_urlEmpty (webhooks off)Must start with http:// or https:// and be a valid address. An invalid address keeps the previous one and shows "The outgoing webhook URL must start with http:// or https:// and be a valid address. The previous webhook URL was kept." Leave empty to switch webhooks off.
Test the webhook(button)-Send a test event posts a signed test event to the saved address and reports your server's HTTP answer. Disabled with "Save a webhook URL first." when no address is saved.

Mark existing orders as shipped

SettingKeyDefaultWhat it does
Automatic runwphub_backfill_completedOn (yes)"Mark orders created before this plugin was activated as shipped (one-time, in the background)." Saved as yes or no.
Order statuseswphub_backfill_statusesCompletedA multi-select of every order status. Orders with these statuses get a Delivered shipment for each unshipped physical item. Silent. An empty selection counts as Completed.
Run now(button)-Mark orders as shipped now starts a run for orders of any date with the statuses currently selected, saved or not. Shows the state of the current or last run. Details are in Mark existing orders as shipped.

Settings that live elsewhere

  • The two emails are configured under WooCommerce → Settings → Emails: enable or disable, subject, heading, additional content and email type.
  • Packing slip and delivery note details (company name, address, logo, footer note) come from the PDF Invoice for WooCommerce plugin's own settings.
  • Licence is managed under Plugins → WpExperts Hub Licences.

7. Screens

ScreenPathWhat is there
Order edit screenWooCommerce → Orders → (an order)The Partial Shipment box in the sidebar, and a Shipment column with a badge on every product line of the order items table.
Orders listWooCommerce → OrdersA Shipment column after Status, the bulk action Create shipment for all items, a "Partially Shipped" status filter, a notice after the bulk action, and a Status column in the order preview popup.
SettingsWooCommerce → Settings → Partial ShipmentAll settings, the API key, the webhook test and the backfill tool.
Fulfillment ReportWooCommerce → Fulfillment ReportCards, filters, a table and CSV download. Hidden when switched off in the settings.
EmailsWooCommerce → Settings → EmailsNew Partial Shipment and Partial Shipment Update.
LicencesPlugins → WpExperts Hub LicencesLicence activation, deactivation and "Email it to me" for every WpExperts Hub plugin that bundles the client.
Plugins screenPluginsLinks under the plugin name: Settings and Activate License or Deactivate License.
Customer order pageMy Account → Orders → ViewItem badges and one card per shipment with a timeline.
Tracking pageA page you createThe [wphub_shipment_tracking] lookup form.

8. Developer reference

Everything here was taken from the plugin's code (version 3.4.0). Names beginning with wxp_ and wphub_ both occur, because the plugin kept some older names for compatibility.

Shortcodes

ShortcodeAttributesOutput
[wphub_shipment_tracking]order_id (integer, default 0): when above zero and no lookup has been submitted, lists that order's shipments under the form.A tracking lookup form and, after a lookup, the matching shipment cards. Enqueues the front-end stylesheet. Described in The tracking page.

The form posts wphub_track_number and, when needed, wphub_track_order. It also prints a nonce field (_wphub_track_nonce, action wphub_tracking_lookup) that the server does not check, so that cached pages keep working.

AJAX and admin-post actions

The AJAX actions are wp_ajax_ only (logged-in users). They all need the capability edit_others_shop_orders and the nonce wphub_oes_nonce, sent in the field nonce. They answer with wp_send_json_success() or wp_send_json_error(). A success reply carries message, html (the redrawn box) and status (the order status without the wc- prefix). wphub_add_shipment and wphub_edit_shipment also return clamped (true when the quantities were reduced).

ActionPOST fieldsNotes and error messages
wphub_add_shipmentorder_id, shipment_url (URL template; __other__ counts as empty), shipment_num, qty[item_id], shipment_status, shipment_date (Y-m-d), shipment_eta, internal_note, customer_noteRequires a tracking number and at least one positive quantity ("A tracking number and at least one item quantity are required."). Also: "Invalid order.", "Shipments cannot be added to orders with this status.", "Unable to save shipment."
wphub_edit_shipmentThe same fields plus shipment_id (the row id in partial_shipment)"A shipment needs at least one item. Delete the shipment instead.", "None of those items has any quantity left to ship.", "Unable to update shipment."
wphub_delete_shipmentorder_id, shipment_id"Unable to delete shipment."
wphub_ship_metaorder_id, shipment_id, shipment_status (picked, dispatched or delivered)"Invalid shipment or status."

In the form, the address typed under Other… sits in a box named shipment_url_other. The page script copies it into shipment_url before the request is sent, so the server never needs the second field. The admin-post actions are for logged-in users too (admin-post.php?action=...).

ActionRequestNeeds
wphub_print_shipment_docGET or POST with doc (packing-slip or delivery-note; anything else counts as packing-slip), id (order id), shipment-id (row id) and _wpnonceedit_others_shop_orders, nonce action packing_slip_shipment, and the PDF Invoice plugin.
wphub_partial_shipment_backfillGET with _wpnonce and optionally wphub_backfill_status (comma-separated status keys)manage_woocommerce, nonce action wphub_partial_shipment_backfill.
wphub_regenerate_api_keyGET with _wpnoncemanage_woocommerce, nonce action wphub_regenerate_api_key.
wphub_test_webhookGET with _wpnoncemanage_woocommerce, nonce action wphub_test_webhook.

The Orders list bulk action uses the value wphub_create_shipments and redirects back with the query argument wphub_bulk_created (the number created).

REST endpoint (reference)

Route. /wp-json/wxp-shipment-data/wxp-data/ (namespace wxp-shipment-data, route wxp-data). Methods GET and POST. Parameters can be in the query string, a form body or a JSON body.

Authentication. Not a WordPress user. The request must carry the API key, and Enable API must be on. The key is looked for, in this order, in the Authorization: Bearer KEY header, the X-WPX-Key header and the key parameter (the last is kept for old integrations and is not recommended, because addresses end up in server logs). Some servers drop the Authorization header; use X-WPX-Key then.

HTTP statusBodyMeaning
403wphxp_api_disabled, "API is disabled."Enable API is off.
401wphxp_api_missing_key, "API key missing."No key sent, or no key stored yet (open the settings screen once).
401wphxp_api_invalid_key, "Invalid API key."The key does not match.
400{"error":true,"message":"Invalid order."}order-id missing or not an order.

Parameters

ParameterUsed byDescription
order-idAllRequired. The order id.
actionAllread (default), update, ship_all, status, edit or delete. An unknown value is treated as read.
shipment-idstatus, edit, deleteThe shipment's row id (the id in the read response), not its visible number.
tracking_numupdate (required), ship_all, editThe tracking number.
tracking_urlupdate, ship_all, editA tracking address or a template with %1$s. Provider names are not accepted; send the provider's address.
itemsupdate (required), editA list of objects, each with qty and either item_id (the order line item id, preferred) or sku (a physical product's SKU). Repeated lines add up.
shipment_statusupdate, ship_all, edit, statusready, picked, dispatched or delivered (the status action takes only picked, dispatched or delivered).
shipment_dateupdate, ship_all, editAny date string WooCommerce can read, for example 2026-10-06.
shipment_etaupdate, ship_all, editEstimated delivery, stored as Y-m-d.
customer_note, internal_noteupdate, ship_all, editText notes.

Actions

ActionWhat it doesSuccess replyErrors
readReturns the order's shipments. The result is cached for 120 seconds per order (transient {order_id}_wxp_partial_shipment) and the cache is cleared whenever a shipment is created, changed or deleted through the plugin.200, see the sample below.404 "No shipments found for this order."
updateCreates a shipment from items (despite the name, it never edits one).200 {"updated":true,"error":false,"id":45,"shipment_id":1}409 for a Pending, Cancelled, Refunded or Failed order (Shipments cannot be added to orders with the status "Pending payment". with the real status name). 400 "A tracking number and at least one item (sku + qty) are required." or "Nothing left to ship for the given items."
ship_allCreates one shipment with every remaining physical item. tracking_num may be empty.200 {"updated":true,"error":false,"shipment_id":2,"items_shipped":3}409 as above. 400 "No remaining items to ship for this order." 500 "Unable to create shipment."
statusSets a shipment's status.200 {"updated":true,"error":false}400 "Invalid shipment or status (use picked, dispatched or delivered)."
editChanges a shipment. A field you do not send keeps its stored value. When items is sent, the shipment's item list is replaced by it.200 {"updated":true,"error":false}400 {"updated":false,"error":true}
deleteDeletes a shipment and its items.200 {"updated":true,"error":false}400 {"updated":false,"error":true}

Creating through the endpoint is not silent: the New Partial Shipment email follows the Shipment Email Trigger setting, the created webhook fires, quantities are reduced to what is available, and the order status is recalculated.

Sample read response

Shipments are keyed by their visible number. Quantities inside items come back as text.

{
  "order-id": 123,
  "shipment": {
    "1": {
      "tracking_url": "https://www3.royalmail.com/track-your-item#/tracking-results/%1$s",
      "tracking_num": "ZXZ123456789",
      "items": { "456": { "name": "T-shirt", "sku": "TSHIRT-RED", "qty": "2" } },
      "id": 45,
      "provider": "Royal Mail",
      "tracking_link": "https://www3.royalmail.com/track-your-item#/tracking-results/ZXZ123456789",
      "status": "dispatched",
      "date": "2026-10-06",
      "eta": "2026-10-09",
      "delivered_date": "",
      "customer_note": ""
    }
  }
}

Examples

# Read
curl -H "X-WPX-Key: YOUR_KEY" "https://example.com/wp-json/wxp-shipment-data/wxp-data/?order-id=123"

# Create a shipment of two T-shirts
curl -X POST -H "X-WPX-Key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"order-id":123,"action":"update","tracking_num":"ZXZ123456789","tracking_url":"https://www3.royalmail.com/track-your-item#/tracking-results/%1$s","items":[{"sku":"TSHIRT-RED","qty":2}]}' \
  https://example.com/wp-json/wxp-shipment-data/wxp-data/

# Mark shipment 45 as delivered
curl -X POST -H "X-WPX-Key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"order-id":123,"action":"status","shipment-id":45,"shipment_status":"delivered"}' \
  https://example.com/wp-json/wxp-shipment-data/wxp-data/

Webhook (reference)

  • Events. created (a shipment was created and was not silent), updated (an edit through the plugin, or a status change through a Mark button, the REST status action or an import), deleted (any deletion, including the data retention clean-up; the message is sent before the row is removed). The background backfill is silent and sends none. Sending a test event is a separate button.
  • Request. POST to your address with Content-Type: application/json, the header X-WPHub-Event (the event name) and, when an API key exists, X-WPHub-Signature: sha256=HEX, where HEX is the HMAC-SHA256 of the raw request body using the API key as the secret.
  • Sending. Through wp_safe_remote_post() without waiting for the answer (non-blocking). There are no retries and no log. WordPress refuses private and loopback addresses and ports other than 80, 443 and 8080 (a port is also accepted when it is the site's own).
{
  "event": "created",
  "order_id": 123,
  "shipment": {
    "id": 45,
    "shipment_id": 1,
    "tracking": "ZXZ123456789",
    "tracking_url": "https://www3.royalmail.com/track-your-item#/tracking-results/%1$s",
    "date": "1791158400",
    "status": "ready",
    "eta": "2026-10-09",
    "customer_note": "",
    "provider": "Royal Mail",
    "tracking_link": "https://www3.royalmail.com/track-your-item#/tracking-results/ZXZ123456789",
    "delivered_date": ""
  },
  "items": [ { "item_id": 456, "qty": 2 } ],
  "order_total": 59.9,
  "customer_email": "customer@example.com",
  "sent_at": "2026-10-06 09:30:00"
}

date and delivered_date are the stored values (timestamp text, empty when not set). sent_at is the UTC time. The test event has order_id 0, an empty shipment and items, a site field with your home address and a sent_at time, and nothing else.

Verify a message in PHP:

$body     = file_get_contents( 'php://input' );
$expected = 'sha256=' . hash_hmac( 'sha256', $body, $api_key );
$given    = isset( $_SERVER['HTTP_X_WPHUB_SIGNATURE'] ) ? $_SERVER['HTTP_X_WPHUB_SIGNATURE'] : '';
if ( ! hash_equals( $expected, $given ) ) {
    http_response_code( 401 );
    exit;
}

Actions

ActionParametersWhen it fires
wphub_partial_shipment_before_insert$order_id, $items (accepted order item id => quantity)Right before a new shipment row is written, while the order lock is held. Since 3.4.0.
wphub_partial_shipment_created$shipment_pk (row id), $order_idAfter a shipment is created, unless the creation was silent. The webhook listens to it.
wphub_partial_shipment_updated$shipment_pk, $order_idAfter an edit that was not silent, and after every status change made with set_shipment_status().
wphub_partial_shipment_deleted$shipment_pk, $order_idJust before a shipment is removed, so listeners can still read it.
wphub_partial_shipment_status$order_idAsks the plugin to recalculate the order status (the plugin listens at priority 9). You can fire it yourself.
wphub_partial_shipment_new_email$order_id, $shipment_pkWhen the New Partial Shipment email is due. The plugin listens at priority 999 and sends the email.
wphub_partial_shipment_update_email$order_id, $shipment_pkWhen the Partial Shipment Update email is due (priority 999).
wphub_partially_shipped_order_details$order, $shipment_id, $sent_to_admin, $plain_text, $emailInside both email templates, where the shipment's items and tracking block are printed.
add_action( 'wphub_partial_shipment_created', function ( $shipment_pk, $order_id ) {
    error_log( "Shipment {$shipment_pk} created for order {$order_id}" );
}, 10, 2 );

// Re-run the status automation for an order.
do_action( 'wphub_partial_shipment_status', 123 );

Filters

FilterArgumentsWhat it changes
wc_partial_labels$labels (keys shipped, not-shipped, partially-shipped, refunded)The four item badge labels, after the settings are applied. Add it before the init action runs.
wxp_partial_shipping_settings$settingsThe settings fields array of the settings screen. A field you add stays in the card it is inserted into.
wphub_shipment_tracking_providers$list (country code => name => URL template), $orderThe built-in provider directory.
wphub_custom_shipment_providers$providers (name => URL template)The merchant's custom providers (after the settings text is read).
wphub_order_shipment_providers$providers, $orderThe providers offered on one order.
wphub_partial_shipment_disable_statuses$statuses (values like wc-pending)The order statuses on which no shipment can be added. Default: wc-pending, wc-cancelled, wc-refunded, wc-failed.
wphub_shipment_status_skip_statuses$statuses (without wc-)Order statuses the automation never changes. Default: refunded, cancelled, failed, checkout-draft, trash, draft.
wphub_shipment_complete_status$status (default completed)The status a fully shipped order gets. Also used to decide that an email says "completed". Ignored unless that status exists.
wphub_shipment_processing_status$status (default processing)The status an order returns to when nothing is shipped.
wphub_shipment_partially_order_subject, wphub_shipment_partially_order_heading$textDefault subject and heading of the New Partial Shipment email for an order that is not completed.
wphub_shipment_completed_order_subject, wphub_shipment_completed_order_heading$textThe same for a completed order.
wphub_shipment_email_qr_url$qr, $tracking_link, $order, $shipmentThe address of the QR image in the HTML email. Return an empty string to drop the QR code.
wphub_partial_shipment_webhook_payload$payload, $event, $shipment_pk, $order_idThe webhook body. When you change it, the signature is recalculated for the new body.
wphub_tracking_rate_limitarray( max, seconds ), default array( 20, 600 )The tracking page limit. A maximum or window of 0 or less switches the limit off.
wphub_report_excluded_statuses$statuses (with wc-)Statuses that "All statuses" leaves out of the Fulfillment Report. Default: wc-trash, wc-checkout-draft, wc-cancelled, wc-refunded, wc-failed.
wphub_backfill_order_query_args$args (for wc_get_orders()), $statusesThe order query used by the backfill.
wphub_backfill_status_options$options (status key => label)The statuses listed in the backfill selector.
// A custom provider on every order.
add_filter( 'wphub_custom_shipment_providers', function ( $providers ) {
    $providers['My Courier'] = 'https://example.com/track/%1$s';
    return $providers;
} );

// Raise the tracking page limit to 60 lookups per 10 minutes.
add_filter( 'wphub_tracking_rate_limit', function () {
    return array( 60, 10 * MINUTE_IN_SECONDS );
} );

// Do not allow new shipments on On hold orders either.
add_filter( 'wphub_partial_shipment_disable_statuses', function ( $statuses ) {
    $statuses['wc-on-hold'] = 'wc-on-hold';
    return $statuses;
} );

// Add a field to the webhook body (the signature follows).
add_filter( 'wphub_partial_shipment_webhook_payload', function ( $payload, $event, $shipment_pk, $order_id ) {
    $payload['site'] = home_url();
    return $payload;
}, 10, 4 );

// No QR code in the shipment email.
add_filter( 'wphub_shipment_email_qr_url', '__return_empty_string' );

Calling the plugin from PHP

The plugin's backend object is available as wphub_partial_shipment()->partial_shipment once WordPress has run init (priority 10). The add-on uses these methods. They are public methods of the plugin's backend class, not a separate API.

MethodReturnsNotes
create_shipment( $order_id, $url, $num, $items, $args = array() )array( 'id' => row id, 'shipment_id' => visible number ) or false$items is order item id => quantity, reduced to what is available. $args keys: silent (no email and no created webhook), shipment_status, shipment_date (timestamp text), shipment_eta, internal_note, customer_note. Takes the per-order lock; returns false if the lock or the quantities are not available.
update_shipment( $shipment_pk, $order_id, $url, $num, $items, $meta = array() )The row id, or 0$url and $num may be null to keep the stored values. $meta keys: shipment_status, shipment_eta, shipment_date, internal_note, customer_note, silent (no email and no updated webhook). An empty $items leaves the items alone; a non-empty one replaces them.
remove_shipment( $shipment_pk, $order_id, $recalculate_status = true )The deleted row, or nullRefuses a row that belongs to another order.
set_shipment_status( $shipment_pk, $order_id, $status )true or false$status is picked, dispatched or delivered.
get_shipment( $shipment_pk, $order_id ), get_items( $shipment_pk )A row object, or a list of item row objectsRaw database rows.
get_order_providers( $order ), get_provider_name( $url, $order ), get_tracking_link( $url, $num ), get_provider_url_by_name( $name, $order )Providers, a name, a link, a URL templateThe last one matches a provider name without regard to case and also accepts a full http(s) address.
show_button( $order ), is_shippable_item( $item ), get_item_available_qty( $item_id, $order_id, $exclude_shipment_id = 0 )Booleans and an integerThe rules behind the box.
add_action( 'init', function () {
    $backend = wphub_partial_shipment()->partial_shipment;
    $created = $backend->create_shipment(
        123,                                              // order id
        'https://example.com/track/%1$s',                 // URL template, or '' for none
        'ZXZ123456789',                                   // tracking number
        array( 456 => 2 ),                                // order item id => quantity
        array( 'shipment_status' => 'picked', 'silent' => true )
    );
}, 20 );

Templates and override paths

The plugin loads its templates with wc_get_template(). In WooCommerce 11.1.2 that looks in the active theme (and child theme) under woocommerce/ first and then directly under the theme root, and uses the plugin's own file when it finds nothing. Copy a file from the plugin's templates folder to the path below.

Plugin fileCopy toUsed for
templates/order/shipment-details.phpyourtheme/woocommerce/order/shipment-details.phpThe list of shipment cards on the customer's order page.
templates/order/single-shipment.phpyourtheme/woocommerce/order/single-shipment.phpOne shipment card (order page and tracking page).
templates/emails/partial-shipment-details.php, templates/emails/plain/partial-shipment-details.phpyourtheme/woocommerce/emails/...The New Partial Shipment email.
templates/emails/partial-shipment-details-updated.php, templates/emails/plain/partial-shipment-details-updated.phpyourtheme/woocommerce/emails/...The Partial Shipment Update email.
templates/emails/order-details.php, templates/emails/plain/order-details.phpyourtheme/woocommerce/emails/order-details.php and .../plain/order-details.phpThe items and tracking block inside both emails.
templates/packing-slip.php, templates/delivery-note.phpyourtheme/wphub-partial-shipment/packing-slip.php and delivery-note.phpThe two PDF documents.
One file name is shared with WooCommerce.The plugin's items block uses the template name emails/order-details.php, the same name WooCommerce uses for its own order table. If your theme has its own copy of WooCommerce's emails/order-details.php, WooCommerce's template lookup finds that copy first, and it replaces the plugin's items block in the shipment emails too. The same applies to emails/plain/order-details.php.

Database tables

Both tables use your table prefix and the site's character set. They are created with CREATE TABLE IF NOT EXISTS; the extra columns are added by separate upgrade steps. wphub_partial_shipment_db_version holds the schema number (currently 3).

partial_shipment (one row per shipment)

ColumnTypeMeaning
idbigint(20), auto increment, primary keyThe row id. The REST shipment-id and the AJAX shipment_id.
order_idbigint(20), indexed (not unique)The WooCommerce order.
shipment_idbigint(20)The visible shipment number within the order (highest + 1 on creation).
shipment_urlvarchar(300)The tracking URL template or address.
shipment_numvarchar(100)The tracking number.
shipment_datevarchar(30)The shipment date as a timestamp (text).
shipment_statustextready, picked, dispatched or delivered. Empty on rows written by the free plugin, which is read as ready.
shipment_etatextEstimated delivery as Y-m-d, or empty.
internal_notelongtextAdmin-only note.
customer_notelongtextCustomer-facing note. Releases before 3.2.0 called this column comments; the upgrade renames it so the text is kept.
email_sentint(1), default 01 once the New Partial Shipment email has been triggered for this shipment.
delivered_datevarchar(30), default emptyThe time the shipment was first marked Delivered, as a timestamp (text).

partial_shipment_items (one row per item in a shipment)

ColumnTypeMeaning
idbigint(20), auto increment, primary keyThe row id.
shipment_idbigint(20), indexedThe partial_shipment.id it belongs to.
item_idvarchar(30), indexedThe WooCommerce order line item id.
item_qtyint(20)The quantity in this shipment.

The upgrade also removes columns that earlier versions had: shipment_primary_id from the items table (it came from the free plugin) and dispatch_date from the shipments table.

Options, transients, scheduled jobs and constants

NameKindPurpose
partially_shipped_status, partially_auto_complete, partially_enable_status_popupOptionsShipment Status settings (shared with the free plugin).
partially_shipped_custom, partially_not_shipped_custom, partially_shipped_label_custom, partially_refunded_customOptionsStatus Labels.
wphub_custom_providers, wphub_shipment_email_trigger, enable_fulfillment_report, wphub_shipment_data_retention, enable_wxp_api, wphub_webhook_urlOptionsThe other settings.
wxp_api_keyOptionThe API key and the webhook signing secret.
wphub_backfill_completed, wphub_backfill_statusesOptionsThe backfill settings.
wphub_partial_shipment_activatedOptionThe activation time used as the cut-off of the automatic backfill.
wphub_partial_shipment_backfill_done, wphub_partial_shipment_backfill_progressOptionsWhether the automatic backfill has finished (yes or no), and the state of the current or last run (run id, statuses, cut-off, counters).
wphub_partial_shipment_db_versionOptionThe schema number.
_wphub_pf_noticesOptionAdmin notices waiting to be shown (for example after "Mark orders as shipped now"). They show on the next admin page and are then removed.
_wphub-partial-shipment_licence_key, _wphub-partial-shipment_key_statusOptionsThe licence key and its status (active, inactive or absent). Written by the licence client.
{order_id}_wxp_partial_shipmentTransient, 120 secondsCached REST read response.
wphub_track_rl_{md5 of the visitor address}Transient, the rate limit windowCounts tracking page lookups per visitor address.
wphub_free_deactivated_noticeTransient, 30 secondsShows the one-time "free plugin was deactivated" notice.
wpxh_licence_check_v2Site transient, 12 hoursCached update and licence data from the licence server.
wpxh_licence_msg_{user id}Transient, 120 secondsThe result message shown after a licence action.
wphub_partial_shipment_cleanupWP-Cron event, dailyData retention clean-up. Scheduled only while a retention period is set.
wphub_partial_shipment_backfill_worker, group wphub-partial-shipmentAction Scheduler actionOne batch of the backfill (25 orders), with the run id as its argument.
WPHUB_PARTIAL_SHIP, WPHUB_PARTIAL_SHIPMENT_VERSION, WPHUB_PARTIAL_SHIPMENT_DB_SCHEMAConstantsThe plugin folder path, the version (3.4.0) and the schema number (3). Each is defined only if it is not already defined.
WPXH_LICENCE_SERVERConstant (optional)Overrides the licence server address in the licence client. The wpxh_licence_server filter does the same, and wpxh_licence_sslverify controls certificate checking.

The backend class also holds fixed limits as class constants: backfill batch 25 orders, report cap 500 orders, report window 30 days, "at risk" threshold 7 days, 50 report rows per page and 200 shipments per clean-up run.

The plugin sets no cookies and stores no post, user or term meta of its own. It adds no capabilities or roles.

WordPress and WooCommerce hooks the plugin attaches to

Only those that matter if you debug or override behaviour:

HookPriorityWhat the plugin does
woocommerce_email_classes999Adds the two email classes (done at plugin load so they exist before WooCommerce builds its email list on init priority 0). A plugin hooked later that removes them wins.
add_meta_boxes30Adds the Partial Shipment box to the order screens.
get_user_option_meta-box-order_shop_order and ..._woocommerce_page_wc-orders10Overrides the saved meta box order of each user, in memory, so the box always sits right after woocommerce-order-actions. The saved preference itself is not changed.
woocommerce_order_item_meta_end999Prints the item badge for customers (front end, pages only).
woocommerce_order_details_after_order_table9Prints the shipment cards on the customer's order page.
woocommerce_order_refunded20Recalculates the order status for orders that have shipments.
woocommerce_order_formatted_billing_address, woocommerce_order_formatted_shipping_address999During a packing slip or delivery note request only, blanks first name, last name and company in the formatted address, because the document prints the name separately. It returns the changed array, so other plugins' changes to those three keys are overwritten for that request.
wc_order_statuses10Adds "Partially Shipped" when the setting is on.
init5, 10, 999Schema check (5), plugin set-up and the retention schedule (10), registering the order status and loading the text domain (999).
admin_init5, 10CSV export before output (5); schema check, automatic backfill and the free-plugin guard (10).
woocommerce_admin_order_item_headers, woocommerce_admin_order_item_values10The Shipment column in the order items table.
woocommerce_admin_order_preview_line_item_columns10The Status column in the order preview popup.
woocommerce_shop_order_list_table_columns, manage_edit-shop_order_columns10The Shipment column on the Orders list (both storage modes).
bulk_actions-woocommerce_page_wc-orders, bulk_actions-edit-shop_order and the matching handle_bulk_actions-...10The bulk action.
before_woocommerce_init10Declares compatibility with HPOS, the Cart and Checkout blocks and the product block editor.

File layout

  • wphub-partial-shipment.php: plugin header, loader, activation, schema check, free-plugin guard, customer item badges.
  • classes/class-wphub-partial-shipment-backend.php: shipment logic, statuses, report, REST endpoint, backfill, providers, tracking shortcode.
  • classes/class-wphub-partial-shipment-settings.php: the settings tab. class-wphub-partial-shipment-sql.php: tables and upgrade. class-wphub-partial-shipment-webhook.php: webhooks. class-wphub-partial-shipment-email.php and ...-update-email.php: the two emails.
  • includes/order-shipment-meta.php: the Partial Shipment box.
  • templates/: customer cards, email templates, packing slip and delivery note.
  • assets/: admin.js and admin-settings.js, the admin and front-end stylesheets and the report stylesheet. languages/wphub-partial-shipment.pot: the translation template (text domain wphub-partial-shipment).
  • licence/class-wpxh-licence-client.php: the bundled licence and update client.

The classes are found by an autoloader that maps a class name to a file in classes/ (lower case, underscores to hyphens, prefixed with class-). The plugin's own files, the free plugin's guard and the add-on all expect the plugin folder to be named wphub-partial-shipment.

9. Privacy

What is stored and where

  • Shipment tables. partial_shipment and partial_shipment_items in your own database hold, per shipment: the order id, item ids and quantities, the tracking number, the tracking address, the shipment, estimated delivery and delivery dates, the status, whether the email was triggered, and the customer note and internal note. The tables hold no customer name, email address or postal address; those stay in the WooCommerce order. The notes are free text that your staff type, so they can contain personal data.
  • Options. The settings, the API key (a secret that also signs webhooks), the webhook address, the state of the backfill, queued admin notices and, once activated, the licence key. They are listed in Options, transients, scheduled jobs and constants.
  • Who sees what. A customer sees the shipments of their own orders on their account pages and in the emails sent to the billing address. Anyone who has a tracking number (and, when the number is used on several orders, the order number) can see the items, quantities, provider, tracking number, dates and customer note of that shipment on your tracking page. The internal note is shown only in wp-admin.

Cookies

The plugin sets no cookies. The tracking page limits lookups by keeping a short-lived record (a transient named wphub_track_rl_ followed by an MD5 hash of the visitor's IP address) that counts lookups. It lasts for the rate limit window, 10 minutes by default, and each counted lookup restarts the window. The address itself is not stored.

Data sent to other servers

ToWhenWhat is sent
https://wpexpertshub.com/wp-json/wphub-licence/v1/activate and /deactivateWhen you click Activate licence or Deactivate licence.The plugin slug (wphub-partial-shipment), the licence key, and your site address (site_url()).
.../send-keyWhen you use Send licence key.The plugin slug and the email address you typed.
.../checkWhen WordPress builds its plugin update list (its regular update check, or Check again on the Updates screen) or someone opens the plugin's "View details" popup, and the cached answer is missing, older than 12 hours (one hour after a failed request) or no longer matches the keys and versions installed.Your site address and, for every plugin on the site that bundles the WpExperts Hub licence client, its slug, its stored licence key (empty when none) and its installed version. One request covers all of them.
The address you enter as Outgoing Webhook URLOn every shipment created, updated or deleted, and when you click Send a test event. Never before you set an address.The order id, the shipment (number, tracking number and address, provider name, tracking link, status, dates, customer note), the item ids and quantities, the order total, the customer's billing email address and the time. See Webhook (reference).
https://api.qrserver.comWhen a customer opens the HTML version of a shipment email that has a tracking link. The customer's email program loads the image, not your server.The tracking link, which contains the tracking number, in the image address, and the usual details of any image request (the recipient's IP address). Remove it with the wphub_shipment_email_qr_url filter.

The requests to wpexpertshub.com also carry the standard headers WordPress adds to every HTTP request, including a User-Agent of the form WordPress/7.1.2; https://your-site (WordPress 7.1.2 shown), and are sent over HTTPS with certificate checking on. No order, customer, shipment or visitor data goes to wpexpertshub.com. The plugin sends nothing for analytics and loads no external scripts or fonts. Tracking links in emails and on the order page lead to the carrier's own website.

Retention, deactivation and deletion

  • Retention. Shipments stay until you delete them or switch on Delete old shipment data, which deletes by shipment date (see Data retention). The default keeps everything.
  • Deactivation removes the daily clean-up event and the pending backfill actions. It deletes no data.
  • Deleting the plugin removes the plugin files only. There is no uninstall routine, so the two tables, the options, and the licence options stay in the database. Remove them yourself if you want them gone, after a backup.
  • Personal data tools. The plugin registers no exporter and no eraser, and no suggested privacy policy text. The shipment tables are therefore not part of WordPress's personal data export and erase tools. If your staff write personal data in notes, delete or edit those shipments yourself when a request comes in.

For your own privacy policy: tracking numbers and links can reveal that a parcel is on its way to a customer, the shipment emails can load a QR image from api.qrserver.com unless you remove it, and a webhook, if you use one, passes the customer's email address and order total to the address you chose.

10. Troubleshooting

ProblemLikely cause and fix
The Partial Shipment box is missing from the order screen.WooCommerce must be active (on a single site the plugin loads nothing otherwise). The box content needs edit_others_shop_orders; a user without it sees an empty box. Open Screen Options at the top of the order screen and make sure the box is ticked. On a new order that has not been saved the box asks you to save first.
"Shipments cannot be added while the order is "Pending payment"." (or Cancelled, Refunded, Failed)By design, no shipment can be added on those statuses. Change the order status first, or change the list with the wphub_partial_shipment_disable_statuses filter. Existing shipments can still be edited and deleted.
"Enter a tracking number to save the shipment." or "A tracking number and at least one item quantity are required."The Add form needs a tracking number and at least one item above 0. The provider is optional ("N/A (no provider)").
The message ends with "(quantities reduced to what is available)".Somebody shipped part of the same items first, or a refund lowered the net quantity. Quantities are always cut down to what is still unshipped. Reload the order to see the current numbers.
"Unable to save shipment." or "Unable to update shipment."Nothing could be saved: either nothing is left to ship for the items, another request held the order's lock for more than 15 seconds, or the database refused the write (check your PHP and database error logs).
The customer did not get the shipment email.Check, in this order: the email is enabled under WooCommerce → Settings → Emails; the order has a billing email address; the Shipment Email Trigger (with "When shipment is marked as Picked" nothing is sent at creation unless the status is Picked); the shipment was not created silently (backfill, or an import set to "Never send emails"); a one-click Mark button never sends an email (except Mark Picked in the Picked mode); an edit that changes only the internal note sends nothing; then check your site's outgoing mail and the spam folder.
Every customer got an email with no tracking number after I used the bulk action.The bulk action creates shipments without a tracking number and without silent mode. Set the trigger to "When shipment is marked as Picked" before using it, or edit those shipments afterwards.
Packing Slip and Delivery Note buttons are missing, or the print link says "The PDF Invoice for WooCommerce plugin is required...".Install and activate PDF Invoice for WooCommerce (the plugin checks that its functions and classes exist). The links also need edit_others_shop_orders and open a PDF in a new tab, so allow pop-ups for the site.
A shipment shows a tracking number but no provider name, or the tracking link does not work.The provider is found by comparing the stored link with the provider lists. If you changed or removed that provider (or used "Other…"), the name is gone but the number remains. A link without %1$s is used as it is, so the number is not added. Edit the shipment and choose the provider again.
The Custom Providers box dropped lines when I saved.Each line needs a name, a pipe and an address starting with http:// or https://, for example My Courier|https://example.com/track/%1$s. The notice says how many lines were ignored.
The order stays "Partially Shipped" although everything has shipped.Either Mark auto "completed" is off (then it returns to Processing and you complete it yourself), or some physical quantity is still unshipped. Remember that refunded units are not counted, virtual items are ignored, and that a line with a deleted product still counts as physical.
A Completed order changed to "Partially Shipped".A shipment of that order was deleted or lowered. The automation moves any order that is not Refunded, Cancelled, Failed, Draft, trashed or a checkout draft. Add the status to wphub_shipment_status_skip_statuses if you do not want that.
Old orders suddenly have Delivered shipments.The one-time automatic run (Automatic run, on by default) marked unshipped items on Completed orders from before the activation as Delivered, silently. To avoid it on the next site, create the option wphub_backfill_completed with the value no before you activate the plugin. Shipments it made can be deleted from each order.
"A backfill is already running." and it never finishes.The run state is stored in wphub_partial_shipment_backfill_progress and there is no timeout. If you deactivated the plugin during a run, or Action Scheduler is stuck, check Tools → Scheduled Actions (group wphub-partial-shipment). To start over, delete that option and try again.
Shipments disappeared.Check Delete old shipment data under Data Retention. It deletes by shipment date, including shipments you just created with an old date. Restore from a backup.
The Fulfillment Report is missing, or shows fewer orders than expected.It needs Enable Fulfillment Report and manage_woocommerce. The default window is the last 30 days. "All statuses" leaves out Cancelled, Refunded, Failed, trashed and draft orders. At most 500 orders are covered, and the page says so when it hits the cap.
REST requests answer 403 "API is disabled." or 401 "API key missing." / "Invalid API key."Turn on Enable API. The key exists only after the settings screen has been shown once. Send it as X-WPX-Key (some servers remove the Authorization header). After Regenerate the old key stops working.
REST answers 409 "Shipments cannot be added to orders with the status ...".The order is Pending payment, Cancelled, Refunded or Failed. The same rule as on the order screen.
The webhook receiver gets nothing.Use Send a test event and read the message. The address must be public (WordPress refuses private and loopback addresses, and ports other than 80, 443 and 8080). Delivery is not retried and the plugin keeps no log. Check your receiver's logs and firewall.
The tracking page says "Too many lookups. Please wait a few minutes and try again."The visitor address hit the limit (20 per 10 minutes by default). If your site is behind a proxy that hides visitor addresses, many visitors can share one address and share the limit. Raise it with the wphub_tracking_rate_limit filter.
The tracking page says "No shipments found for this order." for a number that exists.The final match is case-sensitive. Type the tracking number exactly as stored, including capital letters and without spaces.
After switching from the free plugin, old shipments show as Ready.The free plugin stores no status. Edit those shipments, or use Mark Delivered. See How the three plugins fit together.
The free plugin keeps being deactivated.By design: Advance switches it off on the next wp-admin request when both are active. Only one of the two runs at a time.
The shipment email's item table looks different from the plugin's own layout.Your theme has a copy of WooCommerce's emails/order-details.php, which the plugin's emails also use. See Templates and override paths.
"Automatic update is unavailable for this plugin. Activate your licence to enable updates."No active licence on this site. Open Plugins → WpExperts Hub Licences and activate the key. If activation fails with "The licence server returned an unexpected response", try again later and make sure your server can reach wpexpertshub.com over HTTPS.

11. FAQ

Can I ship the same order in more than two parts?

Yes. An order can have any number of shipments. Each one takes quantities from what is still unshipped, net of refunds.

Does the plugin split my order into several orders?

No. The order stays whole. Shipments are separate records that point to the order's line items.

Which carriers can I use?

Fifty-eight built-in providers for 20 countries, any number of your own providers (Name|Tracking URL, offered on every order), or "Other…" with a tracking address for a single shipment. The provider is optional; the tracking number is required when you add a shipment in the box.

When does the customer receive the shipment email?

By default as soon as a shipment is created. If you set Shipment Email Trigger to "When shipment is marked as Picked", each shipment is emailed once, the first time it becomes Picked. The full table is under Customer emails.

Do I need the free Partial Shipment for WooCommerce plugin as well?

No. Advance replaces it, uses the same shipment data and switches it off when both are active. See How the three plugins fit together.

Does completing an order by hand mark its items as shipped?

Not in Advance. The free plugin does that; Advance does not. Add shipments, use the bulk action Create shipment for all items, or run Mark orders as shipped now for orders that have already gone out.

What about orders placed before I installed the plugin?

On activation, a one-time background run marks the unshipped items of Completed orders from before the activation as Delivered (silently). You can change the statuses or run it again at WooCommerce → Settings → Partial Shipment. See Mark existing orders as shipped.

How do I print packing slips and delivery notes?

Install and activate the free PDF Invoice for WooCommerce plugin. Each shipment in the Partial Shipment box then shows Packing Slip and Delivery Note buttons. Without that plugin the buttons are hidden.

How do I connect the REST endpoint and webhooks?

Turn on Enable API under WooCommerce → Settings → Partial Shipment and copy the API key. Send it in the X-WPX-Key header or as a Bearer token to /wp-json/wxp-shipment-data/wxp-data/ with an order-id and an action. For push messages, enter an Outgoing Webhook URL; events are signed with X-WPHub-Signature. Details are in the REST and webhook references.

How can customers track a parcel without logging in?

Publish a page with [wphub_shipment_tracking]. A customer types the tracking number (and the order number when the number is used on more than one order) and sees the shipment card.

Can two people ship the same order at the same time?

Yes, safely. Creating and editing shipments is processed one at a time per order, so quantities are never over-shipped and shipment numbers are never duplicated.

Does the Fulfillment Report include today's orders?

Yes. The date range covers whole days in your site's time zone. The report covers at most 500 orders and says so when it is capped.

Is there a hook that runs before a shipment is saved?

Yes: the wphub_partial_shipment_before_insert action, with the order id and the accepted quantities.

Can I import shipments from a file?

Yes, with the separate paid add-on Advance Partial Shipment Extension for WP All Import. See its documentation.

Does the plugin work without a licence?

Yes. Every feature works as soon as the plugin is active. The licence key only unlocks update packages through the normal WordPress updates screen.

How do I activate my licence and get updates?

Open Plugins → WpExperts Hub Licences, paste the key from your purchase email (also shown under My Account → Downloads) and click Activate licence. New versions then appear under Dashboard → Updates. The readme says one key covers the number of sites on your plan; the limit is applied by the licence server, not by the plugin. Deactivate the licence on this screen before you move the plugin to another live site. If you lost the key, use Can't find your key? Email it to me on the same screen.

Does the plugin contact any outside server?

Only for the licence and updates (wpexpertshub.com), for webhooks you set up yourself, and, in the HTML emails, for the QR image that the customer's email program loads from api.qrserver.com. The table under Data sent to other servers lists exactly what is sent and when.

What happens if I delete a shipment by mistake?

It cannot be restored. The order status is recalculated and a deleted webhook is sent. Restore from a backup if you need it back.

Is the plugin translation ready?

Yes. The text domain is wphub-partial-shipment and the plugin ships a template file, languages/wphub-partial-shipment.pot. It ships no translation files itself.

12. Changelog

Reproduced from the plugin's readme.txt. The 3.0.0 entry mentions bulk printing of packing slips from the Orders list; version 3.4.0 has no such bulk action (its only bulk action is Create shipment for all items; packing slips are printed per shipment). The 3.2.0 entry mentions a "shipment edit page"; the code has the Edit form inside the order's Partial Shipment box and no separate page.

3.4.0 - 2026-10-06

  • Fix - Two admins (or an import and an admin) shipping the same order at the same moment could ship more than was ordered or get the same shipment number: creating and editing a shipment is now serialised per order.
  • Fix - Fulfillment Report: orders placed on the last day of the date range - today, in the default view - were missing from the report and its CSV export. The range now covers whole days in the site's time zone; reversed or invalid dates are handled.
  • Fix - Saving ANY change on the Settings screen re-armed the one-time background backfill, which then marked old completed orders as shipped again. It is re-armed only when the backfill options themselves change.
  • Fix - A negative quantity (for example -2) shipped that many units; a non-numeric "qty" value caused a fatal error (HTTP 500); an item that belongs to another order, or a virtual item, could be shipped through the AJAX request.
  • Fix - Editing a shipment with every quantity set to 0 reported "updated" while changing nothing; it now asks you to delete the shipment instead.
  • Fix - Editing a shipment reset its time of day to midnight (shipment date) and, with the Fulfillment Report, skewed "days to first shipment".
  • Fix - Lines whose product was deleted after the order was placed could not be shipped from the order box, bulk action or backfill, but still counted for the order status: such orders stayed "Partially Shipped" forever. They are shippable now.
  • Fix - REST API: an "edit" request without tracking_num / tracking_url erased the stored tracking details; new shipments through the API (update / ship_all) are refused for Pending, Cancelled, Refunded and Failed orders, like on the order screen (HTTP 409).
  • Fix - With "Mark auto completed" switched off, a fully shipped order stayed "Partially Shipped"; it returns to Processing so you can complete it yourself.
  • Fix - "When shipment is marked as Picked": a shipment created already Picked, or set to Picked in the edit form or through the API, never emailed the customer. It now does, once. The "shipment updated" email is no longer sent for edits the customer cannot see (internal note).
  • Fix - Upgrading from versions before 3.2.0 dropped the old per-shipment comments; they are now kept as the customer note.
  • Fix - Tracking page: a lookup needs no nonce any more (cached pages carried a stale one and the form silently did nothing); a tracking number shared by several orders asks for the order number instead of showing another customer's order; lookups are rate limited.
  • New - Settings screen redesigned: sections as cards, live preview of the item labels, API endpoint / key with Copy, "Regenerate" API key, "Send a test event" for the webhook, the backfill "Run now" button uses the statuses currently selected, and a header with shortcuts.
  • New - Settings are validated: an invalid webhook URL keeps the previous one, custom provider lines that cannot work are dropped with a notice.
  • New - Packing slip and delivery note show the shipment number, date, provider and tracking number; the delivery note gains a "Remaining" column (net of refunds).
  • New - Shipment box: "Edit shipment #N" heading, item quantities with "x of N" and a "Ship remaining" shortcut in the edit form, translatable "Items to ship" title, labelled form fields and a status region for screen readers; the report scrolls sideways on phones, shows a notice when it is capped at 500 orders and has right-to-left styles.
  • New - The order screen of a brand-new (unsaved) order says to save it first; developers get the wphub_partial_shipment_before_insert action.
  • Tweak - Customer pages: right-to-left styles for the shipment cards and timeline, tracking form wraps on narrow screens.

3.3.0 - 2026-09-27

  • Security - New licence client: licence data is exchanged as JSON only (the old client unserialized server responses) and a failed server request can no longer cause a fatal error.
  • Enhancement - One "Plugins → WpExperts Hub Licences" screen manages the licences of all WpExperts Hub plugins (previously only one plugin's licence page could be opened when several were installed). Existing activations are kept.
  • Enhancement - Updates are delivered through the standard WordPress update screen for sites with an active licence; "Email me my key" added.
  • Fix – REST API: a request with any key while no API key was stored caused a fatal error (TypeError in hash_equals()), and the read endpoint raised a PHP 8 deprecation.
  • Fix – Fulfillment Report CSV export contained the whole admin page HTML before the CSV rows; it is now streamed before any output, nonce-protected and safe against spreadsheet formula injection. The status filter, pagination and CSV link were also reset to the last order's status.
  • Fix – Report backlog now ignores refunded units, "All statuses" no longer counts cancelled / refunded / failed orders as backlog, and day calculations use the site timezone.
  • Fix – Upgrading from the free plugin: its table had a UNIQUE order key, so a second shipment for the same order could not be saved. The index is migrated automatically (schema 3).
  • Fix – When the "Partially Shipped" status was disabled, orders were silently switched to "Pending payment"; the auto-complete setting also blocked the partially-shipped status. Status automation now only uses registered statuses and never touches refunded/cancelled/failed orders.
  • Fix – Refunds are taken into account after shipping: refunding the remaining unshipped units completes the order, and refunded units can no longer leave an order "over-shipped".
  • Fix – Custom tracking URLs containing "%" (e.g. %20) caused a fatal error in emails, the order box and the customer view; custom providers were missing for countries without built-in providers and for orders without a shipping address; "&" in custom provider URLs was saved as "&".
  • Fix – Emails: the plain-text version showed the admin "View order" link to customers and had no tracking details; missing order items caused fatals; refunded quantities were subtracted twice; broken nested table markup; PHP 8.2 dynamic-property deprecation; custom headings from WooCommerce → Emails are now respected.
  • Fix – A shipment could be edited through another order ID (AJAX/REST); the "N/A (no provider)" choice could not be saved; bulk "Create shipment for all items" included virtual items and pending/cancelled orders and showed no result notice.
  • Fix – Background backfill skipped orders when marking them shipped changed their status; data-retention cleanup no longer moves old orders back to Processing; background jobs are unscheduled on deactivation.
  • Fix – Packing slip / delivery note: hardened the PDF Invoice integration (no fatals when it is inactive, order/shipment validated), duplicated customer names, fatals for deleted products, bold/UTF-8 fonts (DejaVu Sans), removed the unused page-number script.
  • Fix – Customer timeline showed "ordered" in lower case; shipments saved without a stage now show "Ready".
  • Tweak – REST API: new status action, item_id matching, optional status/date/ETA/notes on create/edit, and provider / tracking link / status / dates in the read response. Webhook payload adds provider, tracking link and delivered date, plus a wphub_partial_shipment_webhook_payload filter.
  • Tweak – WooCommerce admin assets are no longer re-enqueued on every admin page; the front-end stylesheet only loads on My Account / order-received pages and the tracking shortcode; admin script strings are translatable.
  • Tweak – Schema migrations also run outside wp-admin (REST/cron). Requires PHP 7.4+ (was 8.0), tested with WordPress 7.1 and WooCommerce 11.1.

3.2.3 - 2026-09-15

  • Fix – The delivered_date column added in 3.2.1 could never actually be created: the migration wrapped its SQL type declaration (varchar(30) NOT NULL DEFAULT '') in esc_sql(), which mangled the literal '' default into invalid SQL and silently failed the ALTER TABLE on every install. As a result, marking any shipment **Delivered** since 3.2.1 has been failing the database update outright (visible as a "Mark Delivered" click that reported success while nothing was actually saved). The column now installs correctly and existing sites self-heal on the next admin page load.
  • Fix – set_shipment_status() (used by the "Mark Picked / Dispatched / Delivered" quick actions) always reported success even when the underlying database update failed. It now correctly reports failure so the admin UI shows an error instead of a false "Shipment status updated."
  • Fix – The database-migration version check now uses an internal schema-revision number instead of the plugin's marketing version, so a routine version bump can never accidentally cause a pending schema migration to be skipped (or a completed one to be silently marked as done without actually running).

3.2.2 - 2026-09-09

  • Fix – The “New Partial Shipment” and “Partial Shipment Update” emails were missing from **WooCommerce → Settings → Emails** because the email classes were registered too late (after WooCommerce had already built its email list). They are now registered during plugin bootstrap, so both emails appear in the mailer and work again without any workaround.

3.2.1 - 2026-08-11

  • New – Data Retention under **Settings → Partial Shipment**: automatically delete shipment data older than **3 months / 6 months / 1 year / 2 years** in the background (daily). Default: Do not delete.
  • New – **Delivered Date**: shipments marked **Delivered** now show their delivery date on the order view and tracking page instead of hiding the expected-delivery label. The new delivered_date column is added automatically during upgrade.
  • Fix – Fulfillment Report: the **Shipments** column (and Total shipments card) now counts distinct shipments instead of their line items, so an order with one multi-item shipment shows 1.
  • Fix – Tracking page: searching a tracking number now shows only the matching parcel (not every shipment on the order), and a PHP "Undefined array key" warning was removed.
  • Tweak – Tracking page shipment boxes now use the same layout as the order-details page (shared template: status badge, timeline, provider/tracking, items table, customer note).
  • Tweak – Shipment database migration now runs once per plugin version instead of on every admin page load.

3.2.0 - 2026-08-10

  • New – Editable **Shipment Date** on each shipment (order meta box and shipment edit page).
  • New – **Custom Shipping Providers** under **Settings → Partial Shipment → Shipping Providers**: add your own providers ("Name|Tracking URL") that appear in every provider dropdown.
  • New – Per-shipment **Comments** field on the Add/Edit shipment forms, shown on the **Delivery Note**, in the shipment emails (HTML + plain), and on the customer's order view.
  • Fix – The "Not Shipped" status in the order details now shows the quantity still to be shipped (e.g. "Not Shipped: 5") instead of "Not Shipped: 0".

3.1.1 - 2026-08-08

  • New – Optional Fulfillment Report: enable or disable the **WooCommerce → Fulfillment Report** dashboard from **Settings → Partial Shipment → Fulfillment Report**. When disabled, the menu is hidden and the report page is not registered.

3.1.0 - 2026-08-06

  • New – Configurable "Shipment Email Trigger" under **Settings → Partial Shipment → Email Settings**: send the notification email immediately when a shipment is created (default) or defer it until the shipment is first marked **Picked**. In deferred mode no email is sent on create/edit, Dispatched/Delivered never email, and each shipment is emailed at most once. Works for both partial and complete shipments.
  • Info: new per-shipment email_sent column is added automatically during upgrade (no manual steps).

3.0.1 - 2026-08-05

  • Fix – Refund-aware fulfilment: shipped/available quantities are net of refunds, so refunded items are never re-shipped and auto-status uses the net quantity. Fully-refunded items show a "Refunded" label instead of "Not Shipped: 0".
  • Fix – "Mark orders as shipped now" no longer gets blocked by a finished backfill run; saving the backfill settings re-arms the one-time auto-backfill with the newly selected statuses; and the date boundary now uses second (not day) precision so same-day pre-activation orders are no longer skipped.
  • Tweak – Marked as tested with WooCommerce 11.0.

3.0.0 - 2026-08-02

  • New – Per-shipment fulfillment status (Ready/Picked/Dispatched/Delivered) with one-click marking.
  • New – Dispatch date and estimated delivery (ETA) per shipment.
  • New – Internal & customer-facing notes per shipment.
  • New – Outgoing webhooks (created/updated/deleted) with configurable JSON endpoint.
  • New – Bulk actions on the Orders list: create shipment for all remaining items & bulk-print packing slips.
  • New – Public on-site tracking page via [wphub_shipment_tracking] shortcode.
  • New – Shipment progress timeline on the Order view page.
  • New – WooCommerce Fulfillment Report dashboard (time-to-ship, time-to-complete, backlog) + CSV export.
  • New – Tracking link + QR code added to the shipment (shipped/update) customer emails.
  • New – wchub → wphub naming cleanup across the email/notes/settings/DB.
  • Info: new per-shipment DB columns shipment_status, shipment_eta, internal_note, customer_note are added automatically during upgrade (no manual steps).

2.6.1 - 03/12/2024

  • Fix - Compatibility updates.
  • Fix - Order-edit meta box improvements (inline edit/delete, progress, ship-remaining).

2.6 - 02/04/2024

  • Fix - Minor tweaks.

2.5 - 12/03/2024

  • Fix - Status check before updating.

2.4 - 02/12/2023

  • Fix - HPOS compatibility.

2.3 - 20/07/2023

  • Fix - Shipment Provider filter updated.

2.2 - 27/06/2023

  • Tweak - Disable add shipment for specific order status.

2.1 - 06/06/2023

  • Tweak - Fixed date issue on dashboard.

2.0 - 20/03/2023

  • Tweak - Compatibility and security updates.

1.9 - 18/01/2023

  • Tweak - Code improvement.

1.8 - 22/10/2022

  • Tweak - Shipment provider list updated.

1.7 - 16/09/2022

  • Tweak - Shipment provider added using a select box.
  • Tweak - Code improvement.

1.6 - 02/09/2022

  • Tweak - Compatibility and security updates.
  • Tweak - Code improvement.

1.5 - 16/08/2022

  • Script init fixed.

1.4 - 07/08/2022

  • Providers list updated.

1.3 - 29/07/2022

  • Shipment hooks added.

1.2 - 15/07/2022

  • Shipment providers list added.

1.1 - 27/06/2022

  • Email issue fixed and example code added.

1.0 - 21/05/2022

  • Initial release.

13. Support

Email support@wpexpertshub.com. Please include:

  • Your order ID from wpexpertshub.com.
  • The plugin version (3.4.0 on this page), your WordPress and PHP versions, and your WooCommerce version.
  • What you did, what you expected, what happened, and the exact message you saw.
  • For email problems, the order id and the Shipment Email Trigger setting. For REST or webhook problems, the request you sent (without the API key) and the reply.

There is also a contact form at wpexpertshub.com/contact-us. The plugin's settings screen links to it.