Skip to content

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 for 400 VALIDATION_FAILED-style responses; maps each invalid field to a message.

HTTP status codes

StatusMeaning
200Success.
201Resource created.
400Validation or business-rule failure.
401Authentication failed.
403Authenticated but not allowed.
404Resource not found (or not owned by your merchant).
409Conflict (duplicate).
429Rate limit exceeded — slow down and retry.
5xxServer error — retry with backoff.

Authentication errors

codeHTTPMeaning
MISSING_API_KEY401No Authorization: Bearer header.
INVALID_API_KEY_FORMAT401Key does not start with pk_live_ or pk_test_.
INVALID_API_KEY401Key does not match any merchant.
MERCHANT_INACTIVE403Merchant account deactivated.

Customer errors

codeHTTPMeaning
VALIDATION_FAILED400See errors for field details.
MAX_ADDRESSES_EXCEEDED400Customer already has 5 addresses.
CUSTOMER_NOT_FOUND404Customer not found or not linked to your merchant.
CUSTOMER_PHONE_DUPLICATE409Phone already exists for your merchant.
CUSTOMER_EMAIL_DUPLICATE409Email already exists for your merchant.
CUSTOMER_HAS_ORDERS409Customer has existing orders and cannot be deleted.

Order errors

codeHTTPMeaning
CUSTOMER_REQUIRED400customerId missing.
SPECIAL_HANDLING_REQUIRED400specialHandlingTags empty.
INVALID_SPECIAL_HANDLING_TAG400Tag not in the allowed list.
INVALID_PACKAGE_SIDE400packageSide not in the allowed list.
INVALID_AMOUNT_TO_COLLECT400COD amount missing or negative.
AMOUNT_EXCEEDS_TOTAL400COD amount greater than pricing.total.
PACKAGE_PHOTO_REQUIRED400Merchant requires a package photo.
VALIDATION_FAILED400Other field errors — see errors.
INSUFFICIENT_WALLET_BALANCE400Wallet cannot cover the delivery fee (production only). Includes data: { required, balance, currency }.
CUSTOMER_NO_DELIVERY_ADDRESS400Customer has no address.
ORDER_NOT_DRAFT400activate called on an order that is not a draft.
ORDER_WINDOW_CLOSED400activate called outside the delivery partner's order window.
ORDER_NOT_FOUND404Order not found or not owned by your merchant.

Webhook errors

codeHTTPMeaning
VALIDATION_FAILED400url missing or not https://, or invalid event names — see errors.
WEBHOOK_NOT_FOUND404Webhook not found or not owned by your merchant.

Sandbox errors

codeHTTPMeaning
SANDBOX_ONLY403advance-status called with a production key.
INVALID_STATUS400Status not in the allowed lifecycle list.
ORDER_NOT_FOUND404Sandbox order not found.

Rate limiting

The integration API allows 600 requests per 15-minute window per API key. The response includes standard rate limit headers on every request:

HeaderMeaning
RateLimit-LimitMaximum requests allowed in the window.
RateLimit-RemainingRequests remaining in the current window.
RateLimit-ResetSeconds until the window resets.

When the limit is exceeded you receive 429 Too Many Requests. Wait until the window resets (check RateLimit-Reset) before retrying.

Handling errors well

  • Branch on code, not message or HTTP status alone.
  • Treat 429 as a signal to back off — wait for RateLimit-Reset seconds before retrying.
  • Treat 5xx as transient — retry with exponential backoff and a sensible cap.
  • Surface errors field messages directly to your own form UI when relevant.
  • Log the full error envelope (minus secrets) for support.

Wasal Delivery Platform · Integration API v1.0.0