GOFA Places API

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ả.

Địa chỉ API 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_KEYGOFA_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ó jquuidgen.

: "${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 .
1AutoCompleteNgười dùng nhập địa điểm
2Chọn kết quả gợi ýLưu nguyên place_id
3Place DetailLấy địa chỉ và tọa độ
GET

/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ả latlng, 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ểuBắt buộcMô tả
inputstringNội dung tìm kiếm, không được để trống.
latnumberKhôngVĩ độ ưu tiên. Phải đi cùng lng.
lngnumberKhôngKinh độ ưu tiên. Phải đi cùng lat.
limitintegerKhôngSố 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-idsession_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-idsession_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_metersnull 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ườngKiểuÝ nghĩa
descriptionstringĐịa chỉ đầy đủ dùng để hiển thị.
matched_substringsarrayCác đoạn khớp trong description, mỗi phần tử có offsetlength.
place_idstringĐịnh danh phải chuyển nguyên vẹn sang Place Detail.
referencestringĐị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_formattingobjectTên chính, địa chỉ phụ và vị trí các đoạn khớp để dựng giao diện gợi ý.
has_childrenbooleanCho biết kết quả còn cấp địa chỉ con.
plus_codeobjectMã vị trí gồm compound_codeglobal_code.
compoundobjectThông tin district, communeprovince.
termsarrayCác thành phần địa chỉ cùng vị trí bắt đầu trong chuỗi.
distance_metersnumber | nullKhoảng cách theo mét, hoặc null khi không tính được.
GET

/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ểuBắt buộcMô tả
place_idstringplace_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, compoundurl có thể rỗng khi thông tin không có sẵn.

Trường dữ liệu của result

TrườngKiểuÝ nghĩa
place_idstringĐịnh danh địa điểm.
formatted_addressstringĐịa chỉ đầy đủ đã chuẩn hóa.
geometry.locationobjectTọa độ WGS84 gồm latlng.
plus_codeobjectMã vị trí dạng compound và global.
compoundobjectThông tin quận hoặc huyện, xã hoặc phường và tỉnh hoặc thành phố.
namestringTên ngắn của địa điểm.
urlstringLiên kết bản đồ do GOFA cung cấp, có thể rỗng.
typesstring[]Các loại địa điểm.
GET

/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 }
    ]
  }
}
GET

/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

HTTPMã lỗi / statusCách xử lý
400INVALID_REQUESTKiểm tra tham số yêu cầu và các cặp tham số liên quan.
401missing_api_key
invalid_api_key
Gửi key trong X-API-Key hoặc thay key đã hết hiệu lực.
404NOT_FOUNDplace_id không tồn tại; yêu cầu người dùng tìm và chọn lại.
429rate_limited
quota_exhausted
Tôn trọng Retry-After; liên hệ GOFA nếu cần điều chỉnh gói.
502service_unavailableDịch vụ tạm thời không khả dụng; thử lại sau một khoảng chờ tăng dần.
503service_unavailableDị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?

Đăng ký quyền truy cập GOFA Places API.

Đăng ký API key