Authentication
Authentication
Every request to the Navvo integration API is authenticated with an API key. Keys are scoped, rate-limited, and tied to a project inside your organization.
Sending your key
Pass the key on every request using the x-api-key header:
curl "https://navvo.io/api/v1/search?q=pharmacy" \
-H "x-api-key: nvvo_YOUR_KEY"
For URLs that a browser fetches directly and cannot add headers to — most importantly map tiles and styles in Navvo Maps — pass the key as a query parameter instead. Both api_key and apiKey are accepted:
https://navvo.io/api/v1/tiles/style?style=standard&api_key=nvvo_YOUR_KEY
x-api-key so your key doesn't end up in logs or browser history.Key format
Navvo keys are prefixed and easy to recognize:
nvvo_<48 hex characters>
Only a hash of the key is stored server-side, together with the last four characters (for display). The plaintext is returned exactly once, when the key is created.
Scopes
Each key carries a set of scopes. A request to a scoped endpoint succeeds only if the key grants that scope. There are eleven scopes:
| Scope | Grants access to | Enabled by default? |
|---|---|---|
search | Search | ✅ |
geocode | Geocoding (incl. batch) | ✅ |
places | Places — details, hours, photos, reviews, categories, quests | ✅ |
routing | Routing, matrix, isochrone, commute & itinerary | ✅ |
traffic | Traffic & Incidents | ✅ |
telemetry | Telemetry | ✅ |
tiles | Map Tiles & Map Data | ✅ |
imagery | Imagery | ✅ |
geo | Geofencing & addressing / Plus Codes | ❌ (opt-in) |
insights | Navvo Insights privacy-safe aggregates | ❌ (opt-in) |
optimize | Route Optimization (OR-Tools) | ❌ (opt-in) |
New keys are created with eight of the eleven scopes enabled by default. The geo, insights, and optimize scopes are off by default — request them explicitly if your integration needs geofencing, analytics, or optimization.
The live, authoritative list is also available to signed-in developers at GET /developer/scopes (each scope with a label and description).
Obtaining a key
The fastest way to get a key is the Developer Portal at navvo.io/developer — a point-and-click console for organizations, projects, keys, live usage and a request sandbox. Everything below is also available as a REST API if you prefer to automate it.
API keys are created through the developer portal endpoints, which are protected by a user session token (a JWT, not an API key). The flow is: account → organization → project → key. Every organization, project and key is scoped to the user who created it — you only ever see and manage your own.
1. Create an account / sign in
curl -X POST "https://navvo.io/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"name": "Your Name",
"password": "a-strong-password-min-10-chars"
}'
curl -X POST "https://navvo.io/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"password": "a-strong-password-min-10-chars"
}'
Both return an accessToken (a Bearer JWT) plus your user and session:
{
"user": { "id": "uuid", "email": "you@example.com", "name": "Your Name", "roles": ["user"] },
"sessionId": "uuid",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Send this token as Authorization: Bearer <accessToken> on all /developer/* and /auth/me requests.
developer role (or admin/super_admin). A freshly registered account has only the user role — contact Navvo to have the developer role granted to your account.2. Create an organization
curl -X POST "https://navvo.io/api/v1/developer/organizations" \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{ "name": "Acme Logistics", "slug": "acme-logistics" }'
3. Create a project
curl -X POST "https://navvo.io/api/v1/developer/organizations/<orgId>/projects" \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{ "name": "Driver App" }'
4. Create an API key
curl -X POST "https://navvo.io/api/v1/developer/api-keys" \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{
"projectId": "<projectId>",
"label": "Driver App – production",
"plan": "startup",
"scopes": { "geo": true }
}'
The response contains your key in the key field — this is the only time it is shown:
{
"key": "nvvo_3f9c2a1e8b7d6c5f4a3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b",
"id": "uuid",
"label": "Driver App – production",
"lastFour": "9c8b",
"scopes": {
"search": true, "geocode": true, "places": true, "routing": true,
"traffic": true, "telemetry": true, "tiles": true, "imagery": true, "geo": true
},
"plan": "startup",
"quotaPerMinute": 180,
"quotaPerDay": 2500,
"active": true
}
Request body — POST /developer/api-keys
free, startup, growth, enterprise. Defaults to free.{ scope: boolean } map merged over the defaults. Pass { "geo": true } to enable the opt-in scope, or { "telemetry": false } to disable one.180.2500.Managing keys
All of these endpoints require your Authorization: Bearer <accessToken> session token and are scoped to your account.
| Method | Path | Purpose |
|---|---|---|
GET | /developer/overview | Catalog of products, plans, and rate limits. |
GET | /developer/scopes | The authoritative scope catalog (label, description, defaults). |
GET | /developer/summary | Your counts (organizations, projects, keys, active keys) and requests today. |
GET | /developer/organizations | List your organizations. |
POST | /developer/organizations | Create an organization (body: name; slug optional, auto-generated). |
PATCH | /developer/organizations/:id | Rename an organization. |
DELETE | /developer/organizations/:id | Delete an organization (cascades to its projects and keys). |
GET | /developer/projects?organizationId=… | List projects. |
POST | /developer/organizations/:id/projects | Create a project under an organization (body: name). |
POST | /developer/projects | Create a project (flat form — body: name, organizationId). |
PATCH | /developer/projects/:id | Rename a project. |
DELETE | /developer/projects/:id | Delete a project (cascades to its keys). |
GET | /developer/api-keys?projectId=… | List keys. Shows lastFour, scopes, plan, quotas, active, and live usage — never the plaintext. |
POST | /developer/api-keys | Mint a key (see Obtaining a key). Returns the plaintext once. |
GET | /developer/api-keys/:id/usage | Live per-key usage: requests this minute / today vs. quota. |
PATCH | /developer/api-keys/:id | Update a key's label, plan, scopes, quotaPerMinute, quotaPerDay, or active. Scope changes are merged over the key's current scopes. |
POST | /developer/api-keys/:id/rotate | Generate a new secret and invalidate the old one. Returns the new plaintext once. |
DELETE | /developer/api-keys/:id | Permanently delete a key. |
POST | /developer/sandbox | Run a read-only test request as one of your keys, server-side (body: apiKeyId, path, method? GET|POST, body?). Powers the portal Sandbox. |
Disabling vs. deleting
To temporarily turn a key off (and back on), set active:
curl -X PATCH "https://navvo.io/api/v1/developer/api-keys/<keyId>" \
-H "Authorization: Bearer <accessToken>" \
-H "Content-Type: application/json" \
-d '{ "active": false }'
An inactive key is rejected with 403 Forbidden until you re-enable it. DELETE removes the key permanently.
Rotating a key
If a key is leaked or lost, rotate it — this mints a brand-new secret and immediately invalidates the previous one, keeping the same key id, scopes and quotas:
curl -X POST "https://navvo.io/api/v1/developer/api-keys/<keyId>/rotate" \
-H "Authorization: Bearer <accessToken>"
The response includes the new key in plaintext — again, shown only once. Deploy the new secret to your apps; the old one stops working immediately.
Errors
| Status | Meaning |
|---|---|
401 Unauthorized | No key supplied where one is required, or the key you sent is unknown or revoked. |
403 Forbidden | Key missing the required scope, or a quota/rate limit was exceeded. |
401 on every endpoint. Rotating or deactivating a key from the developer portal therefore takes effect immediately.See Errors for response bodies and Rate limits for quota details.