Integrate the address field¶
This document describes how to combine Autocomplete v4, Place v4 and Reverse v4 to build an address field with suggestions:
- Autocomplete v4 suggests addresses as the user types.
- Place v4 returns the coordinates and address parts of the selected suggestion.
- Reverse v4 turns a map pin position into an address.
Requests go through your server to protect the services key.
On the server¶
// Node.js 18+. Runs on the server; the services key never reaches the browser.
const KEY = process.env.VIETMAP_API_KEY;
const API = "https://maps.vietmap.vn/api";
async function getJson(path, params) {
const q = new URLSearchParams({ apikey: KEY, ...params });
const res = await fetch(`${API}/${path}?${q}`);
if (!res.ok) throw new Error(`${path}: HTTP ${res.status}`);
return res.json();
}
// Suggestions while typing. focus: the user's "lat,lng", if known
export async function suggest(text, focus) {
const params = { text, display_type: "5" }; // new format, old one in data_old
if (focus) params.focus = focus;
const results = await getJson("autocomplete/v4", params);
return results.map((r) => ({ refId: r.ref_id, display: r.display }));
}
// The user picked a suggestion: coordinates and address parts for the order
export async function resolve(refId) {
const p = await getJson("place/v4", { refid: refId });
return {
display: p.display, lat: p.lat, lng: p.lng,
houseNumber: p.hs_num, street: p.street,
wardId: p.ward_id, ward: p.ward, cityId: p.city_id, city: p.city,
};
}
// The user dragged the pin: coordinates -> nearest address
export async function pinToAddress(lat, lng) {
const [nearest] = await getJson("reverse/v4", { lat, lng, display_type: "1" });
return nearest ? { display: nearest.display, lat: nearest.lat, lng: nearest.lng } : null;
}
import os
import requests
KEY = os.environ["VIETMAP_API_KEY"]
API = "https://maps.vietmap.vn/api"
def get_json(path, params):
resp = requests.get(f"{API}/{path}", params={"apikey": KEY, **params}, timeout=10)
resp.raise_for_status()
return resp.json()
def suggest(text, focus=None):
"""Suggestions while typing. focus: the user's "lat,lng", if known."""
# display_type=5: new format, old one in data_old
results = get_json("autocomplete/v4", {"text": text, "focus": focus, "display_type": 5})
return [{"ref_id": r["ref_id"], "display": r["display"]} for r in results]
def resolve(ref_id):
"""The user picked a suggestion: coordinates and address parts for the order."""
p = get_json("place/v4", {"refid": ref_id})
keys = ("display", "lat", "lng", "hs_num", "street", "ward_id", "ward", "city_id", "city")
return {k: p[k] for k in keys}
def pin_to_address(lat, lng):
"""The user dragged the pin: coordinates -> nearest address."""
results = get_json("reverse/v4", {"lat": lat, "lng": lng, "display_type": 1})
return results[0] if results else None
Build a delivery address field with suggestions for my checkout page, using the VIETMAP APIs.
My server has three endpoints that call VIETMAP with the services key:
1. Suggest: GET https://maps.vietmap.vn/api/autocomplete/v4 (text, focus, display_type=5) -> list of {ref_id, display}
2. Pick: GET https://maps.vietmap.vn/api/place/v4 (refid) -> display, lat, lng, hs_num, street, ward_id, ward, city_id, city
3. Drag pin: GET https://maps.vietmap.vn/api/reverse/v4 (lat, lng, display_type=1) -> nearest address
In the browser: call the suggest endpoint only with at least 2 characters and after the user stops typing for 300 ms.
Requirements:
- Read the API key from the VIETMAP_API_KEY environment variable on the server; never send it to the browser.
- Check the HTTP status (401: wrong key, 423: quota used up or API not enabled).
- Read the docs below first. Use only parameters and response fields documented there.
Docs:
- https://maps.vietmap.vn/docs/map-api/use-cases/checkout-address-guide/index.txt
- https://maps.vietmap.vn/docs/map-api/autocomplete-version/autocomplete-v4/index.txt
- https://maps.vietmap.vn/docs/map-api/place-v4/index.txt
- https://maps.vietmap.vn/docs/assets/agents/search-geocoding.txt
In the browser: send requests when the user stops typing¶
The code below sends a request after the user stops typing for 300 ms, which saves transactions:
// Browser: call your own server's endpoint, not VIETMAP directly
const input = document.querySelector("#address");
let timer;
input.addEventListener("input", () => {
clearTimeout(timer);
const text = input.value.trim();
if (text.length < 2) return; // Autocomplete needs at least 2 characters
timer = setTimeout(async () => {
const res = await fetch(`/address/suggest?text=${encodeURIComponent(text)}`);
showSuggestions(await res.json()); // your function that renders the list
}, 300); // call once the user has stopped typing for 300 ms
});
To show a map with a pin, use VietMap GL JS as in Quickstart, step 4 with a draggable marker. When the pin is dropped, send its coordinates to your Reverse endpoint.
Old and new addresses¶
Autocomplete v4 accepts addresses in the old and the new administrative units. The code above uses display_type=5: the new address, with the old version in data_old. The other values are on Autocomplete v4.
For new orders, store the address in the new format with ward_id, city_id and the coordinates. Stored old addresses can be converted with the Address Migration API.
Related APIs¶
- Geocode v4 — coordinates for a whole address string in one call, for example an address pasted from elsewhere.
- Logistics and delivery — dispatch and route optimization for a fleet.
- Error codes — handling
401,423and429.