Skip to content

Errors

Failed requests return a JSON body with one error object:

{
"error": {
"code": "spend_limit",
"message": "This purchase is above the per purchase limit of this API key.",
"details": { "limitCents": 2000 },
"request_id": "c3a7e1f0-52d8-4b69-8e14-7f0a9d6b2c35"
}
}
  • code is stable. Branch on it in code.
  • message is for people. Do not parse it, and expect the wording to change.
  • details is optional and depends on the code. It can hold the field that failed, a limit, or a retry time.
  • request_id matches the X-Request-Id header on the same response. Log it, and quote it when you contact support.
Code HTTP status Meaning What to do
validation 422 The request is malformed or breaks a rule. details.issues lists each field path and message. Also used when a shipping rule blocks a shipment (details.blockedByRule). Fix the request. Do not retry unchanged.
unauthenticated 401 The key is missing, malformed, unknown, revoked or expired. Check the key.
forbidden 403 The key lacks the permission, or the request came from an address outside its allowlist. Use a key with the right permission or from an allowed address.
not_found 404 No such endpoint or object in your account. Check the id.
conflict 409 The request clashes with the current state: an already purchased shipment, expired rates (details.expired), a refund already requested, or an idempotency key still in use. Read the current state, then decide.
insufficient_funds 402 The wallet cannot cover the purchase. Add funds, then try again.
spend_limit 402 The purchase would break a per label or per day limit on the key or the account. details holds the limit in cents. Raise the limit in the app, or wait for the day to reset.
org_suspended 403 The account is not active. Contact support.
rate_limited 429 Too many requests. The Retry-After header says how many seconds to wait. Wait, then retry. See Rate limits.
maintenance 503 The platform is in maintenance and refuses changes. Reads still work. Retry later.
not_configured 501 A needed service is not set up, for example no carrier is available. Retry later or contact support.
upstream 502 A carrier failed or returned something unusable. Retry with backoff.
internal 500 Something went wrong on our side. The message is generic on purpose. Retry with backoff. Quote the request_id if it persists.

An unsupported method on a real path returns 405 with an Allow header.

  • Retry 429, 502, 503 and 500 with exponential backoff and some jitter. For 429, wait at least Retry-After seconds.
  • Do not retry 422, 401, 403, 404 unchanged. They will fail the same way.
  • For a purchase, always retry with the same Idempotency-Key. See Buying labels safely.
  • A 5xx response to a request with an idempotency key does not lock the key. You can send the same request again.

© 2026 Ship Jay. All rights reserved. Created & Developed by WCWS Internet