Appearance
Error Reference
All errors share the standard envelope:
json
{
"success": false,
"message": "Human-readable description",
"code": "MACHINE_READABLE_CODE",
"errors": { "fieldName": "Field-level message" }
}message— a description suitable for logs. Do not match on this string; it may change.code— a stable machine-readable identifier. Match on this.errors— present only for400 VALIDATION_FAILED-style responses; maps each invalid field to a message.
HTTP status codes
| Status | Meaning |
|---|---|
200 | Success. |
201 | Resource created. |
400 | Validation or business-rule failure. |
401 | Authentication failed. |
403 | Authenticated but not allowed. |
404 | Resource not found (or not owned by your merchant). |
409 | Conflict (duplicate). |
429 | Rate limit exceeded — slow down and retry. |
5xx | Server error — retry with backoff. |
Authentication errors
code | HTTP | Meaning |
|---|---|---|
MISSING_API_KEY | 401 | No Authorization: Bearer header. |
INVALID_API_KEY_FORMAT | 401 | Key does not start with pk_live_. |
INVALID_API_KEY | 401 | Key does not match any merchant. |
MERCHANT_INACTIVE | 403 | Merchant account deactivated. |
General errors
code | HTTP | Meaning |
|---|---|---|
REQUEST_FAILED | 4xx | The request failed before a more specific code could be assigned. |
RATE_LIMITED | 429 | The API key exceeded its request allowance. Retry after the current window resets. |
INTERNAL_ERROR | 5xx | An unexpected server error occurred. Retry with backoff and provide the X-Request-ID value to support if it continues. |
Customer errors
code | HTTP | Meaning |
|---|---|---|
VALIDATION_FAILED | 400 | See errors for field details. |
MAX_ADDRESSES_EXCEEDED | 400 | Customer already has 5 addresses. |
CUSTOMER_NOT_FOUND | 404 | Customer not found or not linked to your merchant. |
ADDRESS_NOT_FOUND | 404 | Address does not exist on this customer. |
CUSTOMER_PHONE_DUPLICATE | 409 | Phone already exists for your merchant and customer type. |
CUSTOMER_EMAIL_DUPLICATE | 409 | Email already exists for your merchant and customer type. |
CUSTOMER_HAS_ORDERS | 409 | Customer has outstanding (non-terminal) orders and cannot be deleted. |
Order errors
code | HTTP | Meaning |
|---|---|---|
CUSTOMER_REQUIRED | 400 | customerId missing. |
SPECIAL_HANDLING_REQUIRED | 400 | specialHandlingTags empty. |
INVALID_SPECIAL_HANDLING_TAG | 400 | Tag not in the allowed list. |
INVALID_PACKAGE_SIDE | 400 | packageSide not in the allowed list. |
INVALID_AMOUNT_TO_COLLECT | 400 | COD amount missing or negative. |
AMOUNT_EXCEEDS_TOTAL | 400 | COD amount greater than pricing.total. |
COD_NOT_ENABLED | 400 | COD orders are not enabled for the merchant. |
PACKAGE_PHOTO_REQUIRED | 400 | Merchant requires a package photo. |
INVALID_B2B_SIZE_TIER | 400 | orderType is b2b but b2bSizeTier is missing or not in the allowed list. |
B2B_CUSTOMER_NOT_BUSINESS | 400 | B2B order for a customer that is not a business customer. |
B2B_NOT_ENABLED | 400 | B2B delivery is not enabled for your merchant. |
EXPRESS_NOT_ENABLED | 400 | Express delivery is not enabled for your merchant. |
B2B_PRICING_NOT_CONFIGURED | 400 | No B2B delivery rate is configured for the destination. |
VALIDATION_FAILED | 400 | Other field errors — see errors. |
INSUFFICIENT_WALLET_BALANCE | 400 | Wallet cannot cover the delivery fee. Includes data: { required, balance, currency }. |
CUSTOMER_NO_DELIVERY_ADDRESS | 400 | Customer has no address. |
ORDER_NOT_DRAFT | 400 | activate called on an order that is not a draft. |
ORDER_WINDOW_CLOSED | 400 | activate called outside the delivery partner's order window. |
ORDER_NOT_EDITABLE | 403 | Update called on an order that is not pending. |
ORDER_NOT_CANCELLABLE | 403 | Cancel called on an order that is not pending. |
ORDER_NOT_FOUND | 404 | Order not found or not owned by your merchant. |
BRANCH_NOT_FOUND | 404 | branchId does not exist under your merchant. |
Webhook errors
code | HTTP | Meaning |
|---|---|---|
VALIDATION_FAILED | 400 | url missing or not https://, or invalid event names — see errors. |
WEBHOOK_NOT_FOUND | 404 | Webhook not found or not owned by your merchant. |
WEBHOOK_UNREACHABLE | 502 | Test ping could not be delivered to the webhook URL. |
Rate limiting
The integration API allows 600 requests per 15-minute window per API key, with an additional per-IP limit for abuse protection. The response includes standard rate limit headers on every request:
| Header | Meaning |
|---|---|
RateLimit-Limit | Maximum requests allowed in the window. |
RateLimit-Remaining | Requests remaining in the current window. |
RateLimit-Reset | Seconds until the window resets. |
When the limit is exceeded you receive 429 Too Many Requests with code RATE_LIMITED. Wait until the window resets (check RateLimit-Reset) before retrying.
Handling errors well
- Branch on
code, notmessageor HTTP status alone. - Treat
429as a signal to back off — wait forRateLimit-Resetseconds before retrying. - Treat
5xxas transient — retry with exponential backoff and a sensible cap. - Surface
errorsfield messages directly to your own form UI when relevant. - Log the full error envelope (minus secrets) for support.
