# Map matching API — Vietmap API Playground

> Làm sạch dữ liệu GPS theo đường đi thực tế với dữ liệu bản đồ. Giải pháp lý tưởng cho các ứng dụng giám sát, theo dõi đơn hàng, hoặc quản lý người dùng.

Map Matching API (match-tolls) làm sạch dữ liệu GPS bằng cách khớp một chuỗi điểm GPS — thường lệch và thưa — vào đúng con đường xe đã đi, và cho biết xe đã qua những trạm thu phí nào cùng mức phí theo loại xe (từ loại 1 đến loại 5). Dữ liệu gửi lên là danh sách tọa độ theo thứ tự thời gian trong body JSON, dạng [kinh độ, vĩ độ].

Dùng để làm gì:
- Đối soát phí cầu đường cho đội xe.
- Vẽ lại hành trình thật từ dữ liệu thiết bị giám sát.
- Tính quãng đường đã chạy chính xác hơn so với nối điểm GPS.
- Phát hiện xe đi sai tuyến đã giao.

- Trang tương tác: https://tools.vietmap.vn/playground/map-matching
- Endpoint: `POST /api/match-tolls` trên `https://maps.vietmap.vn`
- Tài liệu chính thức: https://maps.vietmap.vn/docs/map-api/match-tolls/
- API key: mọi request cần tham số `apikey`. Code mẫu dùng `YOUR_API_KEY` làm chỗ giữ key — khi tích hợp, đọc key từ biến môi trường (ví dụ `VIETMAP_API_KEY`). Lấy key tại https://maps.vietmap.vn/console-v2/consumers
- Mã lỗi: `401` sai API key · `403` key bị giới hạn domain/IP · `423` API chưa bật cho consumer của key, hoặc hết credit (phản hồi có "exceeded credit") · `429` vượt giới hạn tần suất.

## Code mẫu

### cURL

```bash
curl -X POST 'https://maps.vietmap.vn/api/match-tolls?apikey=YOUR_API_KEY&vehicle=1' \
  -H 'Content-Type: application/json' \
  -d '[
  [
    106.6538842265694,
    10.76272759672899
  ],
  [
    106.65327405390536,
    10.762410814059304
  ],
  [
    106.65270927200363,
    10.762785866195022
  ],
  [
    106.652236,
    10.763346
  ],
  [
    106.65184,
    10.763564
  ],
  [
    106.651296,
    10.763603
  ],
  [
    106.651313,
    10.76329
  ],
  [
    106.651281,
    10.7628
  ],
  [
    106.650694,
    10.762969
  ],
  [
    106.6498,
    10.763475
  ],
  [
    106.649074,
    10.763686
  ],
  [
    106.648454,
    10.764128
  ],
  [
    106.64823,
    10.764644
  ],
  [
    106.647774,
    10.764902
  ],
  [
    106.647289,
    10.76501
  ],
  [
    106.64681,
    10.765064
  ],
  [
    106.64627,
    10.765323
  ],
  [
    106.645936,
    10.765663
  ],
  [
    106.645447,
    10.765917
  ],
  [
    106.644988,
    10.766128
  ],
  [
    106.644608,
    10.766234
  ],
  [
    106.644225,
    10.766287
  ]
]'
```

### JavaScript

```javascript
// Khi đưa vào sản phẩm, đọc key từ biến môi trường thay vì ghi cứng.
const API_KEY = "YOUR_API_KEY";

const params = new URLSearchParams([
  ["apikey", API_KEY],
  ["vehicle", "1"],
]);

const body = [
  [
    106.6538842265694,
    10.76272759672899
  ],
  [
    106.65327405390536,
    10.762410814059304
  ],
  [
    106.65270927200363,
    10.762785866195022
  ],
  [
    106.652236,
    10.763346
  ],
  [
    106.65184,
    10.763564
  ],
  [
    106.651296,
    10.763603
  ],
  [
    106.651313,
    10.76329
  ],
  [
    106.651281,
    10.7628
  ],
  [
    106.650694,
    10.762969
  ],
  [
    106.6498,
    10.763475
  ],
  [
    106.649074,
    10.763686
  ],
  [
    106.648454,
    10.764128
  ],
  [
    106.64823,
    10.764644
  ],
  [
    106.647774,
    10.764902
  ],
  [
    106.647289,
    10.76501
  ],
  [
    106.64681,
    10.765064
  ],
  [
    106.64627,
    10.765323
  ],
  [
    106.645936,
    10.765663
  ],
  [
    106.645447,
    10.765917
  ],
  [
    106.644988,
    10.766128
  ],
  [
    106.644608,
    10.766234
  ],
  [
    106.644225,
    10.766287
  ]
];

const response = await fetch(`https://maps.vietmap.vn/api/match-tolls?${params}`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(body),
});
if (!response.ok) {
  throw new Error(`Vietmap ${response.status}: ${await response.text()}`);
}
const data = await response.json();
console.log(data);
```

### Python

```python
import requests

# Khi đưa vào sản phẩm, đọc key từ biến môi trường thay vì ghi cứng.
API_KEY = "YOUR_API_KEY"

