SDKOptimize
API Reference
Tài liệu kỹ thuật cho dịch vụ tối ưu lộ trình Optimize tại
https://live.fleetwork.vn/api/v1/optimize.
Base Path
POST https://live.fleetwork.vn/api/v1/optimize
Content-Type: application/json
X-API-Key: <your_api_key>API này nhận payload JSON theo format đầu vào và trả về kết quả tối ưu dưới dạng JSON.
Phạm vi tài liệu
Tài liệu này mô tả:
- schema request cho bài toán Vehicle Routing Problem (Optimize)
- schema response của kết quả tối ưu
- ý nghĩa các object, field và ràng buộc dữ liệu
- các quy ước đơn vị đo và format thời gian
Tài liệu mô tả 2 chế độ xử lý:
- Solving mode: tối ưu lộ trình mặc định
- Plan mode: tính ETA cho route đã được mô tả trước
Tài liệu này tập trung vào payload contract dùng chung cho hai chế độ. Cách backend /api/v1/optimize chọn mode thực thi phụ thuộc implementation của dịch vụ triển khai.
Authentication
API xác thực qua request header:
| Header | Giá trị |
|---|---|
X-API-Key | API key của account |
Content-Type | application/json |
⚠️ Không cần truyền
X-Internal-TokenhayX-Account-Id— gateway tự inject.
Sai hoặc thiếu key sẽ trả về 401 Unauthorized (no body — ASP.NET default).
Quy ước dữ liệu
| Quy ước | Giá trị |
|---|---|
| Thứ tự tọa độ | [lon, lat] |
| Thời gian | seconds |
| Khoảng cách | meters |
time_window | [start, end] với cả 2 đầu mút đều inclusive |
cost trong output | cost nội bộ dùng cho objective optimization |
task | có thể là job, pickup hoặc delivery |
Mục lục
- 1. Request Overview
- 2. Jobs
- 3. Shipments
- 4. Vehicles
- 5. Matrices
- 6. Response Overview
- 7. Summary
- 8. Routes và Steps
- 9. Violations
- 10. Error Responses
- 11. Ví dụ Request/Response
- 12. TypeScript Helper
1. Request Overview
Request body là JSON object mô tả bài toán tối ưu.
| Key | Required | Type | Mô tả |
|---|---|---|---|
jobs | No | job[] | Danh sách điểm giao việc độc lập. |
shipments | No | shipment[] | Danh sách cặp pickup-delivery. |
vehicles | Yes | vehicle[] | Danh sách xe khả dụng để tối ưu. |
matrices | No | object | Custom matrices theo từng profile. |
matrix | No | number[][] | Legacy field đã deprecated. |
Ví dụ request tối thiểu
{
"jobs": [
{
"id": 1,
"location": [106.70098, 10.77689],
"service": 300
}
],
"vehicles": [
{
"id": 1,
"start": [106.66017, 10.76262],
"end": [106.66017, 10.76262]
}
]
}Validation cơ bản
vehiclesphải có ít nhất 1 phần tửidcủajobkhông được trùng nhaupickup.idvàdelivery.idtrong shipments không được trùng nhau cùng loại- nếu dùng custom matrices thì phải khai báo
*_indextương ứng - nếu không dùng custom matrices thì phải khai báo tọa độ thật qua
location,start,end
2. Jobs
job mô tả một điểm công việc độc lập cần được một xe ghé qua.
idintegerYesID duy nhất của job.descriptionstringNoMô tả job.location[lon, lat]Cond.Tọa độ job. Bắt buộc nếu không dùng custom matrix.location_indexintegerCond.Index dòng/cột trong custom matrices. Bắt buộc nếu dùng matrix.setupintegerNoThời gian setup, mặc định0.serviceintegerNoThời gian phục vụ, mặc định0.setup_per_typeobjectNoMap theovehicle.typeđể overridesetup.service_per_typeobjectNoMap theovehicle.typeđể overrideservice.deliveryinteger[]NoNhu cầu delivery đa chiều.pickupinteger[]NoNhu cầu pickup đa chiều.skillsinteger[]NoTập kỹ năng bắt buộc.priorityintegerNoMức ưu tiên từ0đến100, mặc định0.time_windowstime_window[]NoCác khoảng thời gian hợp lệ để bắt đầu service.
Ví dụ job
{
"id": 101,
"description": "Giao hồ sơ chi nhánh A",
"location": [106.70098, 10.77689],
"setup": 60,
"service": 300,
"delivery": [1],
"skills": [2, 7],
"priority": 80,
"time_windows": [[1713402000, 1713405600]]
}Ghi chú
setupchỉ áp dụng khi xe vừa đến một location mới- nếu nhiều task liên tiếp xảy ra cùng vị trí, task sau chỉ tính
service skillscủa job phải là tập con củaskillsxe
3. Shipments
shipment mô tả một cặp công việc có thứ tự bắt buộc: pickup trước, delivery sau.
pickupshipment_stepYesĐiểm lấy hàng.deliveryshipment_stepYesĐiểm giao hàng.amountinteger[]NoTải trọng đa chiều của shipment.skillsinteger[]NoKỹ năng bắt buộc.priorityintegerNoMức ưu tiên0..100.
3.1 Shipment Step
idintegerYesID của step.descriptionstringNoMô tả step.location[lon, lat]Cond.Tọa độ step.location_indexintegerCond.Chỉ số matrix tương ứng.setupintegerNoSetup duration, mặc định0.serviceintegerNoService duration, mặc định0.setup_per_typeobjectNoOverride setup theo loại xe.service_per_typeobjectNoOverride service theo loại xe.time_windowstime_window[]NoCác slot thời gian hợp lệ.
Ví dụ shipment
{
"pickup": {
"id": 201,
"location": [106.66017, 10.76262],
"service": 180
},
"delivery": {
"id": 202,
"location": [106.70098, 10.77689],
"service": 240
},
"amount": [5],
"skills": [3],
"priority": 90
}Ghi chú
- backend sẽ báo lỗi nếu
deliveryxuất hiện trướcpickup shipmentphù hợp với bài toán lấy hàng - giao hàng có ràng buộc precedence
4. Vehicles
vehicle mô tả nguồn lực có thể dùng để phục vụ jobs/shipments.
idintegerYesID xe.profilestringNoRouting profile:car|truck|motorcycle, mặc địnhcar.descriptionstringNoMô tả xe.start[lon, lat]Cond.Điểm xuất phát.start_indexintegerCond.Index trong matrix chostart.end[lon, lat]Cond.Điểm kết thúc.end_indexintegerCond.Index trong matrix choend.capacityinteger[]NoTải trọng đa chiều.costscostNoChi phí vận hành xe.skillsinteger[]NoTập kỹ năng của xe.typestringNoLoại xe.time_windowtime_windowNoGiờ làm việc hợp lệ.breaksbreak[]NoDanh sách điểm nghỉ.speed_factornumberNoHệ số nhân cho travel time,(0, 5].max_tasksintegerNoSố task tối đa.max_travel_timeintegerNoTravel time tối đa.max_distanceintegerNoQuãng đường tối đa.stepsvehicle_step[]NoRoute custom cho plan mode hoặc starting solution.
4.1 Cost Object
fixedintegerNoChi phí cố định nếu xe được dùng.per_hourintegerNoChi phí cho 1 giờ di chuyển.per_task_hourintegerNoChi phí cho 1 giờ task time (setup + service).per_kmintegerNoChi phí cho 1 km di chuyển.
Nếu dùng
per_hourkhác mặc định, không nên đồng thời dùng custom cost matrix cho cùng vehicle vì contract gốc xem đó là không nhất quán.
4.2 Break Object
idintegerYesID break trong xe.time_windowstime_window[]NoSlot hợp lệ để bắt đầu nghỉ.serviceintegerNoThời gian nghỉ.descriptionstringNoMô tả break.max_loadinteger[]NoLoad tối đa cho phép khi break xảy ra.
4.3 Vehicle Step
typestringYesstart,job,pickup,delivery,break,end.idintegerCond.ID task/break nếutypekhông phảistarthoặcend.service_atintegerNoHard constraint cho thời điểm service.service_afterintegerNoLower bound cho service time.service_beforeintegerNoUpper bound cho service time.
Ví dụ vehicle
{
"id": 1,
"profile": "car",
"description": "Xe tải 1.5 tấn",
"start": [106.66017, 10.76262],
"end": [106.66017, 10.76262],
"capacity": [20],
"skills": [2, 3, 7],
"time_window": [1713398400, 1713430800],
"costs": {
"fixed": 100000,
"per_hour": 3600,
"per_km": 1500
},
"breaks": [
{
"id": 1,
"time_windows": [[1713412800, 1713416400]],
"service": 1800,
"description": "Nghỉ trưa"
}
]
}Ghi chú
startvàendlà optional miễn là có ít nhất một trong hai- nếu bỏ
end, route kết thúc ở task cuối cùng được phục vụ - nếu bỏ
start, route bắt đầu ở task đầu tiên được gán - nếu
startvàendgiống nhau, đó là round trip
5. Matrices
matrices cho phép truyền custom matrices theo từng profile của xe.
| Key | Type | Mô tả |
|---|---|---|
durations | number[][] | Travel-time matrix dùng cho timing constraints. |
distances | number[][] | Distance matrix. Muốn dùng field này phải có durations. |
costs | number[][] | Cost matrix cho objective evaluation. |
Ví dụ
{
"matrices": {
"car": {
"durations": [
[0, 14],
[21, 0]
]
},
"bike": {
"durations": [
[0, 57],
[43, 0]
]
}
}
}Ghi chú
- nếu có đủ custom matrices cho mọi
profileliên quan thìlocation,start,endcó thể bỏ qua - khi đó cần dùng
location_index,start_index,end_index - nếu có
durationsnhưng không códistances, backend vẫn có thể cần truy xuất distance riêng nếu bài toán yêu cầu
6. Response Overview
Response trả về JSON object mô tả kết quả tối ưu.
| Key | Type | Mô tả |
|---|---|---|
code | integer | Trạng thái xử lý. 0 là thành công. |
error | string | Thông báo lỗi nếu code != 0. |
summary | object | Tổng hợp chỉ số toàn cục của solution. |
unassigned | object[] | Danh sách task không được gán route, kèm reason. |
routes | route[] | Danh sách route tối ưu. |
6.1 Status Code
| Code | Ý nghĩa |
|---|---|
0 | Thành công, không có lỗi. |
1 | Internal error. |
2 | Input error. |
3 | Routing error. |
7. Summary
summary là phần tổng hợp của toàn bộ nghiệm.
costintegerTổng cost của tất cả routes.routesintegerSố route được tạo.unassignedintegerSố task không được phục vụ.setupintegerTổng setup time.serviceintegerTổng service time.durationintegerTổng travel time.waiting_timeintegerTổng waiting time.priorityintegerTổng priority của task đã được gán.violationsviolation[]Vi phạm ở cấp solution/route.deliveryinteger[]Tổng delivery.pickupinteger[]Tổng pickup.distanceintegerTổng khoảng cách, nếu backend có trả distance.computing_timesobjectThước đo thời gian xử lý nội bộ của engine.
computing_times
loadingintegerThời gian load dữ liệu (ms).solvingintegerThời gian giải bài toán (ms).routingintegerThời gian gọi routing engine (ms).
8. Routes và Steps
8.1 Route Object
vehicleintegerID xe được gán route.stepsstep[]Các bước trong route.costintegerCost của route.setupintegerTổng setup time của route.serviceintegerTổng service time của route.durationintegerTổng travel time của route.waiting_timeintegerTổng waiting time của route.priorityintegerTổng priority của task trong route.violationsviolation[]Vi phạm của route.deliveryinteger[]Delivery load của route.pickupinteger[]Pickup load của route.descriptionstringVehicle description nếu có trong input.geometrystringPolyline encoded, nếu backend bật geometry.distanceintegerTổng quãng đường route.
8.2 Step Object
typestringstart,job,pickup,delivery,break,end.arrivalintegerETA tại step.durationintegerTravel time tích lũy đến step này.setupintegerSetup time tại step.serviceintegerService time tại step.waiting_timeintegerWaiting time trước khi bắt đầu service.violationsviolation[]Vi phạm phát sinh tại step.descriptionstringMô tả step, nếu có từ input.location[lon, lat]Tọa độ step, nếu input có cung cấp.location_indexintegerIndex matrix, nếu có.idintegerID task/break tương ứng.loadinteger[]Tải trọng xe sau khi hoàn tất step.distanceintegerQuãng đường tích lũy đến step.
Ghi chú về steps
- trong solving mode, route sẽ được backend tối ưu tự động
- trong plan mode,
vehicle.stepsmô tả route dự kiến và backend chủ yếu tính ETA/violations - trong solving mode, nếu truyền
vehicle.steps, đó được xem như starting solution và phải hợp lệ với mọi constraint
9. Violations
violation mô tả một ràng buộc bị vi phạm.
causestringNguyên nhân vi phạm.durationintegerMức lệch thời gian nếu làlead_timehoặcdelay.
9.1 Các giá trị cause
| Cause | Ý nghĩa |
|---|---|
delay | Service bắt đầu muộn hơn time window cho phép. |
lead_time | Service bắt đầu sớm hơn time window cho phép. |
load | Tải trọng vượt capacity. |
max_tasks | Số task vượt max_tasks. |
skills | Xe không có đủ skills. |
precedence | Delivery xảy ra trước pickup hoặc thiếu cặp tương ứng. |
missing_break | Bỏ qua break bắt buộc trong custom route. |
max_travel_time | Vượt travel time tối đa. |
max_distance | Vượt distance tối đa. |
max_load | Load tại thời điểm break vượt max_load. |
Trong regular optimization,
violationsthường rỗng. Chúng có ý nghĩa rõ nhất khi backend chạy theo logic plan mode để kiểm tra route có sẵn.
10. Error Responses
HTTP 400 — Input lỗi (OptimizeApi validation)
{
"error": "INPUT_ERROR",
"message": "Request body is empty",
"code": 2
}{
"error": "INPUT_ERROR",
"message": "Request body is not valid JSON",
"code": 2
}HTTP 401 — Unauthorized
Thiếu hoặc sai X-API-Key.
// (no body — ASP.NET default 401)HTTP 400/500 — Engine error (forwarded)
Khi engine trả lỗi, OptimizeApi forward nguyên:
{
"code": 2,
"error": "Invalid jobs: location missing for job 3."
}code | Ý nghĩa |
|---|---|
0 | OK |
1 | Internal error |
2 | Input validation error |
Unassigned jobs
Khi có job không giao được, response sẽ chứa mảng unassigned kèm lý do:
{
"unassigned": [
{
"id": 5,
"type": "job",
"location": [106.72, 10.75],
"reason": "No vehicle with matching skills"
}
]
}11. Ví dụ Request/Response
11.1 Ví dụ Request
Bài toán 1 xe, 3 điểm giao
curl -X POST https://live.fleetwork.vn/api/v1/optimize \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"vehicles": [
{
"id": 1,
"profile": "car",
"start": [106.6297, 10.8231],
"end": [106.6297, 10.8231]
}
],
"jobs": [
{ "id": 1, "location": [106.6602, 10.7626], "service": 300 },
{ "id": 2, "location": [106.7010, 10.7769], "service": 300 },
{ "id": 3, "location": [106.6893, 10.8018], "service": 180 }
]
}'Ví dụ loại service (theo thời gian phục vụ)
Quy ước ví dụ:
service: 120-> giao nhanh (2 phút)service: 300-> giao tiêu chuẩn (5 phút)service: 900-> giao cồng kềnh (15 phút)
curl -X POST https://live.fleetwork.vn/api/v1/optimize \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"vehicles": [
{
"id": 1,
"profile": "car",
"start": [106.6297, 10.8231],
"end": [106.6297, 10.8231]
}
],
"jobs": [
{ "id": 101, "location": [106.6602, 10.7626], "service": 120 },
{ "id": 102, "location": [106.7010, 10.7769], "service": 300 },
{ "id": 103, "location": [106.6893, 10.8018], "service": 900 }
]
}'11.2 Ví dụ Response 200 OK
{
"code": 0,
"summary": {
"cost": 3600,
"unassigned": 0,
"delivery": [0],
"pickup": [0],
"service": 300,
"duration": 3300,
"waiting_time": 0,
"distance": 12500,
"priority": 0,
"violations": [],
"computing_times": {
"loading": 2,
"solving": 45,
"routing": 10
}
},
"unassigned": [],
"routes": [
{
"vehicle": 1,
"cost": 3600,
"service": 300,
"duration": 3300,
"waiting_time": 0,
"distance": 12500,
"priority": 0,
"violations": [],
"delivery": [0],
"pickup": [0],
"steps": [
{
"type": "start",
"location": [106.6297, 10.8231],
"arrival": 0,
"duration": 0,
"distance": 0
},
{
"type": "job",
"id": 1,
"location": [106.701, 10.7769],
"arrival": 2800,
"duration": 3300,
"distance": 12500,
"load": [0]
},
{
"type": "end",
"location": [106.6297, 10.8231],
"arrival": 3600,
"duration": 3600,
"distance": 15200
}
]
}
]
}Lưu ý triển khai
- nếu bài toán có ràng buộc tải trọng, hãy khai báo đồng nhất giữa
vehicle.capacity,job.delivery/job.pickup, hoặcshipment.amount - nếu backend trả về distance hoặc geometry, cần có cấu hình tương ứng ở lớp routing engine
- nếu dùng timestamp tuyệt đối trong
time_window, các giá trịarrivaltrong output cũng được hiểu là timestamp tuyệt đối - nếu dùng giá trị tương đối, toàn bộ
arrivalsẽ là thời gian tương đối theo planning horizon - engine forward nguyên response — không bọc thêm wrapper
- timeout khuyến nghị cho bài toán lớn là 5 phút