Skip to main content
The Zinc API uses conventional HTTP response codes to indicate the success or failure of an API request.

HTTP Status Codes

Error Response Format

All error responses follow a consistent structure:

API Error Codes

General Errors

Example

Authentication Errors

Example

Device Authorization Errors

Returned by POST /device/token while an agent polls for approval. These follow RFC 8628, so three of the four are not failures — they report where the flow is, and only access_denied means stop. authorization_pending and slow_down both carry details.interval, the number of seconds to wait (default 5).

Example

expired_token also covers a code that was already redeemed — a key is handed over exactly once. Retrying a successful redeem returns this, not the key again.

Wallet & Payment Errors

Example

required is max_price + the API fee, because an order with no retailer_credentials_id is placed on a Zinc account and the item comes out of your wallet. details.fund_with lists every way forward; when you already have your own retailer account saved for that store it is listed first, as the your_retailer_account rail, and naming it drops the balance required to the API fee alone. See Retailer Accounts and the rails.
The metered data endpoints are the one exception to the envelope above. GET /search and the /products/* endpoints return a bare {"detail": "Insufficient wallet balance for data API call"} with their 402, not an error object — read detail, not error.code, when handling a shortfall on those.

Order Request Errors

unsupported_retailer, unsupported_country, and guest_checkout_not_supported are all predictable before you submit an order — ask GET /retailers/check with the product URL and destination country first.non_us_retailer is a legacy value that the API no longer returns. Zinc is not US-only; if you branch on it, that branch is dead.

Example

External Service Errors

Example

Order Processing Errors

When an order fails during processing, the error_type field in the order response or webhook payload contains one of these codes:
On a best-effort order, some of these codes stop being failures. A code covered by a concern you relaxed is recorded as an entry in fulfillment.concessions and the order goes ahead — the same code, reported as something that was worked around rather than something that stopped the order.

Structured error details

Alongside the flat error and error_type keys (kept for backward compatibility), a failed job result may include an error_details object. This is the structured home for enrichment beyond the category and message — for example, the specific reasons a shipping address was rejected, or which fields failed validation. Each entry in field_errors is a FieldError: Each entry in line_rejections is a LineRejection: one order line the retailer rejected, as the retailer reported it. It’s currently reported for Amazon orders and is empty on order-level failures. Lines the retailer cancelled only because another line was rejected aren’t listed.

Example

Product Errors

An order sent with fulfillment: { "items": "best_effort" } skips the offending item and ships the rest instead of failing on these codes. The item’s status becomes skipped, and the code lands in fulfillment.concessions. An order whose every item was skipped still fails, as cart_empty.

Example

Price Errors

Example

Cart & Checkout Errors

Example

Gift Errors

An order submitted with is_gift: true fails with this error type rather than being placed as a normal order — a gift arriving with prices visible to the recipient is treated as worse than no order. If gifting is an optional add-on in your flow, catch this error type and retry without is_gift to place the order as a standard purchase. See Gift orders. Alternatively, opt out of the failure up front with fulfillment: { "gift": "best_effort" } — a retailer with no gift option then gets a normal order rather than none, and the order reports the substitution in fulfillment.concessions.
gift_message does not fail this way. Where a retailer’s checkout has no gift-message field, the order is still placed without the message.

Example

Shipping Errors

Example

Payment Errors

Example

Account Errors

Example

Retailer Errors

Refusals you can predict

Three of these refusals are decided from the store and destination alone, so you do not have to submit an order to discover them. GET /retailers/check returns the same code up front in unsupported_reason: The codes are reused verbatim from the order path, so a refusal from /retailers/check and one from POST /orders for the same URL cannot disagree.

Example

Quantity Limit Errors

An order sent with fulfillment: { "quantity": "best_effort" } buys the retailer’s cap instead of failing with quantity_limit_exceeded, and reports the requested and fulfilled counts in fulfillment.concessions. order_limit_exceeded is your own account limit and is not relaxable.

Example