Error Handling
FractalPack returns errors as RFC 9457 Problem Details JSON objects. Every error response has a consistent structure.
Error response format
{
"type": "https://developers.fractalpack.com/errors/not_found",
"title": "Not Found",
"status": 404,
"detail": "Item 'SKU-MISSING' not found.",
"instance": "0HN8ABC123",
"doc_url": "https://developers.fractalpack.com/errors/not_found"
}
| Field | Description |
|---|---|
type |
URI identifying the error type |
title |
Short human-readable summary |
status |
HTTP status code |
detail |
Specific explanation of what went wrong |
instance |
Trace identifier for this request (useful for support) |
doc_url |
Link to documentation for this error type |
Some errors include additional fields. For example, validation errors may include a field extension indicating which input field failed.
Success status codes
| Status | Meaning | Used by |
|---|---|---|
200 OK |
Request succeeded | GET, PATCH, most POST actions |
201 Created |
Resource created | POST /items, POST /containers, POST /orders, POST /shipments, POST /fulfillment-plans |
202 Accepted |
Request accepted for async processing | POST /batch |
204 No Content |
Success with no response body | DELETE /items/{id}, DELETE /containers/{id}, DELETE /keys/{id} |
Error status codes
400 Bad Request
Validation failed. The request body or query parameters are malformed.
{
"type": "https://developers.fractalpack.com/errors/bad_request",
"title": "Bad Request",
"status": 400,
"detail": "At least one item is required.",
"instance": "0HN8ABC456",
"doc_url": "https://developers.fractalpack.com/errors/bad_request"
}
Common causes:
- Missing required fields (
itemsin a pack request) - Values out of range (dimensions must be > 0, weight must be >= 0)
- Items list exceeds the maximum of 10,000 line items
- Total item quantity exceeds 500,000
- Containers list exceeds 1,000 entries
Fix: Check the detail field for specifics. Validate your payload before sending.
401 Unauthorized
Missing or invalid authentication credentials.
{
"type": "https://developers.fractalpack.com/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Invalid or revoked API key.",
"instance": "0HN8ABC789",
"doc_url": "https://developers.fractalpack.com/errors/unauthorized"
}
Common causes:
- Missing
X-Api-Keyheader orAuthorizationheader - Expired or revoked API key
- Expired JWT token
Fix: Verify your API key is correct and active. See Authentication.
403 Forbidden
Valid credentials, but insufficient permissions.
{
"type": "https://developers.fractalpack.com/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Admin role required for this operation.",
"instance": "0HN8ABCDEF",
"doc_url": "https://developers.fractalpack.com/errors/forbidden"
}
Common causes:
- Non-admin user attempting admin operations (delete, bulk import)
- API key lacking the required scope
Fix: Use an admin account or API key with the required permissions.
404 Not Found
The requested resource does not exist.
{
"type": "https://developers.fractalpack.com/errors/not_found",
"title": "Not Found",
"status": 404,
"detail": "Item 'SKU-MISSING' not found.",
"instance": "0HN8ABC012",
"doc_url": "https://developers.fractalpack.com/errors/not_found"
}
Fix: Verify the resource ID. IDs are case-sensitive.
409 Conflict
The request conflicts with current state. Covers duplicate creation and concurrency conflicts.
{
"type": "https://developers.fractalpack.com/errors/conflict",
"title": "Conflict",
"status": 409,
"detail": "An item with ID 'SKU-A100' already exists.",
"instance": "0HN8ABC345",
"doc_url": "https://developers.fractalpack.com/errors/conflict"
}
Common causes:
- Creating a resource with a duplicate ID
- Concurrent update conflict (another request modified the resource since you read it)
- Order already belongs to a consolidation group
Fix: For duplicates, use a unique ID or update the existing resource. For concurrency conflicts, re-read the resource and retry with the latest version.
422 Unprocessable Entity
The request is syntactically valid but semantically wrong.
{
"type": "https://developers.fractalpack.com/errors/bad_request",
"title": "Unprocessable Entity",
"status": 422,
"detail": "Unable to resolve SKU 'MISSING-SKU' to an item with dimensions.",
"instance": "0HN8ABC678",
"doc_url": "https://developers.fractalpack.com/errors/bad_request"
}
Common causes:
- Shipment creation references an order with SKUs not found in the Item Master
- Fulfillment plan references items without physical dimensions
Fix: Ensure all referenced SKUs exist in your Item Master with valid dimensions and weights.
429 Too Many Requests
Rate limit exceeded. See Rate Limiting for details.
{
"type": "https://tools.ietf.org/html/rfc6585#section-4",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit exceeded for this organization. Try again in 30 seconds."
}
Fix: Wait for the duration specified in the Retry-After header, then retry with exponential backoff.
500 Internal Server Error
An unexpected server error occurred.
{
"type": "https://developers.fractalpack.com/errors/server_error",
"title": "Internal Server Error",
"status": 500,
"detail": "An unexpected error occurred.",
"instance": "0HN8ABCABC",
"doc_url": "https://developers.fractalpack.com/errors/server_error"
}
Fix: Retry after a short delay. If the error persists, contact support with the instance value for tracing.
502 Bad Gateway / 503 Service Unavailable
Temporary infrastructure issues. The API is reachable but a downstream dependency is not.
Fix: Retry with exponential backoff. These errors are transient and typically resolve within seconds.
Error codes
| Code | Status | Description |
|---|---|---|
bad_request |
400 | Validation failure |
unauthorized |
401 | Missing or invalid credentials |
forbidden |
403 | Insufficient permissions |
not_found |
404 | Resource does not exist |
conflict |
409 | Duplicate or concurrency conflict |
server_error |
500 | Unexpected server error |
Handling errors in code
import requests
resp = requests.post(
"https://api.fractalpack.com/api/v1/pack",
headers={"X-Api-Key": "fpk_test_..."},
json=payload,
)
if resp.status_code == 200:
result = resp.json()
elif resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 5))
time.sleep(retry_after)
# retry...
elif resp.status_code >= 400:
error = resp.json()
print(f"Error {error['status']}: {error['detail']}")
if resp.status_code == 409:
# handle conflict (re-read and retry)
pass
elif resp.status_code >= 500:
# transient error, retry with backoff
pass