Errors, limits and billing
Every error is structured and written to be shown to a person.
Error format
{
"error": {
"code": "validation_failed",
"message": "2 of 120 orders could not be used. Fix the listed problems and send the request again with a new Idempotency-Key.",
"fields": [
{ "field": "orders[17]", "message": "The address is incomplete. Add a street number and a city or postal code." }
]
}
}code is stable and safe to branch on. message is human readable. fields points at the input path (orders[17]) when the problem is in your data. Requests that fail JSON schema validation return 422 with the failing field and reason.
Common codes
| Status | Code | What to do |
|---|---|---|
| 402 | payment_required | No optimization credit or active plan. Buy credits or choose a plan in Billing. |
| 409 | job_not_completed | The result is not ready. Poll the optimization first. |
| 422 | idempotency_key_required | Add an Idempotency-Key header (8 to 128 characters). |
| 422 | validation_failed | Orders or vehicles were rejected. See fields. |
| 422 | payg_limit_orders / payg_limit_vehicles | A single-optimization credit covers up to 300 orders and 30 vehicles. Split, or use a plan. |
| 422 | too_many_orders / too_many_vehicles | Above 500 orders or 100 vehicles per optimization. Split by zone or depot. |
| 429 | too_many_active_jobs | Two optimizations are already running. Wait for one to finish. |
| 429 | rate_limited | Slow down and retry. |
| 503 | jobs_paused | Maintenance. Retry in a few minutes. |
Limits
- Up to 500 orders and 100 vehicles per optimization, one depot.
- Solver time limit 1 to 60 seconds (default 10).
- Request body up to 256 KB.
- Unassigned orders are not errors: they are returned with a reason so you can fix and re-run.
Billing
- Pay as you go: one credit per completed optimized plan. Baseline comparisons are free after your first purchase.
- Monthly plans: usage is metered by orders optimized, vehicles planned and scenarios executed, with overage.
- Usage is recorded only when an optimization completes successfully. Failed and cancelled runs are never billed. API calls themselves are not metered.
Best practices
- Store the optimization id with your dispatch run, and use the run id in the Idempotency-Key.
- Provide coordinates when you have them: it is faster and avoids geocoding failures.
- Treat unassigned orders as a work list: show the message, fix the cause, run again.
- Verify webhook signatures and keep polling as a fallback.