Error handling
The Flex Forward API uses standard HTTP status codes and structured error responses. This page covers the error formats, status code meanings, and guidance for handling failures.Error response formats
The API returns four error response shapes depending on the type of failure. Understanding which shape to expect helps you write correct error-parsing logic.Standard error
Returned for failures such as unsupported couriers/products, authentication failures, conflicts, not-found errors, and server errors. The shape is{ "error": string, "code"?: string }:
error text is informational and may change without notice. Branch on the HTTP status code and, where present, code — never on the message text.
Some errors include a machine-readable code. The following codes distinguish label-creation conflicts from courier failures:
The
code field is optional and this list is not exhaustive. Handle errors without a code using their HTTP status, and tolerate unknown codes.
Validation error
Returned for request validation failures (HTTP 400). Includes adetails array with field-level error information:
details contains:
Only the first validation error is returned. Fix it and resend to surface the next one.
HTTP 400 can also use the standard error shape, for example when a courier or product is unsupported. Check whether
details exists before reading it; do not assume every 400 contains field-level errors.
HTTP status codes
Label creation outcomes
POST /labels returns the same LabelResponse shape on 200, 201, and 502. The HTTP status code tells you whether this call created the label, replayed an earlier attempt, or was rejected by the courier. The status field tells you whether a label exists.
Validation errors (400)
Schema validation errors indicate that the request body does not meet the API requirements and include adetails array with specific field paths. Other HTTP 400 errors use the standard error shape without details.
Common causes:
- Missing required fields (
shipment.shipTo,courier,idempotencyKey) - Wrong field types or lengths (for example
countryCodemust be exactly 2 characters) - Negative numeric values (
weightand dimensions must not be negative) - An invalid
order.customerOrderNumber(maximum 40 characters, using only ASCII letters, digits,-, and_) - An unsupported
label.format(usePDForPNG) or itemunitPrice.currency(onlyUSDis accepted)
Fix the reported error before retrying. The same
idempotencyKey can be reused after a 400 response because no label was created.Authentication errors (401 / 403)
401 Unauthorized
Thex-rr-apikey or x-rr-apitoken header is missing or invalid:
403 Forbidden
The credentials are valid but the account is not permitted to call the API (for example, a blocked account):Downstream courier errors (502 and 422)
When the courier service returns an error duringPOST /labels, the API responds with HTTP 502. The label is persisted in the database with status: failed and includes the courier error details:
error object contains:
Later calls to
GET /labels/{id} or GET /tracking/{id} for a failed label return HTTP 422 with a LabelFailedResponse body — no document or tracking is available for that label:
Retryable vs non-retryable errors
See Idempotency and Retries for the recommended retry strategy.
Troubleshooting
Missing Content-Type header
Missing Content-Type header
All POST requests must include
Content-Type: application/json. Without it, the request body will not be parsed and the API returns a 400 error.Wrong base URL or HTTP instead of HTTPS
Wrong base URL or HTTP instead of HTTPS
All requests must use HTTPS. Verify you are using the correct environment URL:
https://api.flexforwardship.com (production) or https://sandbox.flexforwardship.com (development).Identifier not found
Identifier not found
The
id parameter in GET /labels/{id} and GET /tracking/{id} accepts a label UUID or your customerOrderNumber. Any other value, or an identifier from another account, returns a 404 error.Label created but status is failed
Label created but status is failed
A
status: failed response is returned with HTTP 502 from POST /labels (or with HTTP 200 when you replay the same idempotencyKey), and later reads of that label return HTTP 422. Check the error object (or the LabelFailedResponse body on reads) for the courier’s error message. Common causes: invalid address, unsupported destination, or courier account configuration issues.