Batch Packing
Submit hundreds or thousands of pack jobs in a single API call and poll for results asynchronously. Batch packing is ideal for overnight processing, bulk order fulfillment, and high-volume scenarios.
Prerequisites
- A valid API key (see Authentication)
- Items with known dimensions and weights
- Containers defined (inline or via Container Master)
Workflow overview
POST /batch (submit jobs) --> 202 Accepted + batchId
|
v
GET /batch/{batchId} (poll for results)
|
v
Results: completed / failed per order
Step 1: Submit a batch
Each batch contains an array of orders, where each order has its own packRequest. Maximum 10,000 orders per batch.
curl -X POST https://api.fractalpack.com/api/v1/batch \
-H "Content-Type: application/json" \
-H "X-Api-Key: fpk_test_your_api_key" \
-d '{
"orders": [
{
"orderId": "ORD-2026-0001",
"packRequest": {
"items": [
{
"id": "WIDGET-LG-001",
"length": 12,
"width": 8,
"height": 6,
"weight": 2.5,
"quantity": 3
}
],
"containers": [
{
"id": "BOX-MEDIUM",
"length": 18,
"width": 14,
"height": 12,
"maxWeight": 40
}
],
"allowMultipleBoxes": true
}
},
{
"orderId": "ORD-2026-0002",
"packRequest": {
"items": [
{
"id": "MONITOR-27IN",
"length": 28,
"width": 18,
"height": 8,
"weight": 12.0,
"quantity": 1
},
{
"id": "KEYBOARD-MECH",
"length": 17,
"width": 6,
"height": 2,
"weight": 2.1,
"quantity": 1
}
],
"containers": [
{
"id": "BOX-LARGE",
"length": 36,
"width": 20,
"height": 12,
"maxWeight": 50
}
],
"allowMultipleBoxes": true
}
},
{
"orderId": "ORD-2026-0003",
"packRequest": {
"items": [
{
"id": "CABLE-USB-C",
"length": 6,
"width": 4,
"height": 1,
"weight": 0.1,
"quantity": 10
}
],
"containers": [
{
"id": "BOX-SMALL",
"length": 12,
"width": 10,
"height": 6,
"maxWeight": 15
}
]
}
}
],
"webhookUrl": "https://hooks.example.com/batch-complete"
}'
Response (202 Accepted)
{
"batchId": "batch_x9y8z7w6",
"status": "submitted",
"totalOrders": 3,
"statusUrl": "/api/v1/batch/batch_x9y8z7w6"
}
The batch is queued for asynchronous processing. If you provide a webhookUrl, a POST is sent to that URL when the batch completes.
Step 2: Poll for results
curl -X GET "https://api.fractalpack.com/api/v1/batch/batch_x9y8z7w6" \
-H "X-Api-Key: fpk_test_your_api_key"
Response (in progress)
{
"batchId": "batch_x9y8z7w6",
"status": "processing",
"totalOrders": 3,
"completedOrders": 1,
"failedOrders": 0,
"pendingOrders": 2,
"createdAt": "2026-04-03T22:00:00Z",
"completedAt": null,
"orders": [
{
"orderId": "ORD-2026-0001",
"status": "completed",
"result": {
"algorithm": "ebAfit",
"results": [
{
"containerId": "BOX-MEDIUM",
"boxIndex": 0,
"packedItems": [
{ "id": "WIDGET-LG-001", "weight": 2.5 },
{ "id": "WIDGET-LG-001", "weight": 2.5 },
{ "id": "WIDGET-LG-001", "weight": 2.5 }
],
"unpackedItems": [],
"volumeUtilizationPercent": 57.1,
"totalWeight": 7.5
}
]
}
},
{
"orderId": "ORD-2026-0002",
"status": "pending"
},
{
"orderId": "ORD-2026-0003",
"status": "pending"
}
],
"nextPageToken": null,
"hasMore": false
}
Response (completed)
{
"batchId": "batch_x9y8z7w6",
"status": "completed",
"totalOrders": 3,
"completedOrders": 3,
"failedOrders": 0,
"pendingOrders": 0,
"createdAt": "2026-04-03T22:00:00Z",
"completedAt": "2026-04-03T22:00:45Z",
"orders": [ ... ],
"nextPageToken": null,
"hasMore": false
}
Batch status values: submitted, processing, completed.
Filtering by status
Retrieve only completed or failed orders:
curl -X GET "https://api.fractalpack.com/api/v1/batch/batch_x9y8z7w6?status=failed" \
-H "X-Api-Key: fpk_test_your_api_key"
Pagination
For large batches, paginate through results with limit and after:
# First page
curl -X GET "https://api.fractalpack.com/api/v1/batch/batch_x9y8z7w6?limit=100" \
-H "X-Api-Key: fpk_test_your_api_key"
# Next page (use nextPageToken from previous response)
curl -X GET "https://api.fractalpack.com/api/v1/batch/batch_x9y8z7w6?limit=100&after=ORD-2026-0100" \
-H "X-Api-Key: fpk_test_your_api_key"
limit: 1-1000, default 100after: cursor token from the previous page'snextPageTokenhasMore:trueif more pages exist
Step 3: Handle partial failures
Some orders may fail while others succeed:
{
"batchId": "batch_x9y8z7w6",
"status": "completed",
"totalOrders": 500,
"completedOrders": 497,
"failedOrders": 3,
"pendingOrders": 0,
"orders": [
{
"orderId": "ORD-2026-0042",
"status": "failed",
"error": "No container can fit item OVERSIZED-PANEL (48x36x2 in)"
},
{
"orderId": "ORD-2026-0199",
"status": "failed",
"error": "Total item quantity exceeds 500,000 limit"
},
{
"orderId": "ORD-2026-0350",
"status": "failed",
"error": "Item WIDGET-LG-001 has invalid dimensions (length=0)"
}
]
}
Failed orders include an error string. Completed orders include the full result (same shape as the POST /pack response).
To retry failed orders, submit a new batch with only the corrected orders.
Step 4: List all batches
curl -X GET "https://api.fractalpack.com/api/v1/batch?limit=20" \
-H "X-Api-Key: fpk_test_your_api_key"
Response
{
"batches": [
{
"batchId": "batch_x9y8z7w6",
"status": "completed",
"totalOrders": 500,
"completedOrders": 497,
"failedOrders": 3,
"createdAt": "2026-04-03T22:00:00Z",
"completedAt": "2026-04-03T22:05:30Z"
},
{
"batchId": "batch_a1b2c3d4",
"status": "processing",
"totalOrders": 200,
"completedOrders": 85,
"failedOrders": 0,
"createdAt": "2026-04-03T22:10:00Z",
"completedAt": null
}
],
"nextPageToken": null,
"hasMore": false
}
Pagination: limit (1-100, default 20) and after (cursor token).
Realistic high-volume scenario
Pack 500 orders overnight. Each order has its own item list and uses Container Master defaults (omit containers from each packRequest):
curl -X POST https://api.fractalpack.com/api/v1/batch \
-H "Content-Type: application/json" \
-H "X-Api-Key: fpk_test_your_api_key" \
-d '{
"orders": [
{
"orderId": "NIGHT-RUN-0001",
"packRequest": {
"items": [
{ "id": "SKU-A100", "length": 10, "width": 8, "height": 4, "weight": 1.5, "quantity": 2 },
{ "id": "SKU-B200", "length": 6, "width": 6, "height": 6, "weight": 3.0, "quantity": 1 }
],
"allowMultipleBoxes": true
}
},
...
],
"webhookUrl": "https://hooks.example.com/nightly-batch"
}'
When all 500 orders complete, the webhook fires with the batch ID. Pull results page by page:
# Page through completed results
curl "https://api.fractalpack.com/api/v1/batch/batch_xxx?status=completed&limit=100"
curl "https://api.fractalpack.com/api/v1/batch/batch_xxx?status=completed&limit=100&after=NIGHT-RUN-0100"
# Check failures separately
curl "https://api.fractalpack.com/api/v1/batch/batch_xxx?status=failed"
Webhook payload
When a webhookUrl is provided, the system sends an HTTPS POST when the batch completes:
{
"event": "batch.completed",
"batchId": "batch_x9y8z7w6",
"status": "completed",
"totalOrders": 500,
"completedOrders": 497,
"failedOrders": 3
}
The webhook URL must use HTTPS and must not target private or reserved IP ranges.
Rate limits
Batch submission is subject to rate limiting. If you exceed your plan's pack budget, the API returns 429 Too Many Requests with a Retry-After header:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Wait the specified number of seconds before retrying.
Constraints
| Constraint | Limit |
|---|---|
| Orders per batch | 10,000 |
| Items per order | 10,000 line items |
| Total quantity per order | 500,000 units |
| Containers per order | 1,000 types |
| Webhook URL | Must be HTTPS, no private IPs |
| Order IDs | Must be unique within a batch |
Error handling
| Status | Cause | Fix |
|---|---|---|
| 400 | Empty orders array | Provide at least one order |
| 400 | Duplicate orderIds | Ensure all orderIds are unique |
| 400 | Invalid webhookUrl | Use HTTPS, avoid private IPs |
| 404 | Batch not found | Check the batchId |
| 429 | Rate limit exceeded | Wait for Retry-After seconds |
Next steps
- Basic Packing -- single synchronous pack requests
- Cost-Optimized Packing -- use
optimizeFor: "cost"in batch packRequests - CSV Import -- import items and orders in bulk before batching