Errors
The RFC 9457 problem+json envelope and the complete, stable error-code registry.
Every 4xx and 5xx response uses the same machine-readable shape: RFC 9457 problem+json. You branch on one stable field — code — and never have to parse prose.
The envelope
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json{
"type": "https://www.fuelatlas.com/developers/guides/errors#insufficient_scope",
"title": "Key lacks required scope",
"status": 403,
"code": "insufficient_scope",
"detail": "This key does not hold the 'guidance:manage' scope.",
"hint": "Request a key with the required scope from the Developer Console, or use GET /v1/me to see current scopes.",
"request_id": "req_9f2c…"
}| Field | Use it for |
|---|---|
code | Branch on this. A stable, documented string — the contract. |
status | The HTTP status (also on the response line). |
title | Short, stable human summary of the code. |
detail | Context specific to this occurrence (may name the field/scope/id involved). |
hint | A concrete next step to resolve it. |
type | A URL to this page, anchored at the code (#<code>). |
request_id | Include it when contacting support — it pins the exact request in our logs. |
Validation failures (422 validation_failed) additionally carry an errors array naming each offending field:
{
"code": "validation_failed",
"status": 422,
"errors": [
{ "field": "destination.latitude", "message": "is required" },
{ "field": "min_arrival_fuel_percent", "message": "must be between 0 and 100" }
]
}Handling errors well
- Switch on
code, notstatus. Several codes share a status (three different429s, for instance) and need different handling. - Retry only what's retryable.
503/504and429 rate_limitedare transient — back off and retry.4xxvalidation, scope, and not-found errors won't fix themselves on retry. - Surface
hintto your operators. It's written to be actionable. - Log
request_id. It's the fastest way for support to find your request.
Error-code registry
Every code the API can return is listed below, grouped by category. Each entry is anchored (#<code>), and the type URL in any error response points straight here. This registry is generated from the API's source of truth, so it's always complete and current.
Authentication & authorization
missing_api_keyHTTP 401API key missing
Send your API key in the Authorization header: 'Authorization: Bearer fa_live_...'.
invalid_api_keyHTTP 401API key invalid
Double-check the key value; generate a new one in the Developer Console if needed.
key_revokedHTTP 401API key revoked
This key was revoked. Generate a new key in the Developer Console.
key_suspendedHTTP 403API key suspended
This key is suspended, typically for a billing or abuse issue. Contact support.
sandbox_key_on_productionHTTP 403Sandbox key used against production
Use a production key against the production API, or call the sandbox base URL with this key.
insufficient_scopeHTTP 403Key lacks required scope
Request a key with the required scope from the Developer Console, or use GET /v1/me to see current scopes.
fleet_header_requiredHTTP 400FA-Fleet header required
Partner keys must select the acting fleet via the 'FA-Fleet: flt_...' header.
fleet_scope_mismatchHTTP 403Fleet does not match key scope
The 'FA-Fleet' header does not match a fleet this key is authorized for.
Validation
validation_failedHTTP 422Request body failed validation
Fix the fields listed in 'errors' and retry.
invalid_cursorHTTP 400Pagination cursor invalid or expired
Restart pagination from the first page (omit the cursor param).
invalid_public_idHTTP 400Public id has the wrong type prefix or is malformed
Check the id's prefix matches the expected resource type (e.g. 'veh_' for vehicles).
batch_too_largeHTTP 413Batch request exceeds the item or size limit
Split the request into smaller batches within the documented limit.
resource_conflictHTTP 409Resource conflicts with an existing one
A concurrent request created a conflicting resource (e.g. a duplicate external_ref); re-read the current state and retry if appropriate.
Idempotency
idempotency_key_requiredHTTP 400Idempotency-Key header required
Send a unique 'Idempotency-Key' header (max 64 chars) with this request.
idempotency_key_reuseHTTP 422Idempotency key reused with a different request body
Use a new Idempotency-Key for a different request, or resend the exact same body to replay the original response.
idempotency_conflictHTTP 409A request with this idempotency key is already in flight
Wait for the in-flight request to complete, then retry with the same key to get its result.
Rate limits & abuse
rate_limitedHTTP 429Rate limit exceeded
Slow down and retry after the duration in 'retry_after' / the RateLimit-Reset header.
quota_exceededHTTP 429Monthly quota exceeded
Wait for the quota to reset, or upgrade your plan in the Developer Console.
station_budget_exceededHTTP 429Station-query budget exceeded for this plan
Reduce station query volume, or upgrade your plan for a higher station-query budget.
enumeration_suspectedHTTP 403Request pattern flagged as station-data enumeration
Reduce the breadth/frequency of station queries; contact support if this was legitimate use.
Not found
resource_not_foundHTTP 404Resource not found
Verify the id and that it belongs to the authenticated fleet.
no_active_guidanceHTTP 404No active guidance session for this vehicle
Start one with POST /v1/vehicles/{id}/guidance.
unknown_vehicleHTTP 404No matching vehicle found
Create the vehicle first with POST /v1/vehicles, or check the id/external_ref.
Resource state
invalid_trip_stateHTTP 409Trip is not in a state that allows this transition
Check the trip's current status and only call transitions valid from that state.
trip_not_editableHTTP 409Trip can no longer be edited
Only 'planned' trips can be edited; use the lifecycle endpoints once a trip is active.
fuel_stop_immutableHTTP 422Fuel stops are system-managed and cannot be edited directly
Modify non-fuel stops instead, or call POST /v1/trips/{id}/optimize to regenerate fuel stops.
vehicle_inactiveHTTP 409Vehicle is deactivated
Reactivate the vehicle before performing this operation.
event_expiredHTTP 410Webhook event is past its replay window
This event can no longer be fetched or redelivered; rely on your original delivery record.
Routing & computation
route_computation_timeoutHTTP 504Route computation exceeded the time limit
Retry the request; if it repeatedly times out, simplify constraints (fewer stops, shorter route).
route_capacityHTTP 503Routing engine is at capacity
Retry with backoff; this is transient load-shedding, not a request error.
insufficient_fuel_dataHTTP 422Not enough fuel data to compute a projection
Set the vehicle's tank_size_gallons and estimated_mpg via PATCH /v1/vehicles/{id}.
routing_unreachableHTTP 502No drivable route found between the given points
Verify both points are reachable by road; the routing engine could not find a path.
Next
- Rate limits — the three
429codes in detail. - Authentication — resolving
401/403auth codes.