API Docs
Reference

Error Handling & Rate Limits

All API errors return consistent JSON responses. This page covers HTTP status codes, error response format, rate limiting, and recommended retry strategies.

Error Response Format

All error responses return a JSON object with an error field describing what went wrong and a timestamp. Validation errors include a properties map with per-field details.

Standard Error Response
{
"error": "Only draft shipments can be submitted",
"timestamp": "2026-03-08T12:00:00.000Z"
}
Validation Error Response
{
"error": "Oops! Something's not right. Please check your entries and try again.",
"properties": {
"name": "name must be a string",
"quantity": "quantity must be a positive number"
},
"timestamp": "2026-03-08T12:00:00.000Z"
}

HTTP Status Codes

CodeMeaningWhat to Do
200SuccessRequest completed successfully.
201CreatedResource created successfully.
204No ContentDelete completed. No response body.
400Bad RequestFix the request body or parameters. Check the error and properties fields for details.
401UnauthorizedToken missing, invalid, or expired. Refresh your token.
403ForbiddenYour token is missing a required OAuth scope for this endpoint. Re-authorize with the correct scopes.
404Not FoundResource doesn't exist or belongs to another organization. Check the ID.
429Too Many RequestsRate limited. Wait and retry with exponential backoff. See below.
500Internal Server ErrorSomething went wrong on our end. Retry after a short delay. If persistent, contact support.

Rate Limits

The API enforces rate limits to ensure fair usage and system stability. Limits are applied per OAuth client.

Sandbox

1,000

requests per hour

Production

Varies

Based on your plan. Contact us for details.

Rate Limit Headers

Every response includes headers to help you track your usage:

HeaderDescription
X-RateLimit-LimitMax requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Retry Strategy

For transient errors (429, 500, 502, 503), use exponential backoff with jitter:

Retry with exponential backoff (Node.js)
async function apiRequest(url, options, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.ok) return res.json();
// Don't retry client errors (except 429)
if (res.status < 500 && res.status !== 429) {
throw new Error(`API error ${res.status}: ${(await res.json()).error}`);
}
if (attempt < maxRetries) {
// Exponential backoff: 1s, 2s, 4s + random jitter
const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error("Max retries exceeded");
}

Common Error Scenarios

400Validation Errors

Missing required fields, invalid field types, or business rule violations. Check the properties map for per-field errors. Fix the request and retry.

401Token Expired

Access tokens expire after 1 hour. Use your refresh token to get a new access token, then retry the original request.

429Rate Limited

You've exceeded the request limit. Check X-RateLimit-Reset to know when you can resume. Use exponential backoff.

400Insufficient Stock

SPD submission failed because there aren't enough cartons in stock. Check available stock via the inventory endpoints before submitting.

Best practices

  • Always check the error field in error responses for details, and properties for per-field validation errors.
  • Implement automatic token refresh on 401 errors to avoid disrupting users.
  • Monitor rate limit headers proactively to avoid hitting limits.
  • Use idempotent request patterns where possible to make retries safe.
  • Log error responses with request IDs for debugging and support tickets.