Pick & Pack
scope: shipmentsPick & Pack shipments are customer orders where the warehouse opens cartons to pick individual product units, repacks them, and ships to a customer address. This incurs additional labor fees per unit. For shipping full cartons without opening, use SPD instead.
Lifecycle
A Pick & Pack shipment goes through these stages:
- 1Create a draft
Choose a warehouse. The shipment starts in
draftstatus. - 2Configure the shipment
Set the shipping address, add order items (product + quantity), and optionally add notes.
- 3Submit
Validates the shipping address and items are present. Creates a new shipment in
pendingstatus and deletes the draft. Use the new ID returned in the response. - 4Warehouse fulfills
The warehouse picks, packs, and ships the order. Status progresses through
processingtoforwarded. - 5Track via API
Use
GET /v0/shipments/:idto check the current status at any time.
Status Flow
Happy path
Cancellation
Inventory timing
forwarded (not on submit like SPD). For shipping full cartons without opening, use SPD.Endpoints
Shipment
/v0/shipments/pnpCreate a new Pick & Pack draft
/v0/shipments/pnp/:idDelete a draft shipment (draft only)
/v0/shipments/pnp/:id/submitSubmit shipment (draft → pending)
/v0/shipments/pnp/:id/cancelRequest cancellation (pending → pending_cancel)
Shipping Address
/v0/shipments/pnp/:id/shipping-addressGet the shipping address
/v0/shipments/pnp/:id/shipping-addressSet or update the shipping address (draft only)
Order Items
/v0/shipments/pnp/:id/itemsGet order items
/v0/shipments/pnp/:id/itemsSet order items — replaces all (draft only)
Notes
/v0/shipments/pnp/:id/notesGet shipment notes
/v0/shipments/pnp/:id/notesUpdate shipment notes (any status)
Create Draft
Creates a new shipment in draft status. You must specify which warehouse will fulfill the order.
Request Body
| Parameter | Type | Description |
|---|---|---|
warehouseId* | string | ID of the warehouse that will fulfill this shipment |
curl -X POST "https://api.3plguys.com/v0/shipments/pnp" \-H "Authorization: Bearer <token>" \-H "Content-Type: application/json" \-d '{ "warehouseId": "1" }'
const res = await fetch("https://api.3plguys.com/v0/shipments/pnp", {method: "POST",headers: {Authorization: `Bearer ${token}`,"Content-Type": "application/json",},body: JSON.stringify({ warehouseId: "1" }),});const draft = await res.json();
res = httpx.post("https://api.3plguys.com/v0/shipments/pnp",json={"warehouseId": "1"},headers={"Authorization": f"Bearer {token}"},)draft = res.json()
{"id": "15","status": "draft","type": "outbound-pickpack","warehouse": { "id": "1", "name": "Main Warehouse" },"notes": "","invoiceId": null,"workflowId": null,"createdAt": "2026-03-04T10:00:00.000Z","updatedAt": "2026-03-04T10:00:00.000Z",}
Shipping Address
The shipping address is where the order will be delivered. It can only be set or changed while the shipment is in draft status. A complete address is required before submitting.
Request Body
All fields are optional — you can send a partial update. However, name, address1, city, state, and zip must be set before submitting.
| Parameter | Type | Description |
|---|---|---|
name | string | Recipient name (required for submit) |
company | string | Company name |
address1 | string | Street address line 1 (required for submit) |
address2 | string | Street address line 2 |
city | string | City (required for submit) |
state | string | State or province code (required for submit) |
zip | string | ZIP or postal code (required for submit) |
phone | string | Phone number |
curl -X PUT "https://api.3plguys.com/v0/shipments/pnp/15/shipping-address" \-H "Authorization: Bearer <token>" \-H "Content-Type: application/json" \-d '{"name": "John Doe","company": "Acme Corp","address1": "123 Main St","city": "Los Angeles","state": "CA","zip": "90001"}'
await fetch(`https://api.3plguys.com/v0/shipments/pnp/${draftId}/shipping-address`, {method: "PUT",headers: {Authorization: `Bearer ${token}`,"Content-Type": "application/json",},body: JSON.stringify({name: "John Doe",company: "Acme Corp",address1: "123 Main St",city: "Los Angeles",state: "CA",zip: "90001",}),});
{"name": "John Doe","company": "Acme Corp","address1": "123 Main St","address2": "Suite 100","city": "Los Angeles","state": "CA","zip": "90001","phone": "555-1234"}
{"name": "John Doe","company": "Acme Corp","address1": "123 Main St","address2": "Suite 100","city": "Los Angeles","state": "CA","zip": "90001","phone": "555-1234"}
Order Items
Order items specify which products and how many units to ship. Setting items replaces all existing items. Items can only be modified while the shipment is in draft status.
Request Body
| Parameter | Type | Description |
|---|---|---|
items* | array | List of products to include in the order |
items[].productId* | string | Product ID |
items[].quantity* | number | Number of units to ship |
curl -X PUT "https://api.3plguys.com/v0/shipments/pnp/15/items" \-H "Authorization: Bearer <token>" \-H "Content-Type: application/json" \-d '{"items": [{ "productId": "1", "quantity": 50 },{ "productId": "2", "quantity": 100 }]}'
const res = await fetch(`https://api.3plguys.com/v0/shipments/pnp/${draftId}/items`, {method: "PUT",headers: {Authorization: `Bearer ${token}`,"Content-Type": "application/json",},body: JSON.stringify({items: [{ productId: "1", quantity: 50 },{ productId: "2", quantity: 100 },],}),});const items = await res.json();
{"items": [{ "productId": "1", "quantity": 50 },{ "productId": "2", "quantity": 100 }]}
[{"productId": "1","sku": "ABC123","productName": "Egg Shells","quantity": 50},{"productId": "2","sku": "DEF456","productName": "Bubble Wrap","quantity": 100}]
Notes
Free-text notes visible to the warehouse. Unlike other fields, notes can be updated at any time regardless of shipment status.
{"notes": "Handle with care — fragile items inside"}
{"notes": "Handle with care — fragile items inside"}
Submit
Submitting validates that the shipment has a complete shipping address and at least one order item. On success, a new shipment is created in pending status and the draft is deleted. Use the new shipment ID returned in the response for all subsequent operations.
{"id": "16","status": "pending","type": "outbound-pickpack","warehouse": { "id": "1", "name": "Main Warehouse" },"notes": "Handle with care — fragile items inside","invoiceId": null,"workflowId": null,"createdAt": "2026-03-04T10:05:00.000Z","updatedAt": "2026-03-04T10:05:00.000Z",}
New ID after submit
Cancel
Request cancellation of a submitted shipment. The shipment must be in pending status. This moves the status to pending_cancel. The warehouse will review the request and either cancel or continue processing.
{"id": "16","status": "pending_cancel","type": "outbound-pickpack","warehouse": { "id": "1", "name": "Main Warehouse" },"notes": "Handle with care — fragile items inside","invoiceId": null,"workflowId": null,"createdAt": "2026-03-04T10:05:00.000Z","updatedAt": "2026-03-04T10:06:00.000Z",}
Delete Draft
Permanently deletes a draft shipment. Only works while the shipment is in draft status. Returns 204 No Content on success.
204 No Content
Error Responses
400Please provide a complete shipping address before submittingReturned when submitting without name, address1, city, state, or zip set.
400Please add at least one item before submittingReturned when submitting without any order items.
400Only draft shipments can be editedReturned when trying to modify items or address on a non-draft shipment.
400Only draft shipments can be deletedReturned when trying to delete a non-draft shipment.
400Only draft shipments can be submittedReturned when trying to submit a shipment that is no longer in draft status.
400Only pending shipments can request cancellationCancellation is only available for shipments in pending status.
404Shipment not foundThe shipment ID does not exist or does not belong to your organization.
404Warehouse not foundThe warehouse ID in the create request does not exist or is archived.
404Product not found: <id>A product ID in the items list does not exist, is archived, or does not belong to your organization.
Important
- Shipping address and items can only be modified while the shipment is in
draftstatus. - Notes can be updated at any time, regardless of status.
- Submit and cancel endpoints do not require a request body.
- The warehouse opens cartons, picks individual units, and repacks them. This incurs per-unit labor fees.
- Inventory is deducted when the warehouse forwards the shipment, not on submit.
- For shipping full cartons without opening, use SPD instead.