Search and addresses
Search by name
Section titled “Search by name”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.
proximitybreaks 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») orproximity.
Each result has a kind (poi, admin, street or plus_code), its name in three languages, and lng/lat.
Search for a search box
Section titled “Search for a search box”GET /v1/locations/search?q=شارع فلسطين&limit=10&lng=44.36&lat=33.31The 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 (idandnamein three languages).nullfor 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,nameandlevel:governorate,districtorarea). A street is placed by its midpoint. For an administrative area it is its parent.region: the governorate, ornullwhen it is theareaitself.adminLevel: the level of an administrative area (governorate,districtorarea);nullfor every other kind.zoom: an administrative area’s stored map zoom. It is approximate: usebboxwhen there is one.bbox:[minLng, minLat, maxLng, maxLat]of an administrative area’s polygon or a street’s line, ready forfitBounds;nullfor 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.
Address of a point
Section titled “Address of a point”GET /v1/locations/reverse-geocode?lng=44.4183&lat=33.3049lang (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 as214-109orS13are not names and are never returned, so the field isnullwhen 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, nevernull. It hassource(poi,street,adminorplus_code),id, the name in three languages,distanceMetersandnear.area: the smallest administrative area containing the point (id, name andlevel:governorate,districtorarea).region: the governorate, ornullwhen it is theareaitself. Both arenulloutside every known area.
label is chosen in this order, and the first match wins:
- A named point of interest within 50 m.
- A named street within 60 m.
- A named point of interest within 200 m, where
nearistrue: show it as “near …”. - The smallest administrative area containing the point.
- 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 } }}Places nearby
Section titled “Places nearby”GET /v1/poi/nearby?lng=44.4183&lat=33.3049&radius=800&sortBy=distancesortBy=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.
Places in a box
Section titled “Places in a box”GET /v1/poi/in-bounds?minLng=44.30&minLat=33.20&maxLng=44.50&maxLat=33.40&take=500The 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.
Places along a route
Section titled “Places along a route”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.
routeis an encoded polyline of 2 to 10,000 points that enters Iraq: what/directionsreturns withgeometries=polyline(routeFormat: "polyline", the default) orpolyline6. 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.categoryIdis required.bufferis 50 to 2,000 m (300 by default).takeis 1 to 20 (10).fromis where the driver is. Places behind it are left out,aheadMeterscounts from it, andmaxAheadMeterslimits how far ahead to look. Send the same full route each time and only changefrom.detour(defaulttrue) 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 defaultalongkeeps route order. Withdetour: falsethe 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 } ]}alongMetersis the distance from the start of the route,offRouteMetersthe distance from the line. The pin fields are those of/v1/poi/nearby.detourSecondsanddetourMetersarenullwhen 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.





