Wholesale Orders Packed Outside ShipHero
This complete flow leverages our Public API to enable third-party systems to fully automate B2B fulfillment, drastically reducing manual operational time while keeping all ShipHero data perfectly accurate and in real-time sync.
When handling Wholesale Orders that are packed outside ShipHero, the Public API allows you to manage the entire flow — from creation to fulfillment — programmatically, without touching the ShipHero UI.
Below you’ll find each step in order, exactly as tested.
Warning
To use the wholesale_order_fulfill mutation, the order can’t be from SPS, there must be no valid shipping labels,
the wholesale order status must be Packing and the packing layout must be 100% empty.
Statuses and transitions
Before diving into the flow, it’s important to understand how wholesale order statuses work in ShipHero. Each wholesale order goes through a series of well-defined states —from creation and inventory reservation to final fulfillment— that reflect its progress through warehouse operations. Transitions between these states are governed by strict business rules: inventory must be allocated before picking starts, packing can only occur after picking completes, and Fulfilled marks the point of no return when inventory is deducted and stores are notified.
1. Create the Wholesale Order
First, create a wholesale order.
You must include a valid SKU that already exists in your account.
mutation {
wholesale_order_create(
data: {
partner_order_id: "WHOLESALE-1004"
shop_name: "My B2B Channel"
order_number: "OR-04"
tags: ["wholesale"]
shipping_address: {
first_name: "Customer"
last_name: "Wholesale"
address1: "123 Street"
city: "Santa Fe"
state: "SF"
zip: "3000"
country: "AR"
}
line_items: [
{
sku: "WHITE-TSHIRT-M"
quantity: 12
price: "15.00"
partner_line_item_id: "LINE-WHITE-TSHIRT-M-04"
}
]
allow_partial: false
picking_flow: DESKTOP
}
) {
request_id
wholesale_order {
id
picking_flow
order {
id
order_number
fulfillment_status
}
}
}
}In this example we’re using manual picking (picking_flow: DESKTOP).
2. Get Available Staging Locations
To see which staging bins are available, use:
query {
wholesale_staging_location_candidates(warehouse_id: "V2FyZWhvdXNlOjE1MDU2") {
request_id
data {
edges {
node {
id
name
}
}
}
}
}Example result:
{
"data": {
"wholesale_staging_location_candidates": {
"data": {
"edges": [
{ "node": { "id": "QmluOjI0MTYxMjY5", "name": "EAD_II_11" } }
]
}
}
}
}Avoid using a staging location that is already in use.
3. Assign a Staging Location
Assign one of the free locations from the list:
mutation {
wholesale_order_update_staging_location(
data: {
order_id: "T3JkZXI6Njg2MzAwMDEz" # new order id for OR-04
staging_location_id: "QmluOjI0MTYxMjY5" # EAD_II_11
}
) {
request_id
wholesale_order {
id
staging_location_id
status
order { id order_number }
}
}
}4. Allocate Inventory for Picking
Now allocate inventory for this order.
mutation {
wholesale_order_auto_allocate_for_picking(
data: {
order_id: "T3JkZXI6Njg2MzAwMDEz"
prioritized_location_ids: ["V2FyZWhvdXNlOjE1MDU2"]
}
) {
request_id
complexity
line_items {
line_item_id
quantity
product { sku }
allocations {
__typename
}
}
}
}A successful allocation will show "__typename": "AllocatedAllocationType".
5. Mark as Ready to Pick
After allocation:
mutation {
wholesale_set_as_ready_to_pick(
data: { order_id: "T3JkZXI6Njg2MzAwMDEz" }
) {
request_id
ok
}
}The order now moves from default → ready_to_pick.
6. Print the Manual Picking Sheet
Generate a PDF with manual picking instructions:
mutation {
wholesale_order_print_manual_picking_sheet(
data: { order_id: "T3JkZXI6Njg2MzAwMDEz" }
) {
request_id
picking_sheet_url
}
}Response example:
{
"data": {
"wholesale_order_print_manual_picking_sheet": {
"picking_sheet_url": "https://d2s9s6xmfnfu1v.cloudfront.net/wholesale/picking_slips/2025-10-10/picking_slip_686300013.pdf"
}
}
}This PDF can be printed and handed to warehouse staff for manual picking.
7. Transfer Picks to Staging
After picking is done, move items into staging.
mutation {
wholesale_order_transfer_picks_to_staging(
data: { order_id: "T3JkZXI6Njg2MzAwMDEz" }
) {
request_id
wholesale_order {
id
status
staging_location_id
order { id order_number }
}
}
}Status should now read packing.
8. Inspect the Staged Manifest (Optional)
Once picks are in staging, you can query the staged inventory manifest to see exactly what is sitting in the staging location for this order, broken down per line item by SKU, lot, container type (eaches vs cases), quantity, and bin. This is especially useful when your packing is driven by an external system: it tells you which lots were allocated, what’s available to pack, and gives you the IDs you need to build the wholesale_order_import_packing_layout payload in the next step.
The manifest is exposed as a staged_inventory field on each wholesale_line_item:
query {
wholesale_order(order_id: "T3JkZXI6Njg2MzAwMDEz") {
request_id
data {
id
status
wholesale_line_items {
edges {
node {
id
staged_inventory {
line_item_id
sku
quantity
case_type
lot_id
lot_name
lot_expiration_date
location_id
location_name
}
}
}
}
}
}
}Example response:
{
"data": {
"wholesale_order": {
"data": {
"wholesale_line_items": {
"edges": [
{
"node": {
"id": "V2hvbGVzYWxlTGluZUl0ZW06MTIz",
"staged_inventory": [
{
"line_item_id": "TGluZUl0ZW06OTg3Ng==",
"sku": "WHITE-TSHIRT-M",
"quantity": 12,
"case_type": null,
"lot_id": "TG90OjQzMg==",
"lot_name": "LOT-2026-04",
"lot_expiration_date": "2027-04-01T00:00:00",
"location_id": "QmluOjI0MTYxMjY5",
"location_name": "EAD_II_11"
}
]
}
}
]
}
}
}
}
}Notes on the response:
- Only items still pending packing are returned. Once a row is fully packed, it disappears from the manifest — so an empty list for a line item means everything staged has already been packed.
case_typeisnullfor loose eaches and set (for example,CASE,INNER_CASE,MASTER_CASE) when the staged unit is a product case.lot_id,lot_name, andlot_expiration_dateare only populated for lot-tracked products.line_item_idis the order line item GID. You can pass this value directly into theorder_line_item_idfield of thepacking_dataJSON in step 9 — no translation needed.
Tip
Treat the manifest as the source of truth when assembling the import payload: the SKUs, quantities, and line_item_id values it returns are the same ones the import mutation expects.
9. Import Packing Layout (Optional)
If your packing is managed by an external system and you want to reflect the full container structure (pallets, packages, case packs, and line items) in ShipHero before fulfilling, you can import the packing layout at this point.
The order must be in packing status (after step 7) and must not have an existing packing configuration.
mutation {
wholesale_order_import_packing_layout(
data: {
order_id: "T3JkZXI6Njg2MzAwMDEz"
packing_data: "{\"containers\": [ ... ]}"
}
) {
request_id
complexity
wholesale_order {
id
status
}
}
}For the full JSON schema, container types, numbering rules, and validation details, see Import Packing Layout.
Note
This step is optional. If you skip it, you can still fulfill the order using is_packed_externally: true in the next step, which does not require a packing layout.
10. Fulfill the Order (Packed Externally)
Finally, after you externally packed and labeled packages, mark the order as fulfilled:
mutation {
wholesale_order_fulfill(
data: {
order_id: "T3JkZXI6Njg2MzAwMDEz"
is_packed_externally: true
}
) {
request_id
wholesale_order {
id
status
}
}
}Expected response:
{
"data": {
"wholesale_order_fulfill": {
"wholesale_order": {
"status": "fulfilled"
}
}
}
}The order is now fully fulfilled, just like an internal ShipHero order.
11. Verify the Order Status
Check the final state:
query {
wholesale_order(order_id: "T3JkZXI6Njg2MzAwMDEz") {
request_id
data {
id
status
picking_flow
staging_location_id
order {
order_number
fulfillment_status
}
}
}
}Summary Table
| Step | Mutation | Description |
|---|---|---|
| 1 | wholesale_order_create | Create wholesale order (picking_flow: DESKTOP) |
| 2 | wholesale_staging_location_candidates | Get staging locations |
| 3 | wholesale_order_update_staging_location | Assign staging bin |
| 4 | wholesale_order_auto_allocate_for_picking | Allocate inventory |
| 5 | wholesale_set_as_ready_to_pick | Mark ready to pick |
| 6 | wholesale_order_print_manual_picking_sheet | Print picking PDF |
| 7 | wholesale_order_transfer_picks_to_staging | Move to staging |
| 8 | wholesale_order (staged_inventory) | Inspect the staged manifest (optional) |
| 9 | wholesale_order_import_packing_layout | Import packing layout (optional) |
| 10 | wholesale_order_fulfill | Fulfill packed externally |
| 11 | wholesale_order | Verify final status |