with one click
order-fulfillment-workflow
// Streamline your warehouse with digital pick-pack-ship workflows, barcode scanning for accuracy, and automatic packing slip generation
// Streamline your warehouse with digital pick-pack-ship workflows, barcode scanning for accuracy, and automatic packing slip generation
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | order-fulfillment-workflow |
| description | Streamline your warehouse with digital pick-pack-ship workflows, barcode scanning for accuracy, and automatic packing slip generation |
| category | fulfillment-shipping |
| risk | critical |
| source | curated |
| date_added | 2026-03-12 |
| tags | ["fulfillment","pick-pack-ship","warehouse","barcode-scanning","packing-slip","wms"] |
| triggers | ["order fulfillment","pick pack ship","warehouse workflow","packing slip","barcode scanning fulfillment","warehouse management"] |
| tools | ["claude-code","cursor","gemini-cli","copilot","codex-cli","kiro","opencode"] |
| platforms | ["shopify","woocommerce","bigcommerce","custom"] |
| difficulty | intermediate |
A fulfillment workflow takes a paid order from "awaiting fulfillment" through picking, packing, and shipping — with barcode verification to prevent mis-ships and packing slip generation for each shipment. For most merchants, purpose-built apps handle this more reliably and cheaply than custom software. Custom development only makes sense for high-volume operations with unique warehouse workflows.
| Platform | Recommended Tool | Why |
|---|---|---|
| Shopify | ShipStation, Shopify Fulfillment Network (SFN), or Pirate Ship | ShipStation handles pick lists, packing slips, and multi-carrier label printing in one tool; SFN fully outsources fulfillment |
| WooCommerce | ShipStation (WooCommerce plugin), WooCommerce Shipping + Packing Slips by WooCommerce | ShipStation's WooCommerce plugin syncs orders automatically; the built-in packing slip extension handles document generation |
| BigCommerce | ShipStation, ShipBob, or Easyship | ShipStation and ShipBob both have native BigCommerce integrations; Easyship offers rate shopping across carriers |
| Custom / Headless | Build a fulfillment state machine + integrate Shippo or EasyPost for labels | Use Shippo/EasyPost for carrier-agnostic label creation; build the pick-pack-ship workflow around them |
Option A: ShipStation (recommended for 50+ orders/day)
Option B: Shopify Fulfillment Network (SFN) — fully outsourced
Option C: Shopify's built-in fulfillment (for low volume)
Using ShipStation:
WooCommerce-only (lower volume):
Using ShipStation:
Using ShipBob (outsourced fulfillment):
A good pick list groups items by warehouse location (bin/shelf) to minimize picker travel time. Most shipping apps support this.
ShipStation pick list settings:
For 3PL integration:
import Shippo from 'shippo';
const shippo = Shippo(process.env.SHIPPO_API_KEY);
// Create a shipping label for a fulfilled order
async function createShippingLabel(params: {
warehouseName: string;
warehouseAddress: Address;
customerAddress: Address;
packageWeightOz: number;
packageDimensions: { lengthIn: number; widthIn: number; heightIn: number };
preferredService?: string;
}): Promise<{ trackingNumber: string; labelUrl: string }> {
const shipment = await shippo.shipment.create({
address_from: {
name: params.warehouseName,
street1: params.warehouseAddress.street1,
city: params.warehouseAddress.city,
state: params.warehouseAddress.state,
zip: params.warehouseAddress.zip,
country: 'US',
},
address_to: {
name: params.customerAddress.name,
street1: params.customerAddress.street1,
city: params.customerAddress.city,
state: params.customerAddress.state,
zip: params.customerAddress.zip,
country: params.customerAddress.country,
email: params.customerAddress.email,
},
parcels: [{
length: params.packageDimensions.lengthIn.toString(),
width: params.packageDimensions.widthIn.toString(),
height: params.packageDimensions.heightIn.toString(),
distance_unit: 'in',
weight: params.packageWeightOz.toString(),
mass_unit: 'oz',
}],
async: false,
});
const rate = params.preferredService
? shipment.rates.find(r => r.servicelevel.token === params.preferredService)
: shipment.rates.sort((a, b) => parseFloat(a.amount) - parseFloat(b.amount))[0];
const transaction = await shippo.transaction.create({
rate: rate.object_id,
label_file_type: 'PDF',
});
return {
trackingNumber: transaction.tracking_number,
labelUrl: transaction.label_url,
};
}
| Problem | Solution |
|---|---|
| Order ships with wrong item | Enable barcode scan verification in ShipStation or your WMS before allowing label printing; do not allow manual override without manager approval |
| Tracking number not sent to customer | Ensure your shipping app is configured to automatically mark orders as fulfilled in your platform and trigger the platform's shipping confirmation email |
| 3PL receives wrong quantities in the order feed | Validate the webhook payload format against the 3PL's spec; test with a handful of orders before enabling for all |
| Fulfillment status drifts out of sync with carrier tracking | Use ShipStation's or EasyPost's tracking webhooks to update order status automatically when packages are scanned by the carrier |