API Reference
Search
Full-text place search across the Middle East, with AI query understanding and sponsored-aware ranking.
Search
Full-text search over Navvo's place database for the Middle East. Combines an AI query-understanding step, Navvo's search index, and the database, then merges, de-duplicates, and ranks results (sponsored-and-relevant first).
Scope required: search
GET /search
Search for places by free-text query.
curl -s "https://navvo.io/api/v1/search?q=coffee%20in%20Abdoun&limit=10" \
-H "x-api-key: nvvo_YOUR_KEY"
Query parameters
q
string required
The search query. Free text — e.g.
coffee in Abdoun, pharmacy near me. Must be non-empty.locale
string
Preferred language,
en (default) or ar. Echoed back on the response.page
number
1-based page number. Defaults to
1.limit
number
Max number of items to return. Defaults to
25.Response
| Field | Type | Description |
|---|---|---|
query | string | Your query, echoed. |
locale | string | Resolved locale. |
understanding | object | AI query-planner output. Answered within a short deadline — on the first occurrence of a query it is usually unavailable (the planner keeps working in the background and is cached for repeats). Search results never wait for it. |
places.items[] | array | The ranked results (see below). Empty when nothing matches — no unrelated filler results. |
places.total | number | Total matching count (0 on a genuine zero-match). |
places.page / places.limit | number | Pagination echo. |
suggestions[] | array | Only present when places.items is empty: popular nearby places you may want to show as a "no results — try these" fallback. Same element shape as places.items[]. |
index | object | Navvo search-index status (provider, configured, available, host). |
Each places.items[] element:
| Field | Type | Description |
|---|---|---|
id | string | Place id. |
slug | string | URL slug (use with GET /places/{slug}). |
nameEn / nameAr | string | Names. |
categories | string | Canonical category slugs (canonical category first). |
canonicalCategorySlug | string | Primary category. |
rawCategories | string | Original, un-normalized categories. |
rating | number | Rating (0 if none). |
sponsored | boolean | Sponsored listing. |
center | string | Location as WKT POINT(<lng> <lat>) — longitude first. |
{
"query": "coffee in Abdoun",
"locale": "en",
"understanding": { "model": "navvo-ai", "unavailable": false, "purpose": "search_understanding", "content": "{\"categoryHints\":[\"coffee\"]}" },
"places": {
"items": [
{
"id": "b1f3c2a0-1234-4abc-9def-0123456789ab",
"slug": "rumi-cafe-abdoun",
"nameEn": "Rumi Cafe",
"nameAr": "مقهى رومي",
"categories": ["cafe", "coffee-shop"],
"canonicalCategorySlug": "cafe",
"rawCategories": ["Coffee shop", "Cafe"],
"rating": 4.7,
"sponsored": true,
"center": "POINT(35.8806 31.9461)"
}
],
"total": 1,
"page": 1,
"limit": 25
},
"index": { "provider": "navvo", "configured": true, "available": true, "host": "configured" }
}
Ranking
Results are ordered: (1) how well the name matches your query — exact name first, then names starting with the query, then substring matches (leading articles like "The" are ignored, in English and Arabic); (2) sponsored and relevant to the query; (3) by descending rating. A place literally named what you searched always outranks a highly-rated unrelated result.
Errors
| Status | When |
|---|---|
400 | q is missing or blank. |
401 / 403 | Missing/invalid key, or key lacks the search scope. |
Pagination has no cursor — compare
page * limit against places.total. To fetch a place's full details (hours, photos, entrances), call GET /places/{slug} with the slug from a result.