Two-tier fulfillment: intent vs execution
When a sales order ships, SKU.io tracks it with two distinct objects, not one. The fulfillment order is the plan — the decision to ship some units from a particular warehouse. The sales order fulfillment (the shipment record) is the execution — what physically left the shelf, with its inventory movements and tracking. Understanding the split explains almost everything about how the Fulfillment tab behaves: why one order can have several fulfillment orders, why a shipment can be dispatched to a carrier before any tracking exists, and why voiding a shipment doesn't erase its history.
Words like fulfillment order, sales order fulfillment, allocation, pick list, and MCF are defined the first time they appear below.
The two objects at a glance
Both objects are called "fulfillment" in everyday speech, which is why they get confused. They answer different questions.
| Fulfillment order (intent) | Sales order fulfillment (execution) | |
|---|---|---|
| What it's | The routed plan: "ship these units of these lines from this warehouse." | The shipment: a record of units that actually left, 1:1 with the shipment the channel or carrier reports. |
| When it's created | At approval/routing, before anything ships — it holds the allocation so stock can't be oversold in the gap before dispatch. | At ship time — when a warehouse ships, a carrier reports a shipment, or you record a manual shipment. |
| What it carries | Target warehouse, the requested shipping method, per-line quantity budget, the provider hand-off, and merge-group membership. | Inventory movements (COGS basis), tracking numbers, fulfilled quantities, and the channel write-back. |
| How many | One sales order can have many fulfillment orders — one per warehouse it ships from. | One fulfillment order can produce one or more shipments (a carrier may split a request). |
The rule of thumb: a sales order splits into fulfillment orders by warehouse, and each fulfillment order is executed by one or more shipments. A single line is never torn apart to satisfy this — if 10 of the Stainless Water Bottle 750ml ship 6 from Main Warehouse and 4 from a second warehouse, the order gets two fulfillment orders, but the original order line and its channel link stay intact.
How the two tiers connect
Follow a shipment from the approved order down to the carrier and back to the sales channel. The fulfillment order sits in the middle; everything hangs off it.
- Approving an order routes its coverable lines into one fulfillment order per warehouse and reserves stock against each. Only Open and Reserved orders enter this pipeline; a Draft order has no fulfillment orders yet. See Approve, reserve, and allocate stock.
- Pick lists are built from fulfillment orders at a warehouse, so warehouse staff can pick the goods. They only exist once fulfillment orders exist.
- Dispatching hands the fulfillment order to a carrier or 3PL. Fulfilling (or the carrier's ship callback) then mints the shipment record.
- The shipment consumes inventory, records tracking, and writes that tracking back to the originating sales channel.
The fulfillment order: Plannable intent
A fulfillment order is the unit you plan, split, move, merge, and dispatch. It's homogeneous by warehouse — one fulfillment order means one ship-from location — so multi-warehouse fulfillment is expressed as several fulfillment orders on one sales order. You reshape them with Split, move, and merge fulfillments; the warehouse routing concept covers how lines land in each one.
A fulfillment order carries two status fields that move independently.
Fulfillment order status — is the plan still live?
| Status | What it means |
|---|---|
| Open | Live intent. It still has units to ship and can be dispatched, split, moved, or merged. |
| Closed | Terminal. Every unit of the plan has shipped, so there is nothing left to execute. |
| Cancelled | The plan was abandoned before (or instead of) shipping. Its budget and allocation are released. |
Request status — the carrier outbox
The second field tracks the conversation with the provider: unsubmitted → submitting → submitted → accepted / acknowledged, plus rejection and cancellation outcomes, and the non-carrier markers manual, imported, awaiting pickup, and picked up. This is what drives the order's own fulfillment status:
- A non-terminal fulfillment order that has been dispatched to its provider (submitting, submitted, accepted, or acknowledged) makes the sales order read Awaiting Tracking — even before any shipment record exists.
- A fulfillment order in awaiting pickup makes the order read Awaiting Pickup. For Click & Collect, no shipment record is minted until the customer collects — the awaiting-pickup state lives entirely on the fulfillment order.
Because each fulfillment order carries its own request status, a single sales order can hold a Click & Collect fulfillment order (awaiting pickup) at one warehouse and a dispatched or shipped fulfillment order at another at the same time. When both are live, the order's own fulfillment status resolves by precedence: an awaiting-pickup fulfillment order makes the whole order read Awaiting Pickup ahead of Awaiting Tracking or Partially Fulfilled, until the pickup is collected. Once every unit — pickup and shipped alike — is accounted for, the order reads Fulfilled.
Because the provider hand-off happens on the fulfillment order and the shipment record is only minted when goods actually ship, a dispatched order can sit in Awaiting Tracking with a live carrier order but zero shipment records. This is normal — the carrier's ship event creates the shipment later.
Full execution transitions in place; partial execution splits
When you execute a fulfillment order, the outcome depends on how much you ship:
- Ship the whole remaining quantity and the fulfillment order transitions in place — it records the shipment and closes.
- Ship only part and SKU.io splits the fulfillment order: a new one is carved for exactly the shipped quantity (carrying the shipment), while the original keeps the unshipped remainder as live intent. This is why a partially shipped order grows extra fulfillment orders over time.
A fulfillment order that's cancelled before execution simply releases its allocation and never produces a shipment.
The shipment: What actually left
The shipment record — one sales order fulfillment — is minted at ship time and mirrors 1:1 the shipment the channel or carrier reports. Its status describes where that one shipment stands. The full value list lives in the status reference; the lifecycle is:
| Shipment state | What it means | Typical trigger |
|---|---|---|
| Submitted | Handed to a provider, in flight. | Default for carrier/3PL shipments (ShipStation, Starshipit, and similar). |
| Acknowledged | The provider accepted the order but hasn't shipped. | Provider acknowledgement. |
| Picked / Packed | Direct-warehouse workflow intermediates. | Warehouse pick/pack steps. |
| Fulfilled | Terminal — the units shipped. Writes inventory movements, consumes FIFO layers, and consumes the fulfillment order's budget. | Default for manual and channel-reported shipments; carrier shipments reach it on the ship event. |
| Fulfilled (awaiting info) | Shipped, but tracking is still pending. | Default for Amazon FBA / MCF shipments. |
| Awaiting pickup | Staged for in-person collection. | Default for pickup shipments. |
| Canceled | Soft-voided. The row is retained for history but excluded from the order's fulfilled and submitted totals. | Voiding a shipment (see below). |
The initial state is chosen from the shipment's fulfillment type. A manual shipment (an operator recorded it) and a channel-reported shipment (the marketplace said it already shipped) both arrive Fulfilled with no carrier hand-off; a carrier shipment starts Submitted; an FBA/MCF shipment starts Fulfilled (awaiting info).
A fulfillment order's per-line budget is consumed only when a shipment reaches Fulfilled or Fulfilled (awaiting info). A merely Submitted or Awaiting pickup shipment is in flight and doesn't draw down the budget — otherwise the plan would close before anything actually shipped.
Reaching a shipped state is also the point where inventory and COGS move; how fulfilling moves inventory and realizes COGS covers the FIFO deduction in detail.
Voiding, deleting, and restoring a shipment
There are two ways to reverse a shipment, and they differ in what they leave behind. Both reverse the inventory the shipment consumed and hand its quantity back to the fulfillment order's budget for re-routing.
| Delete | Void | |
|---|---|---|
| The shipment row | Removed entirely. | Kept, marked canceled. |
| History | Gone. | Preserved, with a void reason and audit stamp. |
| Use it when | The shipment was a mistake with nothing worth keeping. | You want an auditable reversal you can undo. |
A voided shipment can be restored: SKU.io re-consumes the fulfillment order's budget and returns the shipment to the state it held before the void. If it was Fulfilled on a stock-moving warehouse, restoring re-runs the FIFO deduction — so the restore is refused up front if the order no longer has enough allocated stock to back it. The full click-path is in Void, restore, or reset a shipment.
Several guards protect this reversal:
A shipment already shipped at the carrier is return territory — a plain void is refused. You can still force a local-only void: SKU.io reverses the local copy and reopens the plan, while the already-shipped carrier order is left untouched. A manual, pickup, or channel-reported shipment is a phantom with no carrier event behind it, so it stays voidable even once fulfilled, no force needed.
A multichannel-fulfillment (MCF) parent shipment and its children, and shipments in a cross-order merge group, are refused an individual void — voiding one in isolation would desync stock. They're reversed through their own paths.
If a fulfillment order is cancelled, its in-flight shipments are voided. Should a 3PL later report that shipment as shipped anyway, SKU.io refuses to flip the voided shipment back to fulfilled — it logs the stray signal for review instead of silently producing a voided-and-shipped contradiction.
Pick lists hang off fulfillment orders
A pick list is the warehouse's pick instructions, and it always attaches through fulfillment orders — never a sales order directly. The chain is pick list → pick list line → fulfillment order line → sales order line. A pick list is built from the fulfillment orders at a single warehouse; any order line already on an open pick list is skipped so it isn't picked twice.
A pick list is assigned to a picker — it defaults to whoever created it, and if left unassigned it falls to whoever starts picking. Each pick list line also names the bin (warehouse location) to pull that SKU from, and the lines are sequenced into a walk path through the warehouse. When bins are enabled, a single fulfillment order line that draws from several bins explodes into one pick list line per bin; when the warehouse has no bins, the line carries no location and is picked from general stock.
As the picker works, each line resolves to picked, short picked, or skipped, and the picked quantity feeds the shipment. Because pick lists depend on fulfillment orders existing, an order that hasn't been approved (and so has no fulfillment orders) can't be picked yet.
Dispatching to shipping providers
Dispatching a fulfillment order hands its shipment to a carrier or 3PL — Starshipit, ShipStation, ShipHero, Trackstar, Shipfusion, Veracore, Shippit, ShipMyOrders, or an Odoo 3PL. Each provider registers its own order against the fulfillment order, and the fulfillment order is what the carrier receives. See Fulfill a sales order for the dispatch flow.
Because dispatch is deferred, no shipment record is minted when you dispatch — the provider's ship callback mints it later, carrying the tracking. Until that callback arrives, a dispatched fulfillment order shows the order as Awaiting Tracking. When the shipment does ship, its tracking rolls up to the sales order's tracking numbers and is written back to the originating channel so the marketplace order matches. SKU.io's shipment record is authoritative for the shipped state; how channel orders sync covers the write-back in full.
To keep the two views honest, SKU.io can capture provider fulfillment snapshots — a mirror of the provider's own orders and shipments — and diff them against your fulfillment orders and shipments. The reconciliation surfaces orphan provider records so you can re-link a shipment SKU.io lost track of, or import one it never had.
When provider dispatch is disabled for your tenant, the Dispatch action is replaced by a disabled indicator. You still fulfill and record shipments manually; SKU.io just doesn't hand them to a carrier.