Errors and limits
Error format
Errors use standard HTTP status codes and a consistent body:
{
"error": {
"code": "invalid_request",
"message": "Request is not valid.",
"details": { "date": "Must be between today and 400 days ahead." }
},
"request_id": "a91f03c2d4e5b6f7"
}Use error.code in your code — message may change. details lists the fields that need fixing.
| HTTP | error.code | Meaning | Retry? |
|---|---|---|---|
| 400 | invalid_json | The body is not valid JSON. | No — fix the request. |
| 401 | unauthorized | Missing or invalid key. | No. |
| 403 | forbidden / ip_not_allowed | Account not active, live not approved, or IP not allowed. | No. |
| 404 | not_found | Unknown endpoint or booking. | No. |
| 405 | method_not_allowed | Wrong HTTP method. | No. |
| 409 | not_cancellable | Already cancelled or completed. | No. |
| 409 | not_offered | No open offer on this booking (accept / decline). | No. |
| 409 | not_instant | instant_only was requested (or your account is instant-only) and the booking cannot be confirmed instantly. Nothing was created; error.details.reason is no_price, short_notice or credit_limit. | No — offer another vehicle or time. |
| 409 | idempotency_conflict | The Idempotency-Key was used with a different body. | No — use a new key. |
| 409 | request_in_progress | The same Idempotency-Key is still being processed. | Yes, after a second. |
| 410 | offer_expired | The offer is older than 30 minutes. | Quote again. |
| 413 | payload_too_large | Body larger than 64 KB. | No. |
| 415 | unsupported_media_type | Missing Content-Type: application/json. | No. |
| 422 | invalid_request / invalid_offer | Validation failed; see details. | No — fix the request. |
| 429 | rate_limited | Too many requests. | Yes, after Retry-After seconds. |
| 500 | server_error | Unexpected error on our side. | Yes, with backoff. Contact us with the request_id if it persists. |
Rate limits
Each key may send 120 requests per minute by default. Every response carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute. |
X-RateLimit-Remaining | Requests left in the current minute. |
Retry-After | On 429: seconds to wait. |
If you need a higher limit, ask us under Questions. Cache what does not change often: GET /vehicle-types and GET /locations results can be cached for a day.
Idempotency
Networks fail. To retry a POST safely, send an Idempotency-Key header (1–80 characters: letters, digits, - _ : .), for example your order number:
Idempotency-Key: order-10045- The first request is processed normally and its response is stored for 48 hours.
- A repeat with the same key and the same body returns the stored response with the same HTTP status (e.g.
201for a booking) and headerIdempotent-Replayed: true— no second booking. - The same key with a different body returns
409 idempotency_conflict; a repeat while the first request is still running returns409 request_in_progress(retry after a second). - Validation errors are not stored, so you can fix the request and retry with the same key.
Timeouts
Most requests complete in well under a second; quotes that include partner availability can take up to 10 seconds. Set your client timeout to 30 seconds, and when a POST /bookings times out, retry it with the same Idempotency-Key.
Versioning
This is version 1 (/api/v1). Within v1 we only make backwards-compatible changes: new endpoints, new optional request fields, new response fields and new enum values. Make your code tolerant of unknown fields and values. Breaking changes will come in a new version, announced well in advance.