Getting Started
Errors & status codes
HTTP status codes, error response shapes, and the engine availability envelope.
Errors & status codes
Navvo uses conventional HTTP status codes and a consistent error body.
Status codes
| Code | Meaning |
|---|---|
200 OK | Successful GET. |
201 Created | Successful POST (NestJS returns 201 for POST handlers, even when nothing is persisted — e.g. routing). |
400 Bad Request | Invalid or missing parameters / body (validation failure). |
401 Unauthorized | Missing or unknown API key. |
403 Forbidden | Key revoked, missing the required scope, or a rate limit was exceeded. |
404 Not Found | Route does not exist. (Note: some lookups return 200 with a null body instead — see below.) |
502 / 503 | A Navvo dependency (tiles, imagery) is unavailable. |
Error body
Errors use the standard NestJS exception shape:
{
"statusCode": 403,
"message": "API key missing required scopes: routing",
"error": "Forbidden"
}
Validation errors (400) may return message as an array of field-level messages:
{
"statusCode": 400,
"message": ["email must be an email", "password must be longer than or equal to 10 characters"],
"error": "Bad Request"
}
Two behaviors worth knowing
1. The "available" envelope (engine endpoints)
Endpoints backed by a Navvo engine — Geocoding, Routing, and parts of Traffic — do not return a 5xx when the engine is unreachable. Instead they return a normal 200/201 with an available: false (or ok: false) flag and echo your request back:
{
"provider": "navvo",
"available": false,
"path": "route",
"request": { "locations": [ { "lat": 31.95, "lon": 35.91 } ], "costing": "auto" }
}
Always check the
available / ok boolean on engine responses before reading data. A 200 does not guarantee a usable result.2. "Not found" can be 200 null
A few lookup endpoints (notably GET /places/{slug}) return HTTP 200 with a null body when the resource doesn't exist, rather than a 404. Treat an empty/null body as "not found".
Handling errors
const res = await fetch("https://navvo.io/api/v1/search?q=cafe", {
headers: { "x-api-key": key },
});
if (res.status === 401 || res.status === 403) {
// Auth/scope/quota problem — inspect message, don't retry blindly.
const err = await res.json();
throw new Error(`${err.statusCode}: ${err.message}`);
}
if (!res.ok) {
// 400/5xx
throw new Error(`Request failed: ${res.status}`);
}
const data = await res.json();