Plans, Ads, Fleet & Data
Plans, Ads, Fleet & Data
Most maps platforms were built for North America and Europe, priced in dollars or euros, and billed through gateways that barely work in the Middle East. Navvo is built the other way around. It is a MENA-native platform: its data is curated for Jordan and the wider Gulf, its currencies are local, and its commercial surfaces — API plans, consumer subscriptions, promoted placements, fleet logistics, and data licensing — are designed for businesses that operate, invoice, and get paid in the region.
This page documents the commercial layer that sits on top of the maps APIs:
- API plans & usage metering — the public plan catalog, regional pricing, and how every request is weighted and counted.
- Consumer entitlements — Navvo Plus feature gating for end users (offline maps, advanced Atlas, hazard alerts).
- Ads / promoted placements — sponsored pins, sponsored search results, and a sponsored Atlas card, with click-based billing.
- Business — claim a place, run campaigns, generate AI marketing copy, curate entrances, and render business markers on a map.
- Fleet / last-mile — fleets, drivers, delivery tasks with cash-on-delivery, route optimization, and proof-of-delivery.
- Data licensing — de-identified GeoJSON exports for licensed partners, plus the affiliate redirect.
-H "x-api-key: nvvo_YOUR_KEY". Endpoints that act on a specific person's account or assets — consumer entitlements and the entire fleet group — require a user JWT as -H "Authorization: Bearer USER_JWT" instead, and this is called out per endpoint. Data-licensing endpoints are admin-gated. The base URL is https://navvo.io/api/v1.JOD, SAR, or AED. The Jordanian dinar is subdivided into 1000 fils, so divide monthlyPriceMinor (and any *Minor field) by 1000 to get the JOD amount: 29000 minor = 29.000 JOD. The Saudi riyal and UAE dirham are subdivided into 100, so for SAR/AED divide by 100. Always read the currency field before formatting.GET /billing/plans
Returns the public API plan catalog — every plan a developer can subscribe to, with its regional price, included request quota, overage rate, rate limits, and feature list. This endpoint is safe to render directly on a pricing page.
curl -s "https://navvo.io/api/v1/billing/plans" \
-H "x-api-key: nvvo_YOUR_KEY"
Response
{
"provider": "navvo-billing",
"currency": "JOD",
"plans": [
{
"key": "free",
"name": "Free",
"tagline": "For prototypes and side projects",
"currency": "JOD",
"monthlyPriceMinor": 0,
"includedRequests": 50000,
"overagePerThousandMinor": 0,
"rateLimitPerMin": 60,
"rateLimitPerDay": 5000,
"features": ["search", "geocoding", "places", "map-tiles"]
},
{
"key": "starter",
"name": "Starter",
"tagline": "For early-stage products going live",
"currency": "JOD",
"monthlyPriceMinor": 29000,
"includedRequests": 500000,
"overagePerThousandMinor": 400,
"rateLimitPerMin": 300,
"rateLimitPerDay": 100000,
"features": ["search", "geocoding", "places", "map-tiles", "routing", "traffic"]
},
{
"key": "growth",
"name": "Growth",
"tagline": "For scaling teams with real traffic",
"currency": "JOD",
"monthlyPriceMinor": 149000,
"includedRequests": 5000000,
"overagePerThousandMinor": 250,
"rateLimitPerMin": 1200,
"rateLimitPerDay": 1000000,
"features": ["search", "geocoding", "places", "map-tiles", "routing", "traffic", "matrix", "fleet", "imagery"]
},
{
"key": "enterprise",
"name": "Enterprise",
"tagline": "Custom volume, SLA, and data licensing",
"currency": "JOD",
"monthlyPriceMinor": null,
"includedRequests": null,
"overagePerThousandMinor": null,
"rateLimitPerMin": null,
"rateLimitPerDay": null,
"features": ["all", "data-licensing", "priority-support", "dedicated-tiles"]
}
]
}
| Field | Type | Description |
|---|---|---|
provider | string | Always "navvo-billing". |
currency | string | The catalog's billing currency for this account — a MENA currency: "JOD", "SAR", or "AED". |
plans[].key | string | Stable machine identifier for the plan (free, starter, growth, enterprise). Use this when subscribing. |
plans[].name | string | Display name. |
plans[].tagline | string | One-line marketing description. |
plans[].currency | string | The plan's currency (matches the catalog currency). |
plans[].monthlyPriceMinor | number | null | Monthly price in minor units of currency (divide by 1000 for JOD; by 100 for SAR/AED). 0 for free plans, null for "contact us" enterprise plans. |
plans[].includedRequests | number | null | Weighted requests included each month before overage applies. null means custom/unlimited. |
plans[].overagePerThousandMinor | number | null | Price per 1,000 additional weighted requests beyond includedRequests, in minor units. 0 when overage is not billed; null for custom plans. |
plans[].rateLimitPerMin | number | null | Maximum weighted requests per minute. null for custom limits. |
plans[].rateLimitPerDay | number | null | Maximum weighted requests per day. null for custom limits. |
plans[].features | string | API feature families unlocked by the plan (maps to scopes such as routing, traffic, matrix, fleet). |
includedRequests quota and any overage are measured in these weighted requests, so two accounts sending the same number of HTTP calls can consume their quota at very different rates depending on which endpoints they hit.currency and the matching monthlyPriceMinor, then divide by the currency's minor-unit factor (1000 for JOD, 100 for SAR/AED). Treat null prices as an "Contact sales" call-to-action rather than a free plan.GET /me/entitlements
Returns the consumer entitlements for the signed-in Navvo user — which premium features they have unlocked, whether they hold a Navvo Plus subscription, and their active subscription records. Use this to gate end-user features in your own app: offline map downloads, advanced Atlas AI, hazard alerts, and similar.
Requires a user JWT (not an API key). Pass the user's session token as a Bearer token.
curl -s "https://navvo.io/api/v1/me/entitlements" \
-H "Authorization: Bearer USER_JWT"
Response
{
"provider": "navvo-entitlements",
"entitlements": [
"navvo_plus",
"offline_maps",
"atlas_advanced",
"hazard_alerts"
],
"plus": true,
"subscriptions": [
{
"id": "sub_9f3a21",
"product": "navvo_plus",
"status": "active",
"currency": "JOD",
"priceMinor": 3500,
"interval": "month",
"renewsAt": "2026-07-19T00:00:00Z"
}
]
}
| Field | Type | Description |
|---|---|---|
provider | string | Always "navvo-entitlements". |
entitlements | string | Feature keys the user has unlocked. Check membership before enabling a gated feature. Common keys: navvo_plus, offline_maps, atlas_advanced, hazard_alerts. |
plus | boolean | Convenience flag — true when the user holds an active Navvo Plus subscription (equivalent to entitlements containing navvo_plus). |
subscriptions[] | array | Active subscription records: id, product, status, currency, priceMinor (minor units), interval (month | year), and renewsAt. |
navvo_plus entitlement is the master key for consumer premium features. When present, it unlocks offline maps (downloadable map regions for use without a connection), advanced Atlas (the higher-capability Atlas AI assistant), and hazard alerts (proactive road-hazard and incident notifications). Gate your UI on the specific entitlement key rather than on plus alone, so individually-granted features (trials, partner bundles) still work.GET /ads/promoted
Returns sponsored map pins inside a viewport — "promoted" places that an advertiser is paying to surface. Render these alongside organic search results, visually marked as sponsored. Billing is CPC (cost-per-click): impressions are free; you are billed when a user clicks (see POST /ads/{id}/click).
curl -s "https://navvo.io/api/v1/ads/promoted?bbox=35.85,31.90,36.00,32.00&categories=restaurant,cafe" \
-H "x-api-key: nvvo_YOUR_KEY"
Query parameters
west,south,east,north (longitude/latitude in decimal degrees). Only promoted pins inside this box are returned.restaurant,cafe,fuel). When set, only ads in these categories are returned. Omit for all categories.Response
{
"provider": "navvo-ads",
"type": "promoted_pin",
"count": 1,
"ads": [
{
"id": "ad_promo_8821",
"type": "promoted_pin",
"placeId": "plc_amman_cafe_4410",
"title": "Rumi Café — Abdali",
"subtitle": "Specialty coffee · Open now",
"imageUrl": "https://navvo.io/ads/img/ad_promo_8821.jpg",
"ctaUrl": "https://navvo.io/go?ref=RUMI-ABDALI",
"lat": 31.9568,
"lng": 35.9098,
"sponsored": true
}
]
}
| Field | Type | Description |
|---|---|---|
provider | string | Always "navvo-ads". |
type | string | Always "promoted_pin" for this endpoint. |
count | number | Number of ads returned. |
ads[].id | string | Ad identifier. Pass to POST /ads/{id}/click when the user taps the pin or its CTA. |
ads[].type | string | "promoted_pin". |
ads[].placeId | string | The Navvo place the ad promotes — resolve via the Places API for full details. |
ads[].title / subtitle | string | Display text for the pin card. |
ads[].imageUrl | string | Creative/thumbnail image URL. |
ads[].ctaUrl | string | Destination URL for the call-to-action. Open this only after recording the click. |
ads[].lat / lng | number | Pin coordinates. |
ads[].sponsored | boolean | Always true. You must visually mark these as sponsored. |
GET /ads/sponsored-search
Returns sponsored results to blend into a search results list for a given query. Same ad shape as promoted pins but typed sponsored_search. Display clearly labelled as sponsored, typically at the top of organic results.
curl -s "https://navvo.io/api/v1/ads/sponsored-search?q=coffee" \
-H "x-api-key: nvvo_YOUR_KEY"
Query parameters
Response
{
"provider": "navvo-ads",
"type": "sponsored_search",
"count": 1,
"ads": [
{
"id": "ad_search_5530",
"type": "sponsored_search",
"placeId": "plc_amman_cafe_4410",
"title": "Rumi Café",
"subtitle": "Sponsored · Specialty coffee in Abdali",
"imageUrl": "https://navvo.io/ads/img/ad_search_5530.jpg",
"ctaUrl": "https://navvo.io/go?ref=RUMI-SEARCH",
"lat": 31.9568,
"lng": 35.9098,
"sponsored": true
}
]
}
The ads[] objects use the same fields as GET /ads/promoted, with type set to "sponsored_search".
GET /ads/atlas-card
Returns at most one sponsored card to surface inside the Atlas AI assistant for a given query — a single, contextually-relevant promotion shown as a rich card in a conversational result. Typed atlas_card. Returns ad: null when no suitable sponsor matches the query.
curl -s "https://navvo.io/api/v1/ads/atlas-card?q=where%20can%20I%20get%20coffee%20nearby" \
-H "x-api-key: nvvo_YOUR_KEY"
Query parameters
Response
{
"provider": "navvo-ads",
"type": "atlas_card",
"ad": {
"id": "ad_atlas_2207",
"type": "atlas_card",
"placeId": "plc_amman_cafe_4410",
"title": "Rumi Café",
"subtitle": "Specialty coffee · 400 m away · Open now",
"imageUrl": "https://navvo.io/ads/img/ad_atlas_2207.jpg",
"ctaUrl": "https://navvo.io/go?ref=RUMI-ATLAS",
"lat": 31.9568,
"lng": 35.9098,
"sponsored": true
}
}
| Field | Type | Description |
|---|---|---|
provider | string | Always "navvo-ads". |
type | string | Always "atlas_card". |
ad | object | null | A single ad object (same fields as GET /ads/promoted), or null when no sponsor matches. |
ad is non-null, and keep the sponsored label visible. Treat a null card as the normal case, not an error.POST /ads/{id}/click
Records a billable click on an ad and returns the destination URL to navigate to. This is the moment you are charged under the CPC model — call it exactly once when the user actively taps the ad or its call-to-action, then open the returned ctaUrl.
curl -s -X POST "https://navvo.io/api/v1/ads/ad_promo_8821/click" \
-H "x-api-key: nvvo_YOUR_KEY"
Path parameters
ads[].id from any of the ad endpoints above.Response
{
"ok": true,
"ctaUrl": "https://navvo.io/go?ref=RUMI-ABDALI",
"chargedMinor": 180
}
| Field | Type | Description |
|---|---|---|
ok | boolean | true when the click was recorded. |
ctaUrl | string | The destination to open after recording the click — usually a Navvo affiliate redirect (/go?ref=…). |
chargedMinor | number | The CPC actually billed for this click (minor units). For an auto-bidding ad this is the effective bid at click time, not the base bid. |
Smart auto-bidding
By default an ad bids its fixed bidMinor CPC. Opt an ad into auto-bidding and Navvo sets the bid dynamically to spend the daily budget evenly and win impressions where they're worth most. Enable it by adding an autoBid object to the ad's targeting:
{ "targeting": { "categories": ["restaurant"], "autoBid": { "enabled": true, "maxBidMinor": 250 } } }
| Field | Type | Notes |
|---|---|---|
enabled | boolean | turn auto-bidding on for this ad |
maxBidMinor | number | optional ceiling on the effective CPC (defaults to 3× the base bid) |
Two mechanics drive it:
- Budget pacing — the effective bid scales by how far spend is behind or ahead of an even daily pace. Behind schedule → bid up (to 3×) to catch up; ahead → bid down (to 0.25×) so the budget lasts the day. It never bids more than the budget remaining.
- eCPM ranking — ads compete on expected revenue per impression = effective bid × predicted click-through (a Laplace-smoothed CTR with a 5% prior). A new ad ranks on its bid; as it earns clicks, a proven performer wins better placement at the same or lower bid.
POST /ads/{id}/click then charges the effective bid (returned as chargedMinor).
GET /admin/ads/{id}/bid · admin
Transparency for an auto-bidding ad — the live bid breakdown. Admin-gated.
{
"ok": true, "id": "ad_promo_8821",
"autoBid": { "enabled": true, "maxBidMinor": 250 },
"baseBidMinor": 100, "pacingMultiplier": 1.8, "pCtr": 0.05,
"effectiveBidMinor": 180, "auctionScore": 9.0, "remainingBudgetMinor": 9000
}
Business
The Business API is how a company takes control of its presence on the Navvo map: claim the place record and — once the claim is verified — run campaigns, generate AI marketing copy, and curate the place's entrances for arrival intelligence. There is also a public markers feed for rendering business pins on any map surface.
/business/claims, /business/campaigns, /business/ai-copy, adding entrances) require a user JWT — -H "Authorization: Bearer USER_JWT". The two reads meant for map rendering — GET /business/markers and GET /places/{slug}/entrances — are public and authenticate with your API key like any other read.POST /business/claims
Submit a claim of ownership over a place. Any signed-in user can file a claim; a Navvo moderator reviews the evidence, and once it is approved your account becomes the place's verified owner, which unlocks the owner-scoped endpoints below.
curl -s -X POST "https://navvo.io/api/v1/business/claims" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"placeId": "plc_amman_cafe_4410",
"evidence": "Trade license 445871, registered to Rumi Cafe LLC",
"evidenceType": "trade_license",
"evidenceUrls": { "license": "https://example.com/license.pdf" }
}'
Body
| Field | Type | Description |
|---|---|---|
placeId | string, required | The place being claimed (the id from Places or GET /business/markers). |
evidence | string | Free-text supporting statement. |
evidenceType | string | One of trade_license, domain_email, phone, document, other (default other). |
evidenceUrls | object | Links to uploaded evidence documents, keyed however you like. |
Response
{
"id": "clm_1f2e3d",
"placeId": "plc_amman_cafe_4410",
"status": "pending",
"evidenceType": "trade_license",
"createdAt": "2026-07-02T09:30:00Z"
}
Claims start as pending and the place is flagged as claim-pending on the map. Track progress with GET /business/claims.
GET /business/claims
Your own claims, newest first (user JWT). Returns { total, items[] }; each item carries its status (pending → approved / rejected) plus reviewedAt and reviewNotes once a moderator has ruled.
curl -s "https://navvo.io/api/v1/business/claims" \
-H "Authorization: Bearer USER_JWT"
Related: GET /business/owned-places (user JWT) returns the full place records for every place where your ownership is verified — the set of places the endpoints below can act on.
POST /business/campaigns
Create a promotion campaign for a place you own (verified owner or admin). Campaigns are created as draft; a draft becomes a live ad placement (promoted pin, sponsored search, Atlas card) once it is activated and funded.
curl -s -X POST "https://navvo.io/api/v1/business/campaigns" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"placeId": "plc_amman_cafe_4410",
"name": "Summer iced-coffee push",
"targeting": { "categories": ["cafe"], "autoBid": { "enabled": true, "maxBidMinor": 250 } }
}'
Response
{
"id": "cmp_77aa",
"placeId": "plc_amman_cafe_4410",
"name": "Summer iced-coffee push",
"status": "draft",
"targeting": { "categories": ["cafe"], "autoBid": { "enabled": true, "maxBidMinor": 250 } },
"createdAt": "2026-07-02T09:31:00Z"
}
| Field | Type | Description |
|---|---|---|
placeId | string, required | A place you own. Non-owners get 403. |
name | string, required | Campaign display name. |
targeting | object | Ad targeting — same shape as the ads targeting object (categories, autoBid, …). |
GET /business/campaigns
List campaigns (user JWT, scoped to places you own; admins see all). Filter with ?placeId=.
curl -s "https://navvo.io/api/v1/business/campaigns?placeId=plc_amman_cafe_4410" \
-H "Authorization: Bearer USER_JWT"
Returns { total, items[] } of campaign objects (as in POST /business/campaigns), newest first.
POST /business/ai-copy
Generate concise, production-safe Arabic + English marketing copy and tags for a place you own (verified owner or admin). Pass a free-form context object describing what to write about — highlights, offers, tone, audience.
curl -s -X POST "https://navvo.io/api/v1/business/ai-copy" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"placeId": "plc_amman_cafe_4410",
"context": { "highlights": ["specialty coffee", "rooftop seating"], "tone": "warm", "offer": "10% off before 10am" }
}'
Response
{
"model": "navvo-copywriter",
"unavailable": false,
"purpose": "business_copy",
"content": "EN: Rooftop specialty coffee in the heart of Abdali — 10% off before 10am.\nAR: قهوة مختصة على السطح في قلب العبدلي — خصم ١٠٪ قبل العاشرة صباحًا."
}
201 even when the AI backend is down. Always check unavailable before using content — when true, content is empty and you should retry later.GET /business/markers
Public, zoom-adaptive business-pin feed for map rendering — sponsored places first, then by rating. Returns each place's canonical category plus its admin-configured categoryStyle (color, icon, pin shape) so pins render consistently with the Navvo map.
curl -s "https://navvo.io/api/v1/business/markers?bbox=35.85,31.90,36.00,32.00&zoom=14&category=restaurants" \
-H "x-api-key: nvvo_YOUR_KEY"
Query parameters
west,south,east,north. Omit for no spatial filter.restaurants, fuel). Aliases are canonicalized.verified for claimed businesses only.Response
{
"limit": 60,
"zoom": 14,
"category": "restaurants",
"categoryFiltered": true,
"performance": {
"requestedLimit": null, "limit": 60, "zoom": 14,
"candidateCount": 118, "returnedCount": 60,
"serverCapped": false, "resultCapped": true, "capReason": "zoom-limit"
},
"items": [
{
"id": "745cd311-887e-40ed-989d-94f7cb4d8f51",
"slug": "rumi-cafe-abdali-4410",
"nameEn": "Rumi Café",
"nameAr": "مقهى الرومي",
"canonicalCategorySlug": "restaurants",
"categories": ["restaurants"],
"rawCategories": ["Coffee shop"],
"categoryStyle": {
"source": "admin_map_categories",
"slug": "restaurants",
"color": "#F97316",
"iconName": "pin",
"pinStyle": "circle",
"zoomRange": { "min": 12, "max": 20 },
"visibility": { "map": true, "nearby": true, "searchFilters": true }
},
"claimStatus": "verified",
"sponsored": true,
"rating": 4.6,
"lng": 35.9098,
"lat": 31.9568
}
]
}
| Field | Type | Description |
|---|---|---|
performance | object | Cap diagnostics — candidateCount vs returnedCount, whether the result was serverCapped/resultCapped, and why (capReason). |
items[].canonicalCategorySlug | string | The place's canonical Navvo category (raw import categories are mapped/inferred onto the admin taxonomy). |
items[].categoryStyle | object | null | Admin-configured pin styling for the category: color, iconName, pinStyle, valid zoomRange, and surface visibility. |
items[].claimStatus | string | unclaimed, pending, or verified. |
items[].sponsored | boolean | Sponsored places sort first — mark them as such if you badge pins. |
GET /places/{slug}/entrances
Public — list a place's approved entrances (the same records that power arrivalIntelligence on GET /places/{slug}).
curl -s "https://navvo.io/api/v1/places/rumi-cafe-abdali-4410/entrances" \
-H "x-api-key: nvvo_YOUR_KEY"
[
{
"id": "ent_9a01",
"type": "main",
"label": "Main door — Rainbow St side",
"notes": "Step-free. Parking entrance is 40 m further east.",
"location": "POINT(35.9099 31.9569)"
}
]
POST /places/{slug}/entrances
Add an entrance to a place — verified owner of the place, or admin. Submitted entrances go through moderation review before they appear publicly and in arrival intelligence, so a new entrance is not returned by the public reads immediately. (Entrance submission was previously open to any signed-in user; it is now owner/admin-gated with moderation.)
curl -s -X POST "https://navvo.io/api/v1/places/rumi-cafe-abdali-4410/entrances" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"type": "parking",
"label": "Parking garage entrance",
"notes": "Height limit 2.1 m",
"lat": 31.9571,
"lng": 35.9103
}'
| Field | Type | Description |
|---|---|---|
type | string, required | Entrance kind — e.g. main, parking, delivery, accessible. |
label | string | Short display label. |
notes | string | Last-meters guidance shown to arriving users. |
lat / lng | number, required | Entrance coordinates. |
GET /places/{slug} ranks them into arrivalIntelligence.candidates[], and routing to candidates[0].routeTarget beats routing to the map pin.Fleet / last-mile
The Fleet API turns Navvo into a last-mile delivery platform: organize fleets, assign drivers, dispatch delivery tasks (with cash-on-delivery), optimize the day's stop order, and capture proof of delivery. It is designed for regional courier and on-demand logistics businesses, including the cash-heavy COD flows common across MENA.
All fleet endpoints require a user JWT (the authenticated owner/dispatcher, or — for the driver-facing endpoints — the authenticated driver). Pass it as -H "Authorization: Bearer USER_JWT".
This section is an overview of the group rather than a field-by-field reference for every endpoint.
Fleets & drivers
# List your fleets
curl -s "https://navvo.io/api/v1/fleet" \
-H "Authorization: Bearer USER_JWT"
# Create a fleet
curl -s -X POST "https://navvo.io/api/v1/fleet" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{ "name": "Amman City Couriers", "city": "Amman" }'
| Endpoint | Purpose |
|---|---|
GET /fleet | List the fleets you own. |
POST /fleet | Create a fleet ({ name, city? }). |
GET /fleet/{id}/drivers | List drivers in a fleet. |
POST /fleet/{id}/drivers | Add a driver to a fleet ({ name, phone?, vehicle? }). |
Delivery tasks (with COD)
# Create a delivery task with cash-on-delivery
curl -s -X POST "https://navvo.io/api/v1/fleet/flt_amman_01/tasks" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"address": "Rainbow Street, Amman",
"lat": 31.9515,
"lng": 35.9239,
"recipient": "Layla H.",
"phone": "+962790000000",
"codAmountMinor": 12500,
"codCurrency": "JOD"
}'
| Endpoint | Purpose |
|---|---|
GET /fleet/{id}/tasks | List the delivery tasks of a fleet. |
POST /fleet/{id}/tasks | Create a delivery task. Supports COD fields (below). |
Each task carries delivery details (destination coordinates, recipient, contact) plus optional cash-on-delivery fields:
| Field | Type | Description |
|---|---|---|
codAmountMinor | number | Amount to collect on delivery, in minor units (e.g. 12500 = 12.500 JOD). Omit or 0 for prepaid orders. |
codCurrency | string | Currency of the COD amount — a MENA currency (JOD / SAR / AED). |
codCollected | boolean | Whether the driver has collected the cash (set on status update). |
proofUrl | string | URL of proof-of-delivery evidence (signature/photo) captured at completion. |
Route optimization
# Order a driver's pending stops by nearest-neighbour from a start point
curl -s -X POST "https://navvo.io/api/v1/fleet/flt_amman_01/optimize" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{ "start": { "lat": 31.9539, "lng": 35.9106 }, "driverId": "drv_77" }'
POST /fleet/{id}/optimize takes a start point and an optional driverId, and returns the fleet's pending tasks reordered into an efficient nearest-neighbour route (each next stop is the closest remaining one). Omit driverId to optimize across all unassigned tasks in the fleet.
Driver-facing endpoints
These are called by the driver's app, authenticated as the driver:
| Endpoint | Purpose |
|---|---|
GET /fleet/me/tasks | The signed-in driver's assigned tasks for the day. |
PATCH /fleet/tasks/{taskId}/status | Update a task's status ({ status, codCollected?, proofUrl? }) — e.g. mark delivered, record that COD cash was collected, and attach proof-of-delivery. |
POST /fleet/drivers/{driverId}/ping | Report the driver's live location ({ lat, lng }) for tracking and ETA. |
# Driver marks a task delivered, COD collected, with proof
curl -s -X PATCH "https://navvo.io/api/v1/fleet/tasks/tsk_5521/status" \
-H "Authorization: Bearer USER_JWT" \
-H "Content-Type: application/json" \
-d '{ "status": "delivered", "codCollected": true, "proofUrl": "https://navvo.io/pod/tsk_5521.jpg" }'
codAmountMinor / codCurrency), and on completion set codCollected: true and attach proofUrl so the collected cash and the delivery are reconciled together.COD reconciliation
| Endpoint | Purpose |
|---|---|
GET /fleet/{id}/cod-reconciliation | Per-driver cash accounting for a fleet (owner). |
GET /admin/fleet/cod-reconciliation?fleetId= | Same report, admin-gated. |
The end-of-day cash report every COD operation needs — it groups the fleet's COD tasks by driver and tells you, per driver and in total, how much cash has been collected, how much is still outstanding (out for delivery), and — critically — any discrepancy: parcels marked delivered where codCollected was never set, i.e. cash that should have been handed in but wasn't recorded. Failed/returned COD parcels are tracked separately (no cash expected).
curl -s "https://navvo.io/api/v1/fleet/flt_amman_01/cod-reconciliation" \
-H "Authorization: Bearer USER_JWT"
{
"provider": "navvo-fleet", "fleetId": "flt_amman_01", "currency": "JOD",
"totals": { "collectedMinor": 142500, "outstandingMinor": 38000, "discrepancyMinor": 5000, "failedMinor": 9000, "codTasks": 37 },
"drivers": [
{ "driverId": "drv_12", "name": "Sami",
"collectedMinor": 100000, "outstandingMinor": 7000, "discrepancyMinor": 5000, "failedMinor": 0,
"collectedCount": 8, "outstandingCount": 1, "discrepancyCount": 1 }
]
}
A non-zero discrepancyMinor is the figure to investigate — it's delivered cash that hasn't been reconciled to a driver. All amounts are in minor units of currency.
Driver performance leaderboard
| Endpoint | Purpose |
|---|---|
GET /fleet/{id}/driver-performance | Rank a fleet's drivers (owner). |
GET /admin/fleet/driver-performance?fleetId= | Same, admin-gated. |
Ranks drivers by a composite of delivery volume × completion reliability (score = delivered × successRate × 100), with average delivery time and COD reliability alongside — so a high-volume driver with good (not perfect) reliability outranks a low-volume perfect one.
{
"provider": "navvo-fleet", "fleetId": "flt_amman_01", "driverCount": 3,
"drivers": [
{ "rank": 1, "driverId": "drv_2", "name": "Lina", "status": "online",
"delivered": 6, "failed": 2, "canceled": 0, "active": 1,
"successRate": 0.75, "avgDeliveryMinutes": 30, "codReliability": 1, "score": 450 },
{ "rank": 2, "driverId": "drv_1", "name": "Sami",
"delivered": 4, "failed": 0, "successRate": 1, "avgDeliveryMinutes": 20, "score": 400 }
]
}
| Field | Notes |
|---|---|
successRate | delivered / (delivered + failed + canceled) |
avgDeliveryMinutes | mean assignedAt → deliveredAt, capped at 24 h (null if unknown) |
codReliability | share of the driver's COD parcels with cash properly recorded (null if no COD) |
score | the ranking metric — delivery volume weighted by completion reliability |
Data licensing (partner / admin)
Licensed partners can pull de-identified, aggregated GeoJSON from Navvo's regional datasets — for analytics, research, or to enrich their own products — under a data-licensing agreement. These endpoints are admin-gated: they are not available with a standard developer API key and are provisioned for licensed partner accounts.
| Endpoint | Purpose |
|---|---|
GET /admin/data-licensing/datasets | List the datasets available to license (each with a key, name, and row count) plus the supported export formats. |
GET /admin/data-licensing/export?dataset=…&format=…&bbox=… | Export a dataset in the chosen format for an optional viewport. |
Datasets (dataset=): signs (road signs / points), incidents (de-identified active incidents), places (public POI directory — name, category, coordinates).
Formats (format=, default geojson):
| Format | Content-Type | Use |
|---|---|---|
geojson | application/geo+json | a standard FeatureCollection (default; returned inline) |
ndjson | application/x-ndjson | one GeoJSON Feature per line — stream / big-data friendly |
csv | text/csv | flat lng,lat,… columns for spreadsheets / pandas |
sql | application/sql | a portable CREATE TABLE + INSERT dump to load straight into a warehouse |
ndjson/csv/sql download as a file (Content-Disposition); values are correctly escaped (CSV quoting, SQL single-quote doubling).
# List licensable datasets + formats (admin-gated)
curl -s "https://navvo.io/api/v1/admin/data-licensing/datasets" \
-H "x-api-key: nvvo_YOUR_KEY"
# Export road-sign points as SQL for a viewport
curl -s "https://navvo.io/api/v1/admin/data-licensing/export?dataset=signs&format=sql&bbox=35.85,31.90,36.00,32.00" \
-H "x-api-key: nvvo_YOUR_KEY"
All exports are de-identified — incident reports are aggregated and anonymized, and no reporter identity is ever included.
GET /admin/privacy/density · differential privacy
A privacy-safe density heatmap — where activity clusters, released under formal differential privacy (calibrated Laplace noise) with k-anonymity suppression (cells below the threshold are dropped, never published) and grid-snapping (points are snapped to a tile-grid cell, never exact coordinates). Every release is logged to an epsilon-spend ledger. Admin-gated.
| Query | Type | Notes |
|---|---|---|
source | string | feedback (privacy-critical user reports) or signs (public points) |
epsilon | number | privacy budget — lower = more noise / more private (default 1.0) |
minCount | number | k-anonymity threshold; cells with fewer true points are suppressed (default 5) |
zoom | number | grid resolution 8–16 (default 13) |
bbox | string | optional west,south,east,north |
curl -s "https://navvo.io/api/v1/admin/privacy/density?source=signs&epsilon=1&minCount=5&zoom=13" \
-H "x-api-key: nvvo_YOUR_KEY"
{
"provider": "navvo-privacy", "type": "FeatureCollection", "source": "signs",
"epsilon": 1, "minCount": 5, "gridZoom": 13, "pointsSampled": 412, "cells": 23,
"features": [
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [35.925, 31.933] }, "properties": { "count": 19 } }
]
}
Counts are noised, so they're approximate by design; cells you don't see were suppressed for privacy. This is the safe way to publish "busy areas" without exposing any individual's location.
Affiliate redirect
curl -s -i "https://navvo.io/api/v1/go?ref=RUMI-ABDALI"
GET /go?ref=CODE is the affiliate / attribution redirect used by ad ctaUrls and partner links. It records the referral against the ref code and issues an HTTP redirect to the destination, so clicks can be attributed and (for ads) billed. You normally do not build these URLs by hand — open the ctaUrl returned by POST /ads/{id}/click.
Errors
| Status | When |
|---|---|
400 | Validation — e.g. malformed bbox, missing q, an unknown dataset, or invalid fleet/task body. |
401 | Missing or invalid credentials — no API key on a key-gated endpoint, or no/expired user JWT on a JWT-gated endpoint (entitlements, fleet). |
403 | Authenticated but not allowed — e.g. the key lacks the plan/scope, a non-owner acting on a fleet, a user without verified business ownership creating a campaign / AI copy / entrance, or a non-admin hitting a data-licensing endpoint. |
404 | Unknown ad id, fleet id, or taskId. |
Summary
| Endpoint | Auth | Returns |
|---|---|---|
GET /billing/plans | API key | { provider, currency, plans[] } |
GET /me/entitlements | User JWT | { provider, entitlements[], plus, subscriptions[] } |
GET /ads/promoted | API key | { provider, type:"promoted_pin", count, ads[] } |
GET /ads/sponsored-search | API key | { provider, type:"sponsored_search", count, ads[] } |
GET /ads/atlas-card | API key | { provider, type:"atlas_card", ad } |
POST /ads/{id}/click | API key | { ok, ctaUrl } |
POST /business/claims | User JWT | Created claim (status: "pending") |
GET /business/claims | User JWT | { total, items[] } — your claims |
GET /business/owned-places | User JWT (owner) | { total, items[] } — your verified places |
POST /business/campaigns | User JWT (owner/admin) | Created campaign (status: "draft") |
GET /business/campaigns | User JWT (owner-scoped) | { total, items[] } |
POST /business/ai-copy | User JWT (owner/admin) | { model, unavailable, purpose, content } |
GET /business/markers | API key | { limit, zoom, category, performance, items[] } |
GET /places/{slug}/entrances | API key | Approved entrances [] |
POST /places/{slug}/entrances | User JWT (owner/admin) | Created entrance (moderated before public) |
GET /fleet · POST /fleet | User JWT | Fleets you own / created fleet |
GET·POST /fleet/{id}/drivers | User JWT | Drivers / created driver |
GET·POST /fleet/{id}/tasks | User JWT | Tasks / created task (COD fields) |
POST /fleet/{id}/optimize | User JWT | Nearest-neighbour ordered route |
GET /fleet/me/tasks | User JWT (driver) | The driver's tasks |
PATCH /fleet/tasks/{taskId}/status | User JWT (driver) | Updated task (codCollected?, proofUrl?) |
POST /fleet/drivers/{driverId}/ping | User JWT (driver) | Recorded live location |
GET /admin/data-licensing/datasets | Admin | Licensable datasets |
GET /admin/data-licensing/export | Admin | De-identified GeoJSON FeatureCollection |
GET /go?ref=CODE | API key | HTTP redirect to destination (records referral) |
Itinerary, Geofencing & Static Maps
Multi-stop trip optimization, location geofences with webhooks, and embeddable static map images.
Traffic Intelligence & Feedback
Historical traffic profiles, congestion labels, departure timing, area insights, privacy-safe popularity, change analytics, and in-app feedback.