Developers / Errors
Errors
One error shape for the whole API, the full code table, and what is worth retrying.
Every failure on /v1 returns the same shape, whether it came from authentication, a rate limit, a controller, or a path that does not exist. Write one handler and it covers the API.
{
"error": {
"code": "INVALID_VIN",
"message": "VIN must be 17 characters.",
"requestId": "req_2f1c8a9e4b7d4c1a9f3e2d5b6c8a0f1e",
"details": [{ "field": "vin", "issue": "length" }]
}
}code. Messages are written for humans and may be reworded, and HTTP status alone does not distinguish, for example, a missing entitlement from a blocked address. details is present only when there is something specific to a field to say.requestId
Every request and every response carries X-Request-Id, and it is repeated in the error body. Quote it when you contact us and we can find the exact call, with no need to describe what happened.
If you send your own X-Request-Id we echo it back, so you can stitch our logs to your trace. Keep it to 64 characters of letters, digits, _, . or -. Anything else is replaced with one of ours rather than rejected.
The codes
| Code | HTTP | What it means | What to do |
|---|---|---|---|
INVALID_REQUEST | 400 | Malformed body, or a missing or unusable parameter | Fix the request. Do not retry unchanged |
INVALID_VIN | 400 | Not a valid VIN by length, characters or check digit | Validate before sending. Do not retry |
UNAUTHORIZED | 401 | Key missing, unknown, revoked or expired | Check the key. All four answer alike on purpose |
INSUFFICIENT_CREDIT | 402 | Prepaid balance exhausted, or postpaid limit reached | Top up. Retrying will not help |
USAGE_LIMIT_REACHED | 402 | The calls included in this billing period are used up | Topping up will not lift this. It resets next period, or ask us to raise it |
FORBIDDEN | 403 | Authenticated, but not entitled to this endpoint | Contact us to enable it |
IP_NOT_ALLOWED | 403 | Your account is restricted by address and this one is not on the list | The message names the address we saw. Call from an allowed one, or send us that address |
REPORT_NOT_FOUND | 404 | No report with that id on your account | Check the id. Ids are scoped to the account that bought them |
ENDPOINT_NOT_FOUND | 404 | No endpoint at that method and path | Check method and path against the reference |
REPORT_EXPIRED | 410 | Past the access window for that report | Buy the vehicle again for a current report |
RATE_LIMITED | 429 | Too many requests this minute | Wait for Retry-After, then continue |
INTERNAL_ERROR | 500 | Something broke on our side | Retry once. If it persists, send us the requestId |
UPSTREAM_UNAVAILABLE | 503 | A source we depend on is unavailable | Never billed. Safe to retry shortly |
Retrying
- Never retry
400,401,403,404or410. The answer will not change. - Do not hammer
402. Either your balance is empty or this period is used up, and the two need different people: one buys more credit, the other renegotiates the allowance. Branch on the code and alert someone rather than retrying. - Do retry
429,503and500, with backoff. HonourRetry-Afteron a429. - Retrying a lookup for a vehicle you already bought is free if your account has free repeats, and reading the report back is free in any case. Prefer the
GETover re-buying.
Rate limits
Every response carries your current allowance.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58On a 429 you also get Retry-After in seconds. Pace yourself against X-RateLimit-Remaining rather than discovering the ceiling by hitting it. If your limit does not fit your workload, ask. It is a setting on your account, not a platform constant.