Feedback for Geoapify
Product feedback from building SiteScout on Geoapify (REST APIs in the product path, MCP server for the legacy pipeline). Every item has a reproduction you…
On this page
What worked very well is listed first, because it shaped the product.
✅ What worked well
- Isoline → Places by
filter=geometry:<isoline id>. Drawing a 10-minute walk isoline and counting POIs inside it with the returned id is the core of SiteScout and costs one request per category. No polygon upload, no client-side point-in-polygon. This is a genuinely agent-friendly primitive. - Agent-readable errors. An unsupported category returns a 400 whose message tells the caller to call
list_place_categoriesand pick one. Our MCP host used exactly that to self-correct. - New (post-July-2025) ward names are already in the data. When a query uses the new ward name, the result
names the expected new ward in 8/8 test addresses (
bench/hcmc-addresses/RESULTS.md). That is ahead of many local data sources. - Autocomplete is robust to messy Vietnamese. It resolved landmark names with diacritics damaged by an LLM
(
agent/transcripts/01-…jsonl) and reached 86% top-1 accuracy on 29 formal landmark names. - MCP server tools declare
outputSchema(11 tools,tests/fixtures/live/mcp_tools_list_2026-10-22.sse.txt).
#1 — No isoline tool on the MCP server
- Observation:
tools/listonhttps://api.geoapify.com/v1/mcpreturns 11 tools (geocoding ×3, places ×2, routing ×2, geometry ×4). None computes a travel-time area. Re-checked 2026-10-22. - Impact: an MCP-only agent has to approximate catchments with circular buffers, which over-count across rivers and highways (Thảo Điền ↔ Thủ Thiêm across the Saigon River is the textbook case). This is why SiteScout's product path moved to the REST Isoline API.
- Reproduction:
curl -X POST https://api.geoapify.com/v1/mcp -H 'x-api-key: KEY' -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'(afterinitialize). - Suggestion: a
calculate_isolinetool (mode, type time/distance, range) that returns the isoline id as well, sosearch_placescan takefilter=geometry:<id>the way the REST API does.
#2 — Vietnamese addresses after the July-2025 reform: city says "Thành phố Thủ Đức" for central HCMC
- Observation: Viet Nam removed the district level on 1 July 2025 (HCMC is now city → ward; Resolution
1685/NQ-UBTVQH15). In our 55-query benchmark, 56% (search) and 58% (autocomplete) of results carry
"Thành phố Thủ Đức" in the label for places that were never in Thủ Đức, e.g.
Chợ Bến Thành, Lê Lợi, Phường Bến Thành, Thành phố Thủ Đức, 71009andBệnh viện Chợ Rẫy, 201B Đường Nguyễn Chí Thanh, Phường Chợ Lớn, Thành phố Thủ Đức. The ward is correct; the level above it is a stale unit (Thủ Đức city was itself dissolved) and is wrong for these locations. Other results for neighbouring buildings say "Thành phố Hồ Chí Minh" instead, so the field is inconsistent between neighbouring features. - Impact: apps that print
formattedshow a wrong city to Vietnamese users; apps that group or filter bycity/countysilently put central HCMC into Thủ Đức. For an agent, "Phường Sài Gòn, Thành phố Thủ Đức" is a contradiction it may try to "fix" in the wrong direction. - Reproduction:
bench/hcmc-addresses/run.mjs(≈4 credits/query), summary inbench/hcmc-addresses/RESULTS.md; single call:GET /v1/geocode/search?text=Chợ Bến Thành, Thành phố Hồ Chí Minh&lang=vi&filter=countrycode:vn. - Suggestion: for VN after 2025-07-01 emit
city = Thành phố Hồ Chí Minhand leave the district level empty (or expose the old district as a separate, clearly-named legacy field). We are happy to share the 55-query set as a regression test.
#3 — Pre-2025 numbered wards ("Phường 12, Quận 5") are matched against alley numbers
- Observation: most people and many databases still write old addresses. Queries with an old numbered ward
resolve far worse than the same street address with the new ward name (sitescout v1.0 resolver: 2/8 vs 7/8 within
300 m; raw
/geocode/search: 4/8 vs 6/8). The failure mode is specific: the number of an old ward is matched to an alley (hẻm) number:201B Nguyễn Chí Thanh, Phường 12, Quận 5→175/12 Đường Nguyễn Tri Phương(1.0 km off)720A Điện Biên Phủ, Phường 22, Quận Bình Thạnh→149/22 Đường Nguyễn Tri Phương(7.3 km off)57A Tháp Mười, Phường 2, Quận 6→175/2 Đường Nguyễn Tri Phương(2.1 km off)
- Impact: old-format addresses are the norm in existing customer lists, so batch geocoding them gives plausible-looking but wrong points.
- Our workaround (documented, open-source): drop
Phường <number>,Quận …andTP Thủ Đứcbefore calling the geocoder and match tokens as whole words. Old-ward accuracy went 25% → 75% with no extra calls (src/engine/scout.tsresolvePlace, testtests/resolve-place.test.ts). - Suggestion: treat
Phường \d+/Quận \d+as administrative tokens (never as house or alley numbers), and ideally map pre-2025 wards to their successors (the official mapping is public in Resolution 1685).
#4 — Free-text search on landmark names drifts by kilometres while autocomplete is right
- Observation: on 29 well-known HCMC landmarks (reference: Wikidata coordinates),
/v1/geocode/searchwas within tolerance for 19 (66%) vs 25 (86%) for/v1/geocode/autocompletewith identical text and bias. Typical misses: "Bảo tàng Chứng tích chiến tranh" 5.3 km, "Nhà thờ Tân Định" 4.3 km, "Chợ Bà Chiểu" 4.1 km off; the unaccented "buu dien thanh pho" returned a point 175 km away. - Impact: developers reasonably use
searchfor "find this place"; for Vietnamese POI names the quieter endpoint is the better one, which is not obvious from the docs. - Reproduction:
bench/hcmc-addresses/RESULTS.md→ "Every query" table (per-query distances for both endpoints). - Suggestion: either rank POI name matches higher in
searchfor VN, or add a doc note recommending autocomplete for POI-name lookups.
#5 — Places: a comma-separated categories list did not behave as a union in our tests
-
Observation (same circle, 800 m around Thảo Điền,
limit=200):categories=features catering.cafe26 office5 catering.cafe,office26 (expected up to 31) office.company3 office.coworking0 office.company,office.coworking0 (expected 3) -
Impact: a multi-category request silently returns fewer places than its parts; counts look plausible, so the bug is hard to notice. SiteScout now sends one request per category (
placesMulti). -
Reproduction:
GET /v2/places?categories=office.company,office.coworking&filter=circle:106.7317,10.8040,800&limit=200. -
Question: is this expected (e.g. intersection semantics for some combinations)? If so, a doc line would help.
#6 — Boundaries: no ward-level polygon at Hàng Xanh (Bình Thạnh)
- Observation:
/v1/boundaries/part-of?lat=10.801436&lon=106.7113199returns onlyKhu phố 21 (admin_level 9) ⊂ Thành phố Hồ Chí Minh (4) ⊂ Việt Nam (2), no ward, while reverse geocoding the same point names "Phường Thạnh Mỹ Tây". At Phường Sài Gòn and Phường An Khánh the ward level is present. - Impact: a "within this ward" analysis has no polygon to clip to; SiteScout falls back to a disc and says so in the report's limitations.
- Note: this may be an OpenStreetMap data gap rather than a Geoapify issue; reporting it so the boundary import can be checked.
Reproducing everything
npm ci && npm run build
export GEOAPIFY_API_KEY=… # free tier is enough
node bench/hcmc-addresses/run.mjs # ~230 credits, writes results.jsonl
python3 bench/hcmc-addresses/summarize.py