params = [
    ("apikey", API_KEY),
    ("vehicle", "1"),
]

body = [
    [
        106.6538842265694,
        10.76272759672899,
    ],
    [
        106.65327405390536,
        10.762410814059304,
    ],
    [
        106.65270927200363,
        10.762785866195022,
    ],
    [
        106.652236,
        10.763346,
    ],
    [
        106.65184,
        10.763564,
    ],
    [
        106.651296,
        10.763603,
    ],
    [
        106.651313,
        10.76329,
    ],
    [
        106.651281,
        10.7628,
    ],
    [
        106.650694,
        10.762969,
    ],
    [
        106.6498,
        10.763475,
    ],
    [
        106.649074,
        10.763686,
    ],
    [
        106.648454,
        10.764128,
    ],
    [
        106.64823,
        10.764644,
    ],
    [
        106.647774,
        10.764902,
    ],
    [
        106.647289,
        10.76501,
    ],
    [
        106.64681,
        10.765064,
    ],
    [
        106.64627,
        10.765323,
    ],
    [
        106.645936,
        10.765663,
    ],
    [
        106.645447,
        10.765917,
    ],
    [
        106.644988,
        10.766128,
    ],
    [
        106.644608,
        10.766234,
    ],
    [
        106.644225,
        10.766287,
    ],
]

response = requests.post("https://maps.vietmap.vn/api/match-tolls", params=params, json=body, timeout=60)
response.raise_for_status()
print(response.json())
```

## AI prompt

Prompt soạn sẵn để giao cho trợ lý lập trình (ChatGPT, Claude, Copilot…) viết code tích hợp API này:

````text
Tôi cần tích hợp Map Matching (match-tolls) API của Vietmap vào ứng dụng của mình.

Tài liệu chính thức: https://maps.vietmap.vn/docs/map-api/match-tolls/

Đây là một request mẫu đã chạy được trên Vietmap API Playground:

POST https://maps.vietmap.vn/api/match-tolls?apikey=YOUR_API_KEY&vehicle=1

Body (JSON):
```json
[
  [
    106.6538842265694,
    10.76272759672899
  ],
  [
    106.65327405390536,
    10.762410814059304
  ],
  [
    106.65270927200363,
    10.762785866195022
  ],
  [
    106.652236,
    10.763346
  ],
  [
    106.65184,
    10.763564
  ],
  [
    106.651296,
    10.763603
  ],
  [
    106.651313,
    10.76329
  ],
  [
    106.651281,
    10.7628
  ],
  [
    106.650694,
    10.762969
  ],
  [
    106.6498,
    10.763475
  ],
  [
    106.649074,
    10.763686
  ],
  [
    106.648454,
    10.764128
  ],
  [
    106.64823,
    10.764644
  ],
  [
    106.647774,
    10.764902
  ],
  [
    106.647289,
    10.76501
  ],
  [
    106.64681,
    10.765064
  ],
  [
    106.64627,
    10.765323
  ],
  [
    106.645936,
    10.765663
  ],
  [
    106.645447,
    10.765917
  ],
  [
    106.644988,
    10.766128
  ],
  [
    106.644608,
    10.766234
  ],
  [
    106.644225,
    10.766287
  ]
]
```

Tham số đang dùng:
- vehicle = 1

Hãy viết code bằng [ngôn ngữ / framework của tôi] để gọi API này, với các yêu cầu:
1. Đọc API key từ biến môi trường VIETMAP_API_KEY, không ghi cứng trong code.
2. Truyền tham số qua query string đúng như request mẫu; tham số lặp lại (như `point`) phải giữ nguyên thứ tự.
3. Xử lý lỗi theo mã HTTP của Vietmap:
   - 401: API key sai hoặc đã bị thu hồi.
   - 403: key bị giới hạn theo domain / IP không khớp.
   - 423: API chưa được bật cho consumer của key, HOẶC tài khoản hết credit — phân biệt bằng nội dung phản hồi (có cụm "exceeded credit" là hết credit).
   - 429: vượt giới hạn tần suất — thử lại với backoff tăng dần.
4. Đặt timeout cho request, và định nghĩa kiểu dữ liệu (type / interface / dataclass) cho phản hồi.

Nếu không chắc tên một trường, tra trong tài liệu ở link trên thay vì đoán.
````

## Mở lại đúng request này trong Playground

https://tools.vietmap.vn/playground/map-matching?point=10.76272759672899,106.6538842265694&point=10.762410814059304,106.65327405390536&point=10.762785866195022,106.65270927200363&point=10.763346,106.652236&point=10.763564,106.65184&point=10.763603,106.651296&point=10.76329,106.651313&point=10.7628,106.651281&point=10.762969,106.650694&point=10.763475,106.6498&point=10.763686,106.649074&point=10.764128,106.648454&point=10.764644,106.64823&point=10.764902,106.647774&point=10.76501,106.647289&point=10.765064,106.64681&point=10.765323,106.64627&point=10.765663,106.645936&point=10.765917,106.645447&point=10.766128,106.644988&point=10.766234,106.644608&point=10.766287,106.644225&vehicle=1
