Free tier, fair use. All endpoints are CORS-open (Access-Control-Allow-Origin: *) and speak JSON over HTTPS.
One POST with your email. The key is shown once in the response — store it somewhere safe.
curl -X POST https://wecomaps.com/api/keys/register \
-H 'Content-Type: application/json' \
-d '{"email": "you@example.com"}'
# → {"ok":true,"key":"wmk_4f9a2c7e1b3d8f0a5c6e9b2d"}
Or right here:
?key=YOUR_KEY to all endpoints. One key for everything! Keys are rate-limited per minute.GEThttps://wecomaps.com/api/style-dark.json
Full WecoMaps dark style (vector, OpenMapTiles schema). Point maplibregl.Map at it and you have a 3D-ready dark map.
curl 'https://wecomaps.com/api/style-dark.json?key=YOUR_KEY'
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://wecomaps.com/api/style-dark.json?key=YOUR_KEY',
center: [108.4419, 11.9404], // Đà Lạt
zoom: 14,
pitch: 52
});
GEThttps://wecomaps.com/api/geocode?q=…&key=…
World place search — Photon and Nominatim queried in parallel, merged, deduplicated, top 8 results. Min 2 chars.
curl 'https://wecomaps.com/api/geocode?q=dalat&key=YOUR_KEY'
# → {"ok":true,"q":"dalat","results":[
# {"lat":11.9404,"lng":108.4419,"label":"Đà Lạt · Lâm Đồng",
# "kind":"city","source":"photon"}, …]}
const r = await fetch(
'https://wecomaps.com/api/geocode?q=' + encodeURIComponent(q) + '&key=YOUR_KEY'
);
const { results } = await r.json();
map.flyTo({ center: [results[0].lng, results[0].lat], zoom: 15 });
GEThttps://wecomaps.com/api/reverse?lat=…&lng=…&key=…
Convert map coordinates back to a human-readable address. Powered by Photon + Nominatim.
curl 'https://wecomaps.com/api/reverse?lat=11.9404&lng=108.4419&key=YOUR_KEY'
# → {"ok":true,"lat":11.9404,"lng":108.4419,"label":"Nhà hàng Thủy Tạ · Trần Quốc Toản …"}
POSThttps://wecomaps.com/api/ai/address?key=…
Let AI extract the core delivery address from messy user chat messages. (Unified AI endpoint so you only need ONE key for everything!)
curl -X POST 'https://wecomaps.com/api/ai/address?key=YOUR_KEY' \
-H 'Content-Type: application/json' \
-d '{"prompt": "Deliver to hotel Malibu in Vung Tau"}'
# → {"ok":true,"type":"location","query":"hotel Malibu Vung Tau"}
GEThttps://wecomaps.com/api/landmarks.json
Curated GeoJSON FeatureCollection of city landmarks (name, emoji icon, city tag). Loads straight into a GeoJSON source.
curl https://wecomaps.com/api/landmarks.json
map.addSource('landmarks', {
type: 'geojson',
data: 'https://wecomaps.com/api/landmarks.json'
});
GEThttps://wecomaps.com/api/config.json
One JSON with everything the map app uses: style URLs, terrain DEM, satellite tiles, city list, building extrusion defaults, endpoint URLs.
curl https://wecomaps.com/api/config.json
const cfg = await (await fetch('https://wecomaps.com/api/config.json')).json();
console.log(cfg.cities, cfg.terrain, cfg.styleDark);
GEThttps://wecomaps.com/tiles/{z}/{x}/{y}
Planet vector tiles proxied from OpenFreeMap. Usually referenced from inside a style rather than called directly.
curl -o tile.pbf 'https://wecomaps.com/tiles/14/12944/8136.pbf'
map.addSource('wecomaps', {
type: 'vector',
url: 'https://wecomaps.com/tiles/planet' // TileJSON
});
FREEFree tier, fair use — no billing. Geocoding is rate-limited per minute:
· With key — 60 requests/min per key (?key=…).
· Without key — 20 requests/min per IP, so casual and same-origin use keeps working.
· Exceeding the limit returns HTTP 429 with {"ok":false,"error":"rate_limited"} — back off and retry.
Tiles, style, landmarks and config are not key-gated today; please cache responses and don't hot-loop them.