API Docs

Free tier, fair use. All endpoints are CORS-open (Access-Control-Allow-Origin: *) and speak JSON over HTTPS.

1 · Register a free key

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:

Pass the key as ?key=YOUR_KEY to all endpoints. One key for everything! Keys are rate-limited per minute.

2 · MapLibre dark style

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
});

3 · Geocoding

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 });

4 · Reverse Geocoding

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 …"}

5 · AI Address Intent Parsing

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"}

6 · Landmarks

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'
});

7 · Config

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);

8 · Vector tiles proxy

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
});

Limits & fair use

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.