Conventions
The error envelope, headers, pagination, and rate limits every endpoint on the platform shares.
Geo, Parcels and Inventory use the conventions below. AI preserves OpenAI-compatible JSON, SSE and binary responses and uses an OpenAI error envelope; see AI errors.
Errors
Commerce API errors use this envelope:
{
"error": {
"code": "carrier_unsupported",
"message": "zrexpress does not support editing submitted parcels",
"details": { "carrier": "zrexpress", "operation": "edit" }
}
}| HTTP | code | meaning |
|---|---|---|
| 400 | validation_failed | body/query invalid; details.fields[] per field |
| 400 | validation_failed + details.reason | Parcel carrier rejects — clients localize by reason (see below) |
| 401 | invalid_api_key / invalid_token | unknown, revoked, or expired credential |
| 403 | insufficient_scope | credential lacks the required scope (WWW-Authenticate set) |
| 403 | product_not_enabled | project has not enabled the product |
| 404 | not_found / not_covered | resource missing / point outside covered geography |
| 409 | idempotency_conflict | same Idempotency-Key, different payload |
| 422 | batch_too_large / unresolvable_geo | semantic failures |
| 422 | insufficient_stock / unbalanced_operation / reserved_stock_conflict | Inventory quantity guards |
| 422 | batch_cost_conflict / operation_not_reversible / key_not_found | Inventory cost, reversal, and missing-key guards |
| 429 | rate_limited | per-key rate exceeded; Retry-After set |
| 429 | quota_exceeded | daily product quota exhausted; details.resetAt set |
| 501 | carrier_unsupported | operation not supported by this carrier |
| 502 | carrier_error | upstream carrier failed; details.carrierMessage set |
| 500 | internal | a bug — include X-Request-Id when reporting it |
Parcel ship details.reason (stable)
When POST /parcels (submit: true) or send fails at the carrier, the envelope
keeps a machine-readable reason so UIs do not parse Ecotrack French prose:
details.reason | meaning | typical code |
|---|---|---|
cod_amount_rejected | courier rejected COD / montant (often 0) | validation_failed |
destination_not_covered | destination / commune / wilaya reject | validation_failed |
carrier_auth_failed | bad or revoked courier token | invalid_api_key |
carrier_validation_failed | other field validation from the courier | validation_failed |
carrier_unavailable | timeout / 5xx / empty tracking | carrier_error |
details.carrierMessage holds the raw upstream text when available.
details.fields[] points at the fixable path (codAmount, destination.city, …).
Headers
X-Request-Id— on every response, echo it back when reporting a500.X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset— returned by metered commerce endpoints; early rejections may omit them. AI publishes its applicable limit and remaining count.Idempotency-Key: <caller-generated, ≤64 chars>— honored onPOST /parcels,POST /parcels/batch,POST /inventory/operations, andPOST /inventory/reservationsfor 24 hours. Replaying the same key with a different body is a409 idempotency_conflict, not a silent overwrite.
Pagination
Paginated resource lists use cursors; some catalog lists return a complete array. Check the endpoint schema:
GET /parcels?limit=50&cursor=eyJpZCI6InBjbF84WHcifQFor the parcel list, limit defaults to 50 and caps at 200. Its response carries meta.nextCursor,
which is null once you've reached the end.
Localization
Catalog resources always include the full locales map (ar/fr/en).
?lang= additionally sets displayName for the requested language — the resource ID remains stable, but the response display name changes. Cache localized responses by language and query. Conditional ETag/304 handling is not currently implemented.
Attribution
Any response carrying OSM-derived fields includes
meta.attribution: "© OpenStreetMap contributors (ODbL)". Where you display
that data, the license requires you to show it too.
Rate limits and quotas
Launch defaults — catalog-configurable per project, shown live in the API catalog:
| Product | Rate (per key) | Daily quota (per project) | Notes |
|---|---|---|---|
| Geo catalog / search / nearby / reverse | 20 rps, burst 60 | 50,000 | Successful reads count toward quota |
| Geo resolve | 10 rps | 10,000 rows | batch rows count individually |
| Parcels reads | 40 rps, burst 80 | 200,000 | |
| Parcels writes | 20 rps, burst 40 | 50,000 parcels | batch items count individually |
| Labels | 20 rps, burst 40 | 50,000 | bulk PDF counts per parcel |
| Inventory reads | 20 rps | 50,000 | objects, availability, movements |
| Inventory writes | 8 rps | 20,000 | operations, rules |
| Inventory reserve | 15 rps | 50,000 | hold, consume, release |
| AI reads | 20 rps, burst 40 | 50,000 | Model, task and video reads | | AI generation | 10 rps, burst 20 | 10,000 | Paid submissions; project/tenant policy can tighten these |
Daily quotas use Africa/Algiers. Monthly spend uses UTC. Honor Retry-After; limits can change with project policy. AI controls explain layered admission.