Skip to main content
Snappy uses standard HTTP response codes to indicate the success or failure of an API request. If a request fails, we return a descriptive error object to help you identify and resolve the issue. The error shape is the same in V2 and V3.

The Error Object

Every error response follows a consistent JSON structure. The structure differs slightly between validation errors (HTTP 400) and all other errors. Validation errors (HTTP 400):
All other errors (401, 403, 404, 409, 422, 5xx):
Error codes are stable; changing a code is considered a breaking change. Error messages, however, may be updated over time to provide better clarity. Your integration should switch on errorCode for programmatic handling - never on the message text.

V3 error code anatomy

V3 endpoints use structured error codes in the format {STATUS}_{DOMAIN}_{SEQUENCE}:

HTTP Status Codes

400 – Bad Request

The server could not process the request, usually due to a syntax error in the URL or the JSON body. How to fix
  • Verify your request body matches the expected schema.
  • Ensure all required fields are present (e.g. variantId, recipient.email, idempotencyKey).
  • Check that field values are the correct type (e.g. strings vs. integers).
  • Inspect path in the response body - it points to the specific field that failed validation.

401 – Unauthorized

There is an issue with your API key credentials. How to fix
  • Missing header. Ensure you are passing the X-Api-Key header on every request.
  • Invalid key. Double-check that the key hasn’t been mistyped or deleted from the Dashboard.
  • Expired key. Check whether the key has reached its expiration date and rotate it if needed. See Authentication & Security.

403 – Forbidden

Your key is valid but does not have permission to access the requested resource. How to fix
  • Wrong scope. Check that your API key was created with the correct scope for this action (e.g. orders:create to place an order, products:read to read the catalog). See Authentication & Security.
  • Wrong environment. Make sure you are not using a Testing API key against a Production resource or vice versa. See Before You Begin.
  • Insufficient masking scope. Reading PII fields requires :read:unmasked rather than :read:masked. See PII Masking.

404 – Not Found

The requested resource does not exist, or it exists but is not visible to the calling Account. How to fix
  • Double-check the ID in your request path - copy it directly from a previous API response to avoid typos.
  • Verify the resource was successfully created before attempting to retrieve or update it.
  • If you’re scoping with Snappy-Account-Id, verify the resource belongs to that account.
Snappy intentionally returns 404 (rather than 403) in some cases where a resource exists but is not visible to your key - for example, a Collection belonging to a different Account. This prevents exposing the existence of resources your key shouldn’t know about. If you’re confident the resource exists and you should have access, check your key’s scope and account scoping headers.

422 – Unprocessable Entity

The request was syntactically valid, but Snappy can’t fulfill it due to a business rule or current resource state. How to fix
  • Read the errorCode and message to understand the specific rule that was violated.
  • Common 422 scenarios on V3:
    • Order already in transit - POST /v3/orders/{orderId}/cancel returns 422 once the fulfillment partner has picked up the shipment.
    • Variant not shippable to country - POST /v3/orders returns 422 if the shipping address country is outside the variant’s supported locations.
    • Insufficient billing balance - POST /v3/orders returns 422 when the Billing Method has insufficient funds.
    • Idempotency conflict - replaying an idempotencyKey with a different request body returns 422. Use the same key only with identical bodies.
  • Re-issue the request once the underlying state changes (e.g., refunded balance, address updated, order cancelled in time).

429 – Too Many Requests

Your integration has exceeded the API rate limit. How to fix
  • Pause your requests immediately.
  • Respect the Retry-After response header - it tells you how long to wait before retrying.
  • Implement an exponential backoff strategy - wait a short period before retrying, and increase the wait time with each subsequent retry.
  • Review your request frequency against the published Rate Limits.

500 – Internal Server Error

Something went wrong on Snappy’s end. How to fix
  • Check the Snappy Status Page to see if there is an ongoing incident.
  • Retry once with a short delay - many 500s are transient.
  • If no incident is reported and the issue persists, contact support with:
    • Request URL and method
    • The errorCode returned in the response body
    • A timestamp of when the error occurred
    • The idempotencyKey you used (for writes), so support can correlate without risking a duplicate

502 – Bad Gateway

An upstream service returned an invalid response while processing your request. Almost always transient. How to fix
  • Retry with exponential backoff. For writes, only retry if you supplied an idempotencyKey - otherwise you risk duplicate side effects.

503 – Service Unavailable

The service is temporarily unavailable, typically during a deployment or under unusual load. How to fix
  • Retry with exponential backoff. Respect the Retry-After header if present.
  • If the issue persists across several minutes, check the Snappy Status Page.

504 – Gateway Timeout

The request took too long to process and timed out. How to fix
  • Retry with a short delay; most 504s are transient.
  • For writes, only retry if you supplied an idempotencyKey (the original request may have actually succeeded before the timeout - the idempotency key lets you safely re-issue without risking a duplicate).
  • If a specific endpoint times out consistently, contact support with the request details.

Retry & Idempotency

Not all errors are safe to retry. The matrix below summarizes when retrying is the right move.

Idempotency keys make retries safe

Many Snappy write endpoints accept an idempotency key. Sending the same key twice returns the same result - no duplicate side effect, no double-charge, no second gift sent.
  • Generate one stable key per logical operation - e.g., user-{userId}-order-{cartId}. Reuse it on every retry of that operation.
  • Never generate a fresh random key on each retry - that defeats the protection and will result in duplicates.
  • Replaying with a different body returns 422 (idempotency conflict). Either reuse the original body or pick a new key.
  • See Duplicate Detection for the full reference.

Exponential backoff

For all retryable error codes, use exponential backoff with jitter:
  1. First retry: wait ~1 second.
  2. Each subsequent retry: double the wait, with random jitter.
  3. Cap at ~60 seconds between retries.
  4. Give up after 5–7 attempts unless the operation is critical and idempotent. Always respect a Retry-After header if the response includes one - it overrides your local backoff calculation.
Last modified on June 30, 2026