Skip to content
TarekyDocs
Console

Search and addresses

GET /v1/locations/geocode?q=الكرادة&limit=5&proximity=44.36,33.31
  • Searches places, administrative areas and streets, in Arabic, English and Kurdish.
  • Spelling variants of the same letter match: «الكرادة» and «الكراده», «إ» and «ا».
  • Works as you type: a partial word matches its start.
  • proximity breaks ties in favour of the nearer result.
  • A plus code is understood directly. A short one (like 8H7W+XX) needs a city after it («8H7W+XX Baghdad») or proximity.

Each result has a kind (poi, admin, street or plus_code), its name in three languages, and lng/lat.

GET /v1/locations/search?q=شارع فلسطين&limit=10&lng=44.36&lat=33.31

The same places as above, shaped for a search box, with what each row needs to say what it is and where. Besides id, kind, name, description, lng, lat and distanceMeters (when lng and lat were given), every row has these fields. They are always present and are null where they do not apply:

  • category: a place’s category (id and name in three languages). null for every other kind, and for places in the catch-all “General” category, which says nothing.
  • area: the smallest administrative area the result lies in (id, name and level: governorate, district or area). A street is placed by its midpoint. For an administrative area it is its parent.
  • region: the governorate, or null when it is the area itself.
  • adminLevel: the level of an administrative area (governorate, district or area); null for every other kind.
  • zoom: an administrative area’s stored map zoom. It is approximate: use bbox when there is one.
  • bbox: [minLng, minLat, maxLng, maxLat] of an administrative area’s polygon or a street’s line, ready for fitBounds; null for places and plus codes.

Build the line under a name from category (or the kind) and then area and region: «شارع · الرصافة، بغداد» tells two streets called «شارع فلسطين» apart. GET /v1/locations/geocode does not return these fields.

GET /v1/locations/reverse-geocode?lng=44.4183&lat=33.3049

lang (ar, en or ckb; default ar) sets the language of place, street and address. Where a name has no translation the Arabic one is used (then the English one), so with lang=en a street or area is usually English and a shop often stays Arabic. With lang=en the address is joined with , ; otherwise with the Arabic comma ،. label, area and region already carry all three languages, so lang does not change them. Any other value is a 422 invalid_request.

Returns:

  • place: the name of the nearest point of interest within 200 m, else the smallest administrative area containing the point.
  • street: the nearest named street within 60 m. Alley codes such as 214-109 or S13 are not names and are never returned, so the field is null when no named street is close (common in Baghdad, Erbil and Mosul neighbourhoods). A street whose name is a number but which is a main road, like «شارع 60», is kept.
  • address: the written address from finest to coarsest (street, district, city).
  • plusCode: the plus code.
  • label: the name to show for this point, never null. It has source (poi, street, admin or plus_code), id, the name in three languages, distanceMeters and near.
  • area: the smallest administrative area containing the point (id, name and level: governorate, district or area). region: the governorate, or null when it is the area itself. Both are null outside every known area.

label is chosen in this order, and the first match wins:

  1. A named point of interest within 50 m.
  2. A named street within 60 m.
  3. A named point of interest within 200 m, where near is true: show it as “near …”.
  4. The smallest administrative area containing the point.
  5. The plus code.

Names that are only a number («1111», «محلة 718») do not count as names. The server makes the choice because it needs the database; you only phrase it.

{
"place": "مطعم السلام",
"street": "شارع الرشيد",
"address": "شارع الرشيد، الشورجة، الرصافة، بغداد",
"plusCode": "8H568988+3C",
"label": {
"source": "poi",
"id": "…",
"name": { "ar": "مطعم السلام", "en": null, "ckb": null },
"distanceMeters": 32.4,
"near": false
},
"area": { "id": "…", "name": { "ar": "الشورجة", "en": "Shorja", "ckb": null }, "level": "area" },
"region": { "id": "…", "name": { "ar": "بغداد", "en": "Baghdad", "ckb": null } }
}
GET /v1/poi/nearby?lng=44.4183&lat=33.3049&radius=800&sortBy=distance

sortBy=rating orders by rating, then by distance on ties. categoryId narrows to one category.

Each place has openingHours: a weekly schedule with the keys mon to sun, each a list of { "open": "08:00", "close": "22:00" } (several ranges are a split shift). A day that is missing is unknown, [] is closed that day, and null means no hours are on record, which is the usual case today. Times are local to Iraq (UTC+3, no daylight saving), so work out “open now” on the client. /v1/poi/in-bounds does not return hours.

Address-only survey rows (a name that starts “behind the court”) are never returned. count is the number of matches inside the radius, before take.

filters narrows a category by its own attributes: a JSON string, the same one /v1/poi/in-bounds takes. Only EV charging stations have filters today:

GET /v1/poi/nearby?lng=44.4183&lat=33.3049&radius=5000&categoryId=<EV category id>&filters={"accessType":"PUBLIC","minPowerKw":22}

count then counts only the stations that match. A payload that is not JSON, or that the category does not accept, is a invalid_request (400). For a category without filters the parameter is ignored.

GET /v1/poi/in-bounds?minLng=44.30&minLat=33.20&maxLng=44.50&maxLat=33.40&take=500

The places inside a bounding box, for drawing a map. They come most important first: each place has an importance (its category’s weight, higher for a place that was surveyed or added by a person than for a bare import), highest first, then by id; take (1 to 2,000, 500 by default) keeps that many. A box over a whole city holds thousands of places, so a viewport shows its fuel stations and hospitals before its schools. Read importance as a rank, not a score. Address-only survey rows are not returned. categoryId and filters work as on /v1/poi/nearby.

POST /v1/poi/along-route
{
"route": "ybqp~@q_sqsAvNfBhBRUvQ…",
"routeFormat": "polyline6",
"categoryId": "…",
"from": { "lng": 44.3661, "lat": 33.3152 },
"buffer": 300,
"take": 10
}

Places of one category within buffer metres of a route, in the order the route reaches them, each with the extra driving time to visit it. For “petrol on the way” or “add a stop” without drawing a circle around every point of the trip.

  • route is an encoded polyline of 2 to 10,000 points that enters Iraq: what /directions returns with geometries=polyline (routeFormat: "polyline", the default) or polyline6. It is a POST body because a full-length route is 10 KB, more than a URL carries. A route simplified to 10 m is about a third of that size.
  • categoryId is required. buffer is 50 to 2,000 m (300 by default). take is 1 to 20 (10).
  • from is where the driver is. Places behind it are left out, aheadMeters counts from it, and maxAheadMeters limits how far ahead to look. Send the same full route each time and only change from.
  • detour (default true) prices each place: the extra driving time to go to it and rejoin the route, measured over 1.5 km of road either side of the place. sortBy: "detour" ranks the first 20 places ahead by it; the default along keeps route order. With detour: false the routing engine is not used.
{
"routeLengthMeters": 13881,
"fromAlongMeters": 0,
"data": [
{
"id": "…",
"name": { "ar": "محطة وقود السعدون", "en": null, "ckb": null },
"lng": 44.3869, "lat": 33.3252,
"alongMeters": 10676,
"aheadMeters": 10676,
"offRouteMeters": 32,
"detourSeconds": 15,
"detourMeters": 30
}
]
}
  • alongMeters is the distance from the start of the route, offRouteMeters the distance from the line. The pin fields are those of /v1/poi/nearby.
  • detourSeconds and detourMeters are null when a place could not be priced (no road within reach, routing unavailable). The places are still returned, never an error. Times are free-flow; they do not include traffic.
  • Each call costs 2 units and is limited to 10 a second per key. An invalid route is a 422 invalid_request.