Fulfill an Order
This guide walks you through the complete process of fulfilling orders using the ShipOS API. The fulfillment process involves multiple steps to ensure data integrity and proper inventory management.
Prerequisites
- A valid API key with fulfillment permissions
- An order ID (we'll show you how to get the fulfillment order ID from this)
- A shipping label to upload OR a carrier integration setup/linked for rate shop
Understanding Order IDs vs Fulfillment Order IDs
Important: The order_id and fulfillment_order_id are different!
- Order ID: The main order identifier (e.g.,
ord_123abc...) - Fulfillment Order ID: A sub-order for fulfillment purposes (e.g.,
fo_456def...)
One order can have multiple fulfillment orders if items are fulfilled separately or split across warehouses.
Overview
The complete fulfillment process follows these steps:
- Get fulfillment orders from an order - Find the fulfillment order ID(s) from your order ID
- Acquire a lock on the fulfillment order - Prevent concurrent fulfillment
- Retrieve fulfillment order details - Get shipping and line item information
- Create one or more packages - Define what you're shipping
- Upload or generate shipping labels - Add tracking information
- Fulfill the package(s) - Complete the fulfillment
After successful fulfillment, the lock will be automatically released. If you no longer wish to fulfill this fulfillment order, we recommend releasing the lock to allow other fulfillment methods (Picking Sessions, Bulk Ship, Manual Fulfillments) to fulfill this fulfillment order. The lock will also expire automatically if not released.
Step 1: Get Fulfillment Orders
First, confirm the order exists and note its order_id:
GET /v1/shipos/orders/{order_id}{
"id": "ord_123abc...",
"status": "PENDING_FULFILLMENT",
}Then, request the fulfillment orders for that order by passing the order_id filter to the Get many fulfillment orders endpoint:
GET /v1/shipos/fulfillment-orders?order_id={order_id}{
"data": [
{
"id": "fo_456def...",
"order_id": "ord_123abc...",
"status": "IN_PROGRESS",
"request_status": "ACCEPTED"
}
],
"meta": {
"page": 0,
"page_size": 20,
"total": 1
}
}Key points:
- The Get Order response does not embed fulfillment orders; always call
GET /v1/shipos/fulfillment-orderswith anorder_idfilter to fetch them. - Fulfillment orders are returned in the
dataarray; use eachid(e.g.,fo_456def...) in the remaining steps. - An order may have multiple fulfillment orders if items are split across warehouses.
- Only fulfillment orders with status
ACCEPTEDorIN_PROGRESScan be locked.
Before proceeding: Ensure the fulfillment order request_status is ACCEPTED and the status is IN_PROGRESS.
Step 2: Acquire Lock
First, acquire an exclusive lock on the fulfillment order to prevent double fulfillment scenarios:
POST /v1/shipos/fulfillment-orders/{fulfillment_order_id}/lockRequest:
{
"lock_owner": "lock_holder",
"timeout_minutes": 30 // 30 minutes
}Response:
{
"success": true,
"lock_owner": "lock_holder",
"expires_at": "2024-01-20T10:15:00Z"
}The lock will automatically expire after the timeout period if not released manually.
Step 3: Get Fulfillment Order Details
Retrieve the complete fulfillment order details:
GET /v1/shipos/fulfillment-orders/{fulfillment_order_id}Response includes:
- Line items with quantities to fulfill
- Shipping address information
- Current fulfillment status
Step 4: Create Package
Create one or more packages for the items you're shipping:
POST /v1/shipos/packagesRequest:
{
"fulfillment_order_id": "fo_123abc...",
"name": "Box #1",
"weight": 2.5,
"weight_unit": "LB",
"length": 12,
"width": 10,
"height": 8,
"measurement_unit": "IN",
"rate_strategy": "CHEAPEST",
"carton_id": "carton_123...",
"package_line_items": [
{
"sku": "PRODUCT-001",
"quantity": 2,
"product_id": "prod_123..."
},
{
"sku": "PRODUCT-002",
"quantity": 1,
"product_id": "prod_456..."
}
]
}Response:
{
"id": "pkg_789xyz...",
"status": "PENDING",
"tracking_number": null,
// ... other package details
}Partial Fulfillment
You can create multiple packages or fulfill partial quantities:
{
"package_line_items": [
{
"sku": "PRODUCT-001",
"quantity": 1 // Only shipping 1 of 2 ordered
}
]
}Step 5: Upload or Generate Shipping Label
Upload or Generate shipping labels for packages:
POST /v1/shipos/packages/{package_id}/labelRequest:
{
"label_url": "https://your-label-storage.com/labels/label_123.pdf",
"tracking_number": "1Z999AA10123456784",
"carrier": "UPS",
"service": "GROUND",
"cost": 12.50,
"cost_currency": "USD"
}You can generate labels through ShipOS's integrated carriers or upload labels generated externally.
Step 6: Fulfill Package
Fulfill the packages, which will bill the merchant (if applicable), push tracking to the sales channel, decrement remaining quantity on line items.
POST /v1/shipos/packages/{package_id}/fulfillRequest:
{
"locked_by": "lock_holder"
}To learn more about the side effects of the fulfill operation, please visit the fulfill endpoint documentation
Next Steps
- Explore Webhook Events to receive real-time updates on fulfillment status
- Review Carrier Integrations for automated label generation
Rate Limits
The ShipOS API implements rate limiting to ensure fair usage and maintain service reliability for all users. This guide explains how rate limits work, the different tiers available, and best practices for handling rate limit responses.
Setup & Configuration
Learn how to create webhook endpoints, verify signatures, handle retries, and implement best practices for receiving real-time notifications from ShipOS.