GOFA Places · B2B API
Tích hợp tìm kiếm địa điểm Việt Nam vào sản phẩm của bạn.
Hai endpoint HTTP giúp gợi ý địa điểm khi người dùng nhập và lấy thông tin chi tiết sau khi họ chọn một kết quả.
GOFA_PLACES_BASE_URL
Địa chỉ API và API key được gửi qua email sau khi hồ sơ đăng ký được phê duyệt.
01 · Bắt đầu
Xác thực
Các yêu cầu AutoComplete, Detail và kiểm tra hạn mức cần gửi API key trong header X-API-Key. Endpoint /healthz không yêu cầu xác thực.
X-API-Key: YOUR_API_KEY
02 · Thử request đầu tiên
Quick start
Đặt địa chỉ API, API key và định danh người dùng vào các biến môi trường GOFA_PLACES_BASE_URL, GOFA_PLACES_API_KEY và GOFA_PLACES_USER_ID. Đoạn lệnh dưới đây tạo một session tìm kiếm, gọi AutoComplete rồi dùng ngay place_id đã chọn để gọi Detail. Máy chạy ví dụ cần có jq và uuidgen.
: "${GOFA_PLACES_BASE_URL:?Chưa đặt GOFA_PLACES_BASE_URL}"
: "${GOFA_PLACES_API_KEY:?Chưa đặt GOFA_PLACES_API_KEY}"
: "${GOFA_PLACES_USER_ID:?Chưa đặt GOFA_PLACES_USER_ID}"
session_id=$(uuidgen)
autocomplete_response=$(curl --silent --show-error --fail-with-body --get \
"${GOFA_PLACES_BASE_URL}/v5/Place/AutoComplete" \
--header "X-API-Key: ${GOFA_PLACES_API_KEY}" \
--header "X-id: ${GOFA_PLACES_USER_ID}" \
--data-urlencode 'input=Số 1 đường giáp hải phường bắc giang' \
--data-urlencode "session_id=${session_id}" \
--data-urlencode 'limit=8')
printf '%s\n' "$autocomplete_response" | jq .
place_id=$(printf '%s\n' "$autocomplete_response" | jq -er '.predictions[0].place_id')
curl --silent --show-error --fail-with-body --get \
"${GOFA_PLACES_BASE_URL}/v5/Place/Detail" \
--header "X-API-Key: ${GOFA_PLACES_API_KEY}" \
--data-urlencode "place_id=${place_id}" | jq .
/v5/Place/AutoComplete
Trả về danh sách địa điểm phù hợp với nội dung người dùng đang nhập. Khi truyền cả lat và lng, kết quả có thể kèm khoảng cách tới vị trí ưu tiên.
Tham số yêu cầu
| Tham số | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
input | string | Có | Nội dung tìm kiếm, không được để trống. |
lat | number | Không | Vĩ độ ưu tiên. Phải đi cùng lng. |
lng | number | Không | Kinh độ ưu tiên. Phải đi cùng lat. |
limit | integer | Không | Số kết quả từ 1–20. Mặc định là 8. |
Cá nhân hóa kết quả gợi ý
Nên gửi đủ X-id và session_id trên mọi yêu cầu AutoComplete. Hai giá trị này giúp GOFA giữ đúng ngữ cảnh của lượt tìm kiếm và cải thiện thứ tự gợi ý cho từng người dùng.
Header X-idĐịnh danh ổn định của cùng một người dùng qua nhiều phiên. Dùng một chuỗi ID do ứng dụng của bạn tạo. Không gửi email hoặc số điện thoại trong X-id.
session_idUUID mới cho mỗi lượt tìm kiếm. Giữ nguyên giá trị này trong toàn bộ các request khi người dùng tiếp tục nhập và chọn kết quả. Không tạo session mới cho mỗi ký tự.
Ví dụ: Người dùng nhập lần lượt “giáp”, “giáp hải” rồi chọn một kết quả. Các yêu cầu AutoComplete trong lượt tìm kiếm này dùng cùng X-id và session_id. Yêu cầu Detail dùng nguyên place_id của kết quả đã chọn.
Phản hồi 200 OK
{
"predictions": [
{
"description": "số 1 Giáp Hải, Phường Xương Giang, Thành Phố Bắc Giang, Tỉnh Bắc Giang",
"matched_substrings": [
{ "length": 1, "offset": 3 },
{ "length": 5, "offset": 28 },
{ "length": 5, "offset": 49 },
{ "length": 5, "offset": 65 }
],
"place_id": "gofa_example_place_id_001",
"reference": "gofa_example_place_id_001",
"structured_formatting": {
"main_text": "số 1 Giáp Hải",
"main_text_matched_substrings": [
{ "length": 1, "offset": 3 }
],
"secondary_text": "Phường Xương Giang, Thành Phố Bắc Giang, Tỉnh Bắc Giang",
"secondary_text_matched_substrings": [
{ "length": 5, "offset": 13 },
{ "length": 5, "offset": 34 },
{ "length": 5, "offset": 50 }
]
},
"has_children": false,
"plus_code": {
"compound_code": "+CEOWFP Phường Xương Giang, Thành Phố Bắc Giang, Tỉnh Bắc Giang",
"global_code": "1BDC1+CEOWFP"
},
"compound": {
"district": "Bắc Giang",
"commune": "Xương Giang",
"province": "Bắc Giang"
},
"terms": [
{ "offset": 0, "value": "số 1 Giáp Hải" },
{ "offset": 19, "value": "Phường Xương Giang" },
{ "offset": 44, "value": "Thành Phố Bắc Giang" },
{ "offset": 70, "value": "Tỉnh Bắc Giang" }
],
"types": ["street_address", "subpremise"],
"distance_meters": null
}
],
"execution_time": "",
"status": "OK"
}
Lưu ý: distance_meters là null khi không có vị trí để tính khoảng cách. Hãy chuyển nguyên vẹn place_id sang yêu cầu Detail.
Trường dữ liệu của prediction
| Trường | Kiểu | Ý nghĩa |
|---|---|---|
description | string | Địa chỉ đầy đủ dùng để hiển thị. |
matched_substrings | array | Các đoạn khớp trong description, mỗi phần tử có offset và length. |
place_id | string | Định danh phải chuyển nguyên vẹn sang Place Detail. |
reference | string | Định danh tham chiếu của kết quả. Không dùng thay cho place_id trong luồng tích hợp. |
structured_formatting | object | Tên chính, địa chỉ phụ và vị trí các đoạn khớp để dựng giao diện gợi ý. |
has_children | boolean | Cho biết kết quả còn cấp địa chỉ con. |
plus_code | object | Mã vị trí gồm compound_code và global_code. |
compound | object | Thông tin district, commune và province. |
terms | array | Các thành phần địa chỉ cùng vị trí bắt đầu trong chuỗi. |
distance_meters | number | null | Khoảng cách theo mét, hoặc null khi không tính được. |
/v5/Place/Detail
Lấy địa chỉ chuẩn hóa và tọa độ của kết quả đã chọn. Hãy chuyển tiếp nguyên vẹn place_id nhận từ AutoComplete.
Tham số yêu cầu
| Tham số | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|
place_id | string | Có | place_id từ prediction đã chọn. |
curl --get "${GOFA_PLACES_BASE_URL}/v5/Place/Detail" \
--header "X-API-Key: ${GOFA_PLACES_API_KEY}" \
--data-urlencode "place_id=${place_id}"
Phản hồi 200 OK
{
"result": {
"place_id": "gofa_example_place_id_001",
"formatted_address": "1 Đường Giáp Hải 1, Phường Xương Giang, Thành Phố Bắc Giang, Tỉnh Bắc Giang",
"geometry": {
"location": { "lat": 21.288803, "lng": 106.213579 }
},
"plus_code": {
"compound_code": "+CEOWFP Phường Xương Giang, Thành Phố Bắc Giang, Tỉnh Bắc Giang",
"global_code": "1BDC1+CEOWFP"
},
"compound": {
"district": "Bắc Giang",
"commune": "Xương Giang",
"province": "Bắc Giang"
},
"name": "1 Đường Giáp Hải 1",
"url": "",
"types": ["street_address", "subpremise"]
},
"status": "OK"
}
Lưu ý: Các chuỗi trong plus_code, compound và url có thể rỗng khi thông tin không có sẵn.
Trường dữ liệu của result
| Trường | Kiểu | Ý nghĩa |
|---|---|---|
place_id | string | Định danh địa điểm. |
formatted_address | string | Địa chỉ đầy đủ đã chuẩn hóa. |
geometry.location | object | Tọa độ WGS84 gồm lat và lng. |
plus_code | object | Mã vị trí dạng compound và global. |
compound | object | Thông tin quận hoặc huyện, xã hoặc phường và tỉnh hoặc thành phố. |
name | string | Tên ngắn của địa điểm. |
url | string | Liên kết bản đồ do GOFA cung cấp, có thể rỗng. |
types | string[] | Các loại địa điểm. |
/Account/Quota
Tra cứu hạn mức tháng, số yêu cầu đã sử dụng và số còn lại cho từng endpoint. Yêu cầu này không trừ hạn mức.
curl --silent --show-error --fail-with-body \
"${GOFA_PLACES_BASE_URL}/Account/Quota" \
--header "X-API-Key: ${GOFA_PLACES_API_KEY}" | jq .
Phản hồi 200 OK
{
"status": "ok",
"period": {
"starts_at": "2026-09-01T00:00:00+00:00",
"resets_at": "2026-10-01T00:00:00+00:00"
},
"quota": {
"limit": 2000,
"used": 37,
"remaining": 1963,
"endpoints": [
{ "code": "autocomplete", "name": "Place AutoComplete", "limit": 1500, "used": 30, "remaining": 1470 },
{ "code": "detail", "name": "Place Detail", "limit": 500, "used": 7, "remaining": 493 }
]
}
}
/healthz
Kiểm tra trạng thái hoạt động của dịch vụ.
curl --silent --show-error "${GOFA_PLACES_BASE_URL}/healthz"
Hoạt động bình thường 200 OK
{ "status": "ok" }
Dịch vụ chưa sẵn sàng 503 Service Unavailable
{ "status": "degraded" }
03 · Vận hành ổn định
Quota & rate limit
Mỗi API key có giới hạn tốc độ dùng chung và quota tháng riêng cho từng endpoint theo gói đã được cấp. Các header sau giúp ứng dụng theo dõi phần quota còn lại:
RateLimit-LimitQuota tháng của endpoint đang gọi.
RateLimit-RemainingSố request còn lại trong kỳ hiện tại.
RateLimit-ResetThời điểm reset dưới dạng Unix timestamp.
Retry-AfterSố giây cần chờ; có trong response 429.
04 · Xử lý lỗi
Mã lỗi
| HTTP | Mã lỗi / status | Cách xử lý |
|---|---|---|
400 | INVALID_REQUEST | Kiểm tra tham số yêu cầu và các cặp tham số liên quan. |
401 | missing_api_keyinvalid_api_key | Gửi key trong X-API-Key hoặc thay key đã hết hiệu lực. |
404 | NOT_FOUND | place_id không tồn tại; yêu cầu người dùng tìm và chọn lại. |
429 | rate_limitedquota_exhausted | Tôn trọng Retry-After; liên hệ GOFA nếu cần điều chỉnh gói. |
502 | service_unavailable | Dịch vụ tạm thời không khả dụng; thử lại sau một khoảng chờ tăng dần. |
503 | service_unavailable | Dịch vụ tạm thời không khả dụng; thử lại sau. |
Phản hồi lỗi từ Places API
AutoComplete, HTTP 400:
{
"predictions": [],
"execution_time": "0.21ms",
"status": "INVALID_REQUEST"
}
Detail, HTTP 400:
{
"result": null,
"status": "INVALID_REQUEST"
}
Detail, HTTP 404:
{
"result": null,
"status": "NOT_FOUND"
}
Lỗi xác thực và giới hạn sử dụng
{ "error": "invalid_api_key" }
Sẵn sàng tích hợp?
Places API