UzMap docs

Places

Seven endpoints return places and what is known about them. Together they are billed as the places product.

EndpointReturns
GET /api/nearbyPlaces around a point
GET /api/place/{id}One place with contact details, opening hours and neighbours
GET /api/place/osm/{n|w|r}/{id}The same, addressed by OpenStreetMap id
GET /api/geometry/{id}A place's outline as GeoJSON
GET /api/categoriesThe category taxonomy
GET /api/districtsRegion, district and mahalla label points as GeoJSON
GET /api/photoPhoto metadata for a Wikidata id
GET /api/photo/img/{qid}.jpgThe photo itself

All handlers live in services/server/internal/server/server.go. Examples below use $UZMAPS for the server origin (for instance http://127.0.0.1:8080 for a local uzmap serve), and the JSON shown is real output from a current build, trimmed where marked .

What applies to every endpoint#

API key. When the server runs with --require-key, every /api/ path needs one. Pass it as ?key=… or as an X-API-Key header; the query parameter is checked first. Photo image URLs are the case where the query form is the only option — see Photos. A missing or unknown key gets a 401 JSON body with error, code, message and docs. The key mechanism is described on the API keys page.

lang. Accepted values are uz (default), uz-Cyrl, ru and en. Anything else silently becomes uz (lang() in server.go). It affects name, label, category_label and full_address.

Errors are JSON {"error": "…"}. Every place endpoint returns 503 with search index not built (districts: index not built) when data/build/search.sqlite is missing. The photo image endpoint is the exception: its 404 is plain text, from http.NotFound.

CORS. Access-Control-Allow-Origin: * on every response (withCommon).

The place object#

/api/nearby returns a list of these; /api/place/{id} returns one with extra fields added. The shape is resultJSON in server.go.

FieldTypeNotes
idintegerStable within one data build. This is the id /api/place/{id} and /api/geometry/{id} take.
kindstringplace, street, poi, address or nature.
categorystringTaxonomy id such as food.cafe. See Categories.
groupstringThe category's group, e.g. food. Derived by taxonomy.GroupOf.
iconstringSprite icon name. The category's icon, falling back to the group's, then poi (taxonomy.IconFor).
namestringBest name for lang (resolution below).
labelstringSecondary line: Park · Sharof Rashidov, Toshkent.
category_labelstringCategory label in lang.
lat, lonnumberRepresentative point.
bbox[minlon, minlat, maxlon, maxlat]Equals [lon, lat, lon, lat] for point features.
distancenumberMetres from the query point. Omitted when not computed and, because zero counts as empty, when it is exactly 0.
addressobjectSee below. Always present, possibly {}.
namesobjectName variants keyed by language or OSM name key. Omitted when there are none.
ranknumberImportance, 0–1. Used for ordering.
matched, reasonSearch-only fields; absent from place endpoints.

Name resolution: uznames.uz; uz-Cyrlnames["uz-Cyrl"], then names.ru; runames.ru, then names["uz-Cyrl"]; ennames.en, then names.uz. If nothing matches, the primary name is used, and if the feature has no name at all, the category label stands in for it.

names keys come from pickNames in internal/osmx/extract.go: the name: prefix is stripped, so OSM's name:uz-Cyrl becomes uz-Cyrl, while un-prefixed keys stay as they are. Possible keys: uz, uz-Latn, uz-Cyrl, ru, en, kaa, tg, kk, alt_name, old_name, official_name, int_name, short_name, etymology. Overture places carry only uz, uz-Cyrl, ru, en.

Category labels for uz-Cyrl come out in English. taxonomy.Label falls back lang → en → uz, and the taxonomy only defines uz, ru and en labels.

address (store.Address): street, housenumber, neighbourhood, suburb, city, district, region, postcode — strings, each omitted when empty.

GET /api/nearby#

Places within a radius of a point.

ParameterDefaultNotes
lat, lon0Not validated. Omitting them searches around 0°,0° and returns {"results":[]}.
radius500Metres. Values above 20000 are clamped, not rejected.
kindspoiComma-separated list of kinds.
categoryExact category id (food.cafe) or a whole group (group:food). Nothing looser: food.cafe does not include food.teahouse.
limit200 or negative means no limit.
languz

Results are ordered by rank × 0.4 + 0.6 / (1 + distance / 300) (Index.Nearby), so a prominent place 100 m away can come before an obscure one 20 m away. Before the limit is applied, entries with the same normalised name, kind and city within a kind-dependent radius — 250 m for POIs — are collapsed to one, which is why a bazaar mapped both as a building and as a point appears once.

bash
curl "$UZMAPS/api/nearby?lat=41.3111&lon=69.2797&radius=300&limit=3&lang=en"
json
{"results":[
  {"id":112943,"kind":"poi","category":"leisure.park","group":"leisure","icon":"park",
   "name":"Square","label":"Park · Sharof Rashidov, Ташкент","category_label":"Park",
   "lat":41.31128571278156,"lon":69.27975493574449,
   "bbox":[69.2779275,41.3100336,69.2813994,41.312818],"distance":21.153959974222012,
   "address":{"neighbourhood":"Sharof Rashidov","city":"Ташкент","district":"Yunusobod Tumani"},
   "names":{"en":"Square","ru":"Сквер","uz":"Skver","alt_name":"…","old_name":"…"},
   "rank":0.8500000000000001},
  {"id":455,"kind":"poi","category":"culture.monument","group":"culture","icon":"monument",
   "name":"Amir Timur","label":"Monument · Sharof Rashidov, Toshkent","category_label":"Monument",
   "lat":41.3111759,"lon":69.2797551,"bbox":[69.2797551,41.3111759,69.2797551,41.3111759],
   "distance":9.612904450845452,
   "address":{"neighbourhood":"Sharof Rashidov","city":"Toshkent","district":"Yunusobod Tumani"},
   "names":{"en":"Amir Timur","ru":"Амир Тимур","uz":"Amir Temur"},"rank":0.75},

]}

GET /api/place/{id}#

One place, with everything the index holds about it. {id} is the integer from a result object. The alternative form /api/place/osm/{type}/{id} looks the entry up by its OpenStreetMap type letter and id instead; /api/place/osm/n/377979982 returns the monument above.

StatusBodyWhen
400bad id{id} is not an integer
400use /api/place/osm/{n|w|r}/{id}The osm/ form has the wrong number of segments
404not foundNo entry with that id

The response is the place object plus:

FieldTypeNotes
osmobject{type, id, url} — see Where a place came from.
tagsobjectSource tags, filtered to a fixed allowlist (below).
populationinteger0 when unknown.
admin_levelinteger0 when unknown.
full_addressstringstreet[, housenumber] or neighbourhood; then district (if different from city); then city, or region if there is no city. With nothing to show it is Xaritadagi nuqta / Точка на карте / Dropped pin by lang.
detailsobjectContact and attribute fields lifted out of tags — table below. Always present, possibly {}.
photo_hintstring/api/photo?wikidata=Q…, present only when photos are enabled and the entry has a wikidata tag. The path carries no key; add yours.
nearbyarray or nullUp to six named POIs within 350 m, excluding the place itself. null — not [] — when there are none.
geometry_urlstring/api/geometry/{id}, present when the entry has stored geometry and its kind is street, place, nature or poi.

details keys, in the order the handler builds them:

KeyTaken from
phonephone, else contact:phone
websitewebsite, else contact:website
instagramcontact:instagram
telegramcontact:telegram
emailemail, else contact:email
cuisine, wheelchair, internet_access, outdoor_seating, takeaway, delivery, building:levels, height, capacity, fee, stars, ele, iata, brand, operator, description, sport, denomination, wikipedia, wikidataThe tag of the same name, copied verbatim when present
opening_hoursThe raw opening_hours tag
hours, open_statusParsed from opening_hours — see Opening hours

tags is not the full OSM tag set. The extractor keeps only these keys: opening_hours, phone, contact:phone, website, contact:website, contact:instagram, contact:telegram, email, contact:email, brand, operator, cuisine, wheelchair, wikidata, wikipedia, description, level, building:levels, height, addr:street, addr:housenumber, addr:city, addr:district, addr:place, addr:quarter, addr:suburb, addr:postcode, addr:neighbourhood, addr:block, amenity, shop, tourism, leisure, office, historic, natural, place, highway, railway, aeroway, public_transport, religion, denomination, sport, internet_access, outdoor_seating, takeaway, delivery, smoking, capacity, fee, parking, fuel:cng, fuel:lpg, fuel:diesel, fuel:octane_95, stars, rooms, population, admin_level, ele, iata, icao, network, ref, route_ref, colour, image, school:language, healthcare, dispensing, drive_through, payment:cards.

bash
curl "$UZMAPS/api/place/112943?lang=en"
json
{"id":112943,"kind":"poi","category":"leisure.park","group":"leisure","icon":"park",
 "name":"Square","label":"Park · Sharof Rashidov, Ташкент","category_label":"Park",
 "lat":41.31128571278156,"lon":69.27975493574449,
 "bbox":[69.2779275,41.3100336,69.2813994,41.312818],
 "address":{"neighbourhood":"Sharof Rashidov","city":"Ташкент","district":"Yunusobod Tumani"},
 "names":{"en":"Square","ru":"Сквер","uz":"Skver","alt_name":"…","old_name":"…"},
 "rank":0.8500000000000001,
 "osm":{"type":"w","id":802384567,"url":"https://www.openstreetmap.org/way/802384567"},
 "tags":{"leisure":"park","natural":"grass","opening_hours":"24/7","ele":"455",
         "website":"https://mytashkent.uz/2007/06/05/skver-amira-temura/",
         "wikidata":"Q4421686","wikipedia":"ru:Сквер Эмира Тимура",
         "addr:city":"Ташкент","addr:street":"Сквер Амира Тимура"},
 "population":0,"admin_level":0,
 "full_address":"Sharof Rashidov, Yunusobod Tumani, Ташкент",
 "details":{"ele":"455","website":"https://mytashkent.uz/2007/06/05/skver-amira-temura/",
            "wikidata":"Q4421686","wikipedia":"ru:Сквер Эмира Тимура",
            "opening_hours":"24/7",
            "hours":{"raw":"24/7","all_day":true,"days":[[{"open":0,"close":1440}],[{"open":0,"close":1440}],
                     [{"open":0,"close":1440}],[{"open":0,"close":1440}],[{"open":0,"close":1440}],
                     [{"open":0,"close":1440}],[{"open":0,"close":1440}]]},
            "open_status":{"open":true,"known":true,"all_day":true}},
 "photo_hint":"/api/photo?wikidata=Q4421686",
 "nearby":[],
 "geometry_url":"/api/geometry/112943"}

Where a place came from#

osm.type is the letter the extractor stored, and the index holds places from three sources:

osm.typetags.sourceExtra tags
n, w, r
oovertureoverture:id, overture:category
ccustomcustom:id, custom:categories, custom:gallery, custom:socials, custom:schedule, custom:attributes, custom:menu, status, image

For o and c entries osm.id is a hash of the source record id, and osm.url is built by the same rule as for real OSM objects — anything that is not n or w gets /relation/ — so it points at nothing. Check tags.source before linking to it.

The custom:* values are raw JSON strings copied through as-is; custom:schedule is not turned into hours, and image / custom:gallery are relative paths that no endpoint on this server serves. Overture contact data does surface in details, because it is stored under the OSM key names (phone, website, email, contact:instagram, contact:telegram).

The /api/place/osm/{type}/{id} handler passes {type} through to the database unchecked, so /api/place/osm/o/701235510889211 resolves an Overture entry. The browser client's placeByOsm only types 'n' | 'w' | 'r'.

Opening hours#

When the entry has an opening_hours tag, details.hours is the parsed weekly schedule and details.open_status is its evaluation at the current time in Asia/Tashkent (tashkentNow in server.go — the client's clock and time zone play no part). Both come from internal/hours/hours.go.

hours:

FieldTypeNotes
rawstringThe tag as written.
all_dayboolean24/7, 24 hours, 00:00-24:00 or круглосуточно.
daysarray of 7 arraysMonday first. Each day is a list of {open, close} in minutes from midnight; close exceeds 1440 for a range that runs past midnight (20:00-02:00 is {1200, 1560}). A closed day is [], never null.
unparsedbooleanPresent and true when no rule could be read. days is then all [].

open_status:

FieldTypeNotes
openboolean
knownbooleanfalse when the schedule was unparsed; open is then meaningless.
all_daybooleanOmitted when false.
next_changestringHH:MM of the next opening or closing. Omitted when there is none in the coming week.
closes_soon, opens_soonbooleanThe change is within 60 minutes. Omitted when false.
next_dayintegerDays ahead of the next opening — 1 is tomorrow. Omitted for today.

The parser deliberately covers the patterns that dominate Uzbekistan's data rather than the full opening_hours grammar: rules separated by ;, day ranges and lists in English (Mo-Fr, Sa,Su) or Russian abbreviations (пн-пт), times with : or ., and off / closed. PH and SH are ignored. Anything else — month rules, week parities, sunrise — leaves the schedule unparsed.

A cafe tagged Mo-Su 09:00-23:00, fetched after closing time:

json
"hours":{"raw":"Mo-Su 09:00-23:00","all_day":false,
         "days":[[{"open":540,"close":1380}],[{"open":540,"close":1380}],[{"open":540,"close":1380}],
                 [{"open":540,"close":1380}],[{"open":540,"close":1380}],[{"open":540,"close":1380}],
                 [{"open":540,"close":1380}]]},
"open_status":{"open":false,"known":true,"next_change":"09:00","next_day":1}

GET /api/geometry/{id}#

The outline of a place as one GeoJSON Feature, for drawing a highlight. Coordinates are [lon, lat] at six decimal places. properties is {id, name, kind}. Served with Cache-Control: public, max-age=3600.

Entrygeometry.typeproperties.kind
A street, or a nature entry with category nature.riverMultiLineString, one line per stored segmentThe entry's kind
A place whose osm.type is rMultiPolygon built from the administrative boundary — outer ring first, then holes, per polygonadmin
Anything else with stored geometry (area POIs, lakes, parks)Polygon, outer ring onlyThe entry's kind
StatusBodyWhen
400bad idNot an integer
404not foundNo such entry
404no polygonA relation-backed place whose boundary is not in the geocoder
404no geometryThe entry is a point — most POIs, and places mapped as nodes such as city districts

Only follow geometry_url from a place response; requesting geometry for an arbitrary id mostly yields no geometry.

bash
curl "$UZMAPS/api/geometry/327434"
json
{"type":"Feature",
 "properties":{"id":327434,"kind":"admin","name":"Andijon viloyati"},
 "geometry":{"type":"MultiPolygon","coordinates":[[[[71.97975,40.619067],[71.979203,40.619425],]]]}}

GET /api/categories#

The whole taxonomy, with labels in every language. No parameters. No Cache-Control header is set, but the content changes only with a server release; the browser client caches it for the page's lifetime.

json
{"groups":[{"id":"food","icon":"restaurant","color":"#E8712B",
            "label":{"uz":"Ovqatlanish","ru":"Еда","en":"Food & drink"}}, ],
 "categories":[{"id":"food.restaurant","group":"food","icon":"restaurant",
                "label":{"uz":"Restoran","ru":"Ресторан","en":"Restaurant"},
                "synonyms":["restoran","ресторан","restaurant","oshxona","ошхона","milliy taomlar"],
                "rank":0.55}, ]}
Category fieldNotes
idThe value in a place's category.
groupNot always the id's prefix — see the exceptions below the tables.
iconSprite name.
label{uz, ru, en}.
synonymsSearch terms in any script. Omitted when there are none.
rankBase importance 0–1.

Groups#

The eighteen groups, from taxonomy.Groups:

idiconcoloren
foodrestaurant#E8712BFood & drink
shoppingshopping#D9489CShopping
healthhealth#E0454BHealth
educationeducation#5B6CDBEducation
financebank#2E8B57Finance
transporttransport#3A7BD5Transport
autofuel#5A6B7CAuto
lodginghotel#8E5AD6Lodging
cultureculture#B4631ECulture & sights
religionmosque#5F7C5AReligion
leisurepark#3E9B4FLeisure & sport
servicesservices#6B7280Services
beautybeauty#D46AA0Beauty
officeoffice#7A8699Offices
naturenature#4F8A3CNature
placeplace#4B5563Places
streetstreet#4B5563Streets
addressaddress#4B5563Addresses

Categories#

All 108 ids from taxonomy.Categories, with their English label. Listed under the group they belong to, which is what group: filters and the group field use.

GroupCategories
foodfood.restaurant Restaurant · food.cafe Cafe · food.fast_food Fast food · food.teahouse Teahouse · food.bar Bar · food.bakery Bakery · food.ice_cream Ice cream
shoppingshopping.supermarket Supermarket · shopping.convenience Convenience store · shopping.mall Shopping mall · shopping.marketplace Bazaar · shopping.clothes Clothes · shopping.electronics Electronics · shopping.furniture Furniture · shopping.books Books · shopping.florist Florist · shopping.jewelry Jewelry · shopping.gift Gifts · shopping.shop Shop
healthhealth.hospital Hospital · health.clinic Clinic · health.pharmacy Pharmacy · health.dentist Dentist · health.doctors Doctor · health.veterinary Veterinary
educationeducation.university University · education.school School · education.college College · education.kindergarten Kindergarten · education.library Library · education.language_school Learning centre
financefinance.bank Bank · finance.atm ATM · finance.exchange Currency exchange
transporttransport.airport Airport · transport.train_station Train station · transport.metro Metro station · transport.bus_station Bus station · transport.bus_stop Bus stop · transport.taxi Taxi
autotransport.parking Parking · auto.fuel Fuel station · auto.charging EV charging · auto.car_wash Car wash · auto.car_repair Car repair · auto.car_dealer Car dealer
lodginglodging.hotel Hotel · lodging.hostel Hostel
cultureculture.museum Museum · culture.theatre Theatre · culture.cinema Cinema · culture.gallery Gallery · culture.attraction Attraction · culture.monument Monument · culture.viewpoint Viewpoint · culture.historic Historic site · culture.zoo Zoo
religionreligion.mosque Mosque · religion.church Church · religion.synagogue Synagogue · religion.place_of_worship Place of worship
leisureculture.theme_park Amusement park · leisure.park Park · leisure.playground Playground · leisure.stadium Stadium · leisure.sports_centre Sports centre · leisure.fitness Fitness · leisure.swimming_pool Swimming pool · leisure.water_park Water park · leisure.garden Garden
servicesservices.post Post office · services.police Police · services.government Government office · services.embassy Embassy · services.townhall Town hall · services.courthouse Courthouse · services.fire_station Fire station · services.notary Notary · services.laundry Laundry · services.toilets Toilets · services.telecom Telecom shop
beautybeauty.hairdresser Hair salon · beauty.salon Beauty salon
officeservices.coworking Coworking · office.company Company · office.it IT company · office.insurance Insurance · office.lawyer Lawyer · office.travel_agency Travel agency
naturenature.peak Peak · nature.spring Spring · nature.lake Lake · nature.river River · nature.beach Beach · nature.reserve Nature reserve · nature.cave Cave
placeplace.country Country · place.region Region · place.city City · place.town Town · place.district District · place.suburb Suburb · place.neighbourhood Neighbourhood · place.village Village · place.locality Locality · place.island Island
streetstreet Street
addressaddress Address

Three things to be aware of:

  • The prefix is not the group for transport.parking (group auto), culture.theme_park (group leisure) and services.coworking (group office). Filter with group:auto to get car parks; group:transport will not return them.
  • street and address are category ids with no dot; they are their own group.
  • A place's category is not guaranteed to be in this list. The Overture mapper files funeral homes, storage, cleaning and repair businesses under services.services, which the taxonomy does not define. For an undefined id the server derives group from the prefix (services), uses the group icon, and returns an empty category_label. Treat an empty label as "generic member of group".

GET /api/districts#

Administrative areas as label points, one FeatureCollection of Point features. No parameters. Served with Cache-Control: public, max-age=300.

The reason this exists: OSM maps districts and mahallas as boundary relations, so the vector tiles carry their outlines with no name attached and they cannot be labelled from tiles at all. There are only a few hundred, so one small document is cheaper than another tileset.

Levels included, and the minimum diagonal extent an area must have to be returned (a mis-tagged street can carry admin_level=6; a real district is kilometres across):

levelMeaningMinimum extent
6Viloyat / region2000 m
7City2000 m
8City district1200 m
9Rural district1200 m
10Mahalla150 m

Feature properties:

PropertyNotes
namePrimary name.
levelAs above.
extentDiagonal of the area's bounding box in metres. The style uses it to hold small mahalla names back until the area is large enough on screen to carry one.
name:<key>One per entry in the area's names map, so name:ru, name:uz-Cyrl, name:en, and also name:int_name, name:alt_name and the like.
bash
curl "$UZMAPS/api/districts"
json
{"type":"FeatureCollection","features":[
  {"type":"Feature",
   "properties":{"name":"Бейнеу ауданы","level":6,"extent":252778,
                 "name:en":"Beynew District","name:ru":"Бейнеуский район","name:kk":"Бейнеу ауданы",
                 "name:int_name":"Beyneu","name:uz-Cyrl":"Бейнеу ауданы"},
   "geometry":{"type":"Point","coordinates":[55.39638205789523,45.02939666418345]}},

]}

The OSM extract's bounding box overlaps neighbouring countries, so some level-6 features — that first one is in Kazakhstan — lie outside Uzbekistan. Nothing in the endpoint filters them.

Photos#

Photos come from Wikidata and Wikimedia Commons and are the platform's one optional external dependency. They are on by default and switched off with uzmap serve --wikimedia=false; /api/status reports the state in its photos boolean.

GET /api/photo?wikidata=Q…#

StatusBodyWhen
200{"photo": {…}}A photo was found
200{"photo": null}The item has no image, or the lookup failed (see caching below)
502{"error":"bad wikidata id"}wikidata missing or not matching ^Q\d+$
502{"error":"…"}The Wikidata request itself failed
404{"error":"photos disabled"}Server started with --wikimedia=false

Both 200 responses carry Cache-Control: public, max-age=86400.

The photo object:

FieldTypeNotes
urlstringServer-relative: /api/photo/img/Q4421686.jpg.
source_urlstringThe file's page on Commons.
authorstringFrom Commons Artist, with HTML stripped. Omitted when empty.
licensestringCommons LicenseShortName. Omitted when empty.
license_urlstringOmitted when empty.
titlestringFile name without the File: prefix. Omitted when empty.
width, heightintegerDimensions of the original file as reported by Commons, not of the image the server serves. Omitted when zero.
attributionstringauthor · license · Wikimedia Commons, empty parts dropped. Always present. Display it next to the image.

How a photo is resolved. The server asks Wikidata for the item's P18 claim and takes the first file name; asks Commons for that file's imageinfo at iiurlwidth=1200; downloads the 1200-pixel thumbnail (or the original if there is no thumbnail), reading at most 8 MB with a 15-second timeout per request; and writes the image to <data>/cache/photos/img/<qid>.jpg and the metadata to <data>/cache/photos/meta/<qid>.json. Concurrent requests for the same id wait for the first.

Negative results are cached too, including failures. If the item has no P18, or the Commons metadata or image download fails, an empty metadata file is written and every later request returns {"photo": null} from cache. Nothing expires it. Requesting the image URL is the one thing that retries: /api/photo/img/{qid}.jpg deletes the metadata file and resolves again when it has no image on disk. To clear a wrong negative by hand, delete meta/<qid>.json.

GET /api/photo/img/{qid}.jpg#

The cached JPEG, Content-Type: image/jpeg, Cache-Control: public, max-age=604800. The .jpg suffix is optional. Anything that cannot be served — photos disabled, no image, a malformed id — is a plain-text 404, so an <img> fails the normal way.

The key goes in the query string here. An <img src> is fetched by the browser itself; there is nowhere to attach an X-API-Key header. The server accepts ?key= on every path for exactly this reason (it also lets a MapLibre style carry the key on tile URLs). The browser client's photoUrl() does the work:

js
import { UzMapClient } from '@uzmaps/api';

const api = new UzMapClient({ baseUrl: 'https://maps.example.uz', apiKey: 'YOUR_KEY', language: 'en' });

const place = await api.place(112943);
if (place.tags.wikidata) {
  const { photo } = await api.photo(place.tags.wikidata);   // GET /api/photo?wikidata=Q4421686
  if (photo) {
    img.src = api.photoUrl(photo);      // https://maps.example.uz/api/photo/img/Q4421686.jpg?key=YOUR_KEY
    caption.textContent = photo.attribution;
  }
}

photoUrl appends the key only to server-relative URLs; an absolute url is returned untouched so the key never leaks to another host. Without the client, do the same by hand:

html
<img src="https://maps.example.uz/api/photo/img/Q4421686.jpg?key=YOUR_KEY" alt="Amir Temur square">

Using the browser client#

Every endpoint on this page has a method on UzMapClient in @uzmaps/api. The client sends the key as an X-API-Key header on these calls; only photoUrl() uses the query form.

js
import { UzMapClient } from '@uzmaps/api';

const api = new UzMapClient({ baseUrl: 'https://maps.example.uz', apiKey: 'YOUR_KEY', language: 'ru' });

const { results } = await api.nearby(41.3111, 69.2797, { radius: 300, category: 'group:food', limit: 5 });
const place = await api.place(results[0].id);            // PlaceDetails
const byOsm = await api.placeByOsm('n', 377979982);       // same shape
const outline = place.geometry_url ? await api.geometry(place.id) : null;   // GeoJSON Feature
const { groups, categories } = await api.categories();
const districts = await api.districts();                  // GeoJSON FeatureCollection

place, placeByOsm, geometry, categories, districts and photo are cached per URL for the lifetime of the client instance; nearby is not.

Map data © OpenStreetMap contributors, licensed under the ODbL. © 2026 National Development Community.