Skip to Content
Errors & Rate Limits

Errors & Rate Limits

The IDeliver API uses standard HTTP status codes and returns machine-readable JSON error bodies so you can handle failures gracefully in your integration.


Error response format

All errors return a JSON body with at minimum an error code and a human-readable message:

{ "error": "validation_error", "message": "customer_phone is required.", "details": { "field": "standardized.customer_phone" } }

HTTP status codes

CodeMeaningWhat to do
200 / 201SuccessOrder created or retrieved successfully
400Bad requestFix the request body — check error and message for the specific issue
401UnauthorizedYour API key is missing, expired, or invalid
403ForbiddenYour key lacks the required scope, or your account is blocked (e.g. billing issue, pending KYB)
404Not foundThe order ID or endpoint does not exist
409ConflictDuplicate external_order_id with a different payload
429Rate limitedSlow down — back off and retry after the Retry-After header value
500 / 503Server errorRetry with exponential backoff; if persistent, check status.ideliver.ng 

Common error codes

error valueWhat it means
unauthorizedMissing or invalid API key
forbiddenValid key, but insufficient scope or account restriction
validation_errorOne or more required fields are missing or invalid
OUT_OF_COVERAGE_AREAPickup or dropoff coordinates fall outside all active dispatch zones. Includes point (pickup/dropoff), lat, lng. Use GET /v1/coverage/check first
duplicate_orderexternal_order_id already exists
outside_coverageCoordinates / address outside platform coverage (e.g. public pricing preview)
pickup_outside_coveragePickup outside merchant / pricing zone (internal estimation paths)
wallet_insufficientYour wallet balance is too low to fund this delivery
idempotency_conflictIdempotency-Key reused with a different request body
missing_pickup_timestandardized.scheduled_pickup_at is required
missing_delivery_windowstandardized.delivery_window_start and delivery_window_end are required
invalid_pickup_timePickup time must be in the future
invalid_delivery_windowDelivery window start must be before end
cannot_cancelOrder is in a terminal or protected status and cannot be cancelled
kyb_requiredAccount requires identity verification before placing orders
rate_limitedToo many requests — slow down

Rate limits

Rate limits are applied per API key:

TierRequests per minute
Sandbox (ilv_test_…)60
Production (ilv_live_…)300

When you are rate limited, the API returns HTTP 429 with a Retry-After header indicating how many seconds to wait before retrying.

HTTP/1.1 429 Too Many Requests Retry-After: 5

Retrying requests

For server errors (5xx), use exponential backoff with jitter:

async function createOrderWithRetry(client, payload, maxAttempts = 3) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await client.orders.create(payload); } catch (err) { if (err.status >= 500 && attempt < maxAttempts) { const delay = Math.pow(2, attempt) * 500 + Math.random() * 200; await new Promise(resolve => setTimeout(resolve, delay)); continue; } throw err; } } }

Do not retry 4xx errors — they indicate a problem with your request that must be fixed before retrying.