Skip to main content
Sign in with your store to see only the help that applies to you.

Error Handling

The Developer API uses standard HTTP status codes and returns JSON error bodies. Error responses are not wrapped in the data / meta envelope.


Error Response Format​

Most errors carry a single error message:

{
"error": "Human-readable error message"
}

Validation error bodies vary by endpoint — read defensively:

WhereShape
Most endpoints (generic validation failure){ "error": "Validation failed: ...", "errors": ["Name can't be blank"] }
POST /api/v1/products{ "error": "Sku has already been taken", "errors": { "sku": ["has already been taken"] } }
POST/PATCH /api/v1/customers{ "errors": ["Email is invalid"] } (no error key)
Webhook subscriptions{ "error": "Validation failed", "errors": ["Url must use HTTPS"] }

Plan-related errors also include a machine-readable code, for example { "error": "Feature not enabled: enable_customers", "code": "feature_not_enabled" }.


Status Codes​

Success​

CodeMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
207 Multi-StatusPOST /api/v1/products/bulk_upsert — at least one row failed; see the body

Client Errors​

CodeMeaningCommon Cause
400 Bad RequestMissing required parameter: <name>A required wrapper object (e.g. product, customer) is missing from the body
401 UnauthorizedInvalid, expired or revoked API keyCheck the X-API-Key header
402 Payment RequiredThe store has no active POS subscription (code: pos_plan_required) or has not finished onboardingContact the store owner
403 ForbiddenMissing scope, read-only or internal endpoint, a write with a Test Mode key, or a feature not included in the store's planCheck key scopes and the error message
404 Not FoundResource doesn't existCheck the ID
409 ConflictRecord already exists (with a details field)A unique value is already taken
422 Unprocessable EntityValidation failed or invalid inputCheck error / errors
429 Too Many RequestsRate limit exceededWait and retry

Server Errors​

CodeMeaning
500 Internal Server ErrorSomething went wrong on our end. The body is {"error": "An unexpected error occurred. Please contact support."} (or "Database error occurred" with a details field)

Rate Limiting (429)​

When you exceed your rate limit, the response looks like this:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1774180860

{"error":"Rate limit exceeded. Retry later."}

Retry-After is the number of seconds left in the current window, and X-RateLimit-Reset is the moment that window ends, as a Unix timestamp in seconds. Limits are counted in fixed one-minute windows.

Handle 429 gracefully

Wait the number of seconds in Retry-After before retrying — that takes you into a new window. Add exponential backoff if repeated retries are still throttled.


Common Mistakes​

Wrong header name​

# Wrong — API keys use X-API-Key, not Authorization
curl -H "Authorization: Bearer bpos_abc..."

# Correct
curl -H "X-API-Key: bpos_abc..."
note

Authorization: Bearer <jwt> is used by the POS terminal for user session auth (JWT tokens). Sending an API key that way returns 401 Unauthorized. External API keys always use the X-API-Key header.

Missing scope​

If you get 403 Forbidden with Insufficient scope. Required: <scope>, the key is missing that scope. For example, reading customers requires customers:read. Scopes cannot be added to an existing key — create a new key with the right scopes.

Write on read-only endpoint​

Some endpoints only allow read access via API keys (e.g., sales). Any non-GET request to them returns 403 Forbidden with Write operations are not available for this endpoint via API key.


What's Next?​