Getting Started > Error Codes

Error Codes

Last Updated: 2026-07-02

Every error response has a machine-readable code. Branch your retry logic on the code — never the human-readable message.

Error shape

All error responses share this envelope:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "title is required"
  },
  "requestId": "01HXYZ..."
}

The code is the contract. The message may change between versions — don't pattern-match on it. The requestId is your tracking ID when reporting bugs to our support team.

Error code catalog

CodeHTTP When you'll see it
BAD_REQUEST400Malformed request (missing required header, invalid query param)
INVALID_JSON400Body parse failed (malformed JSON)
VALIDATION_ERROR400Body schema rejected (field missing, wrong type, out of bounds)
PAYLOAD_TOO_LARGE413Body exceeded 1 MB (10 MB for /admin/uploads)
UNAUTHORIZED401Missing or invalid credentials / signature
SELLER_TOKEN_REQUIRED401Endpoint needs an access token (see OAuth flow)
HMAC_VERSION_DEPRECATED401Using HMAC v1; migrate to v2 (binds method + body)
SIGNATURE_REPLAYED401Same signature was used within the freshness window — re-sign with a fresh timestamp
FORBIDDEN403Auth succeeded but the actor lacks the required scope
NOT_FOUND404Resource does not exist — or exists but does not belong to your seller (we return 404 not 403 to avoid leaking existence)
RATE_LIMITED429Per-minute quota tripped — see Retry-After header
SHIP_FAILED400Upstream rejected the ship action (state transition not allowed)
CANCEL_FAILED400Upstream rejected the cancel action
CREATE_FAILED502Upstream rejected the return-creation (see safe message in response)
APPROVE_FAILED400Upstream rejected the return-approval or cancellation-approval
REJECT_FAILED400Upstream rejected the return-rejection or cancellation-rejection
DISPUTE_FAILED400Upstream rejected the return dispute (POST /open/v1/returns/:id/dispute)
INVALID_TRANSITION400Tried to ship an already-cancelled order, etc.
ORDER_NOT_CANCELLABLE422Order has shipped or completed — seller cancellation refused (POST /orders/:id/cancel)
CANCELLATION_ALREADY_PROCESSED422Cancellation request was already approved, rejected, or auto-approved
CANCELLATION_DEADLINE_EXCEEDED422Cancellation response window expired — buyer is entitled to auto-approval
SSRF_CHECK_FAILED400Webhook URL points to a private/internal address
NOT_IMPLEMENTED501Endpoint reserved for a future version (e.g. /open/v1/payouts)
MAINTENANCE503Platform is in maintenance mode — retry shortly
INTERNAL_ERROR500Bug on our end — include the requestId from the response when reporting

Cross-tenant 404 — why not 403

If you look up an order ID that exists but belongs to a different seller, we return 404 NOT_FOUND, not 403 FORBIDDEN. This is deliberate — 403 leaks that the resource exists. Partners might use that for enumeration.

If you're sure the ID is yours but getting 404, check:

  1. Are you using the right access token for the right seller?
  2. Did the order's seller revoke your authorization? POST /open/v1/auth/revoke flips all subsequent reads to 404.
  3. Is the access token expired? Refresh via POST /open/v1/auth/token/refresh.