Giới thiệu
Mỗi công ty trong OptiRoutes có một thư mục tệp riêng: các đơn hàng công ty tải lên, các phiếu giao hàng đã ký (POD) kèm ảnh và chữ ký, các tệp xuất tuyến và các báo cáo cuối ngày. Files API cho phép hệ thống của bạn đọc và ghi trực tiếp vào thư mục đó, không cần máy chủ FTP trung gian.
- Địa chỉ:
https://srv2.optiroutes.com/api/v1— chỉ qua HTTPS. - Quyền truy cập: một khóa API do quản lý của công ty tạo trong OptiRoutes, tại Cài đặt → API và tệp. Không cần gửi yêu cầu đến bộ phận hỗ trợ OptiRoutes.
- Mọi loại tệp mà hệ thống đang dùng: CSV, JSON, TXT, XLSX/XLS, PDF và hình ảnh.
- Phản hồi ở dạng JSON, trừ khi tải tệp xuống — khi đó trả về chính tệp.
Bắt đầu trong 3 bước
- Tạo khóa. Trong OptiRoutes, quản lý mở Cài đặt → API và tệp, nhấn Khóa mới, đặt tên (ví dụ "Máy chủ ERP"), chọn quyền và sao chép khóa. Khóa chỉ hiển thị một lần.
- Kiểm tra kết nối.
curl -H "Authorization: Bearer $OPTIROUTES_KEY" https://srv2.optiroutes.com/api/v1/me - Tải xuống các POD đã ký của hôm nay trong một tệp ZIP:
curl -H "Authorization: Bearer $OPTIROUTES_KEY" -o pod.zip "https://srv2.optiroutes.com/api/v1/pod/archive?date=$(date +%F)"
Bảo mật — vui lòng đọc
- Bảo vệ khóa như mật khẩu. Lưu khóa trong kho bí mật hoặc biến môi trường trên máy chủ của bạn. Không bao giờ đặt khóa trong trang web, ứng dụng di động, email, phiếu hỗ trợ hay hệ thống quản lý mã nguồn.
- Quyền tối thiểu. Cấp cho mỗi hệ thống một khóa riêng chỉ với những quyền cần thiết:
pod:read(chỉ POD đã ký),files:read(đọc mọi tệp của công ty),files:write(tải lên đơn hàng và tệp vào hộp thư đến). - Giới hạn địa chỉ. Khi máy chủ của bạn có địa chỉ IP cố định, hãy thêm địa chỉ đó vào khóa ("Địa chỉ được phép"). Lệnh gọi từ bất kỳ địa chỉ nào khác sẽ bị từ chối.
- Hết hạn và luân chuyển. Khóa có thể hết hạn sau một số ngày. Để luân chuyển: tạo khóa mới, chuyển hệ thống của bạn sang khóa đó, rồi thu hồi khóa cũ — không bị gián đoạn.
- Thu hồi ngay khóa có thể đã bị lộ: Cài đặt → API và tệp → Thu hồi. Khóa ngừng hoạt động trong vòng 30 giây.
- Kiểm tra nhật ký. Mọi lệnh gọi đều được ghi lại (thời gian, địa chỉ, tệp, phản hồi) và hiển thị cho quản lý trên cùng màn hình.
- OptiRoutes chỉ lưu dấu vân tay (SHA-256) của mỗi khóa, không bao giờ lưu chính khóa. Kết nối chỉ qua HTTPS (TLS 1.2+).
- Mỗi khóa chỉ truy cập được thư mục của chính công ty mình. Tệp của các công ty khác và các thư mục nội bộ của hệ thống không bao giờ truy cập được.
Xác thực
Gửi khóa trong mọi yêu cầu, bằng một trong các header sau:
Authorization: Bearer opr_2813_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
X-API-Key: opr_2813_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKhóa có dạng opr_2813_… (số công ty, sau đó là 32 ký tự ngẫu nhiên).
Thư mục của công ty
| Thư mục | Nội dung | Bên ghi |
|---|---|---|
orders_files/ | Tệp đơn hàng hằng ngày mà OptiRoutes tải vào: orders_files/YYYY-MM-DD.csv (hoặc .json / .TXT, theo thiết lập trong Cài đặt → Tải dữ liệu). Tệp xuất tuyến: orders_files/routes_export_YYYY_MM_DD.csv. | Bạn (đơn hàng) · OptiRoutes (tệp xuất) |
pod/YYYY/MM/DD/ | Các POD đã ký của ngày đó: <order>_sign_….pdf, chữ ký và ảnh (<order>_….png/jpg). | OptiRoutes |
pod/ | Phiếu giao hàng gốc để ký trong ứng dụng tài xế: pod/<order number>.pdf. | Bạn |
reports/YYYY/MM/ | Báo cáo cuối ngày và báo cáo hàng trả lại. | OptiRoutes |
podBaseFile/ | Mẫu POD gốc. | Bạn |
inbox/ | Thư mục tự do cho các tệp bạn muốn chuyển giao. | Bạn |
Tham chiếu
| Lệnh gọi | Quyền | Chức năng |
|---|---|---|
GET /api/v1/me | bất kỳ | Kiểm tra khóa. Trả về số công ty, các quyền của khóa và địa chỉ của bạn. |
GET /api/v1/files?folder=<folder> | files:read (pod:read: chỉ pod/) | Liệt kê một cấp thư mục: các tệp (tên, đường dẫn, kích thước, ngày sửa đổi) và thư mục con. |
GET /api/v1/files/download?path=<file> | files:read (pod:read: chỉ pod/) | Tải xuống một tệp. |
PUT /api/v1/files?path=<file> | files:write | Tải lên một tệp (nội dung yêu cầu là chính tệp, hoặc một biểu mẫu multipart có trường file). Tệp đã tồn tại sẽ bị thay thế. Tối đa 50 MB. |
DELETE /api/v1/files?path=<file> | files:write | Xóa một tệp bạn đã tải lên (ở nơi bạn được phép tải lên). |
GET /api/v1/pod?date=YYYY-MM-DD[&order=<number>] | pod:read | Các tệp POD của một ngày, mỗi tệp kèm số đơn hàng và loại: signed_pdf, signature, photo. |
GET /api/v1/pod/archive?date=YYYY-MM-DD[&kind=signed_pdf] | pod:read | Mọi tệp POD của ngày trong một tệp ZIP. |
Ví dụ phản hồi của lệnh liệt kê:
{
"ok": true,
"folder": "pod/2026/10/11/",
"items": [
{ "name": "12345_sign_2026_10_11.pdf", "path": "pod/2026/10/11/12345_sign_2026_10_11.pdf",
"type": "file", "size": 84213, "modified": "2026-10-11T09:14:02.000Z" }
]
}Tác vụ thường gặp
Tải lên tệp đơn hàng của hôm nay
# curl (Linux / macOS / Windows 10+)
curl -X PUT -H "Authorization: Bearer $OPTIROUTES_KEY" \
--data-binary @orders.csv -H "Content-Type: text/csv" \
"https://srv2.optiroutes.com/api/v1/files?path=orders_files/$(date +%F).csv"
# PowerShell
Invoke-RestMethod -Method Put -InFile .\orders.csv -ContentType 'text/csv' `
-Headers @{ Authorization = "Bearer $env:OPTIROUTES_KEY" } `
-Uri "https://srv2.optiroutes.com/api/v1/files?path=orders_files/$(Get-Date -f yyyy-MM-dd).csv"OptiRoutes tải tệp vào như cách hiện nay (tải tự động trong Cài đặt → Tải dữ liệu, hoặc nút "Tải tệp" của người dùng).
Tải xuống các POD đã ký của một đơn hàng
curl -H "Authorization: Bearer $OPTIROUTES_KEY" "https://srv2.optiroutes.com/api/v1/pod?date=2026-10-11&order=12345"
# then, for each item:
curl -H "Authorization: Bearer $OPTIROUTES_KEY" -OJ "https://srv2.optiroutes.com/api/v1/files/download?path=pod/2026/10/11/12345_sign_2026_10_11.pdf"
Tải xuống báo cáo cuối ngày
curl -H "Authorization: Bearer $OPTIROUTES_KEY" "https://srv2.optiroutes.com/api/v1/files?folder=reports/2026/10/"
curl -H "Authorization: Bearer $OPTIROUTES_KEY" -OJ "https://srv2.optiroutes.com/api/v1/files/download?path=reports/2026/10/report_2026_10_11.csv"
Python
import os, datetime, requests
BASE = "https://srv2.optiroutes.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['OPTIROUTES_KEY']}"}
# upload today's orders
day = datetime.date.today().isoformat()
with open("orders.csv", "rb") as f:
r = requests.put(f"{BASE}/files", params={"path": f"orders_files/{day}.csv"},
data=f, headers={**H, "Content-Type": "text/csv"}, timeout=60)
r.raise_for_status()
# download every signed POD of the day
pods = requests.get(f"{BASE}/pod", params={"date": day}, headers=H, timeout=60).json()["items"]
for p in pods:
if p["kind"] == "signed_pdf":
data = requests.get(f"{BASE}/files/download", params={"path": p["path"]}, headers=H, timeout=60)
open(p["name"], "wb").write(data.content)
C# (.NET)
using var http = new HttpClient { BaseAddress = new Uri("https://srv2.optiroutes.com/api/v1/") };
http.DefaultRequestHeaders.Authorization =
new("Bearer", Environment.GetEnvironmentVariable("OPTIROUTES_KEY"));
// upload today's orders
var day = DateTime.Today.ToString("yyyy-MM-dd");
using var content = new ByteArrayContent(File.ReadAllBytes("orders.csv"));
content.Headers.ContentType = new("text/csv");
(await http.PutAsync($"files?path=orders_files/{day}.csv", content)).EnsureSuccessStatusCode();
// the day's PODs as one ZIP
var zip = await http.GetByteArrayAsync($"pod/archive?date={day}");
File.WriteAllBytes($"pod-{day}.zip", zip);
Node.js
const BASE = 'https://srv2.optiroutes.com/api/v1';
const H = { Authorization: `Bearer ${process.env.OPTIROUTES_KEY}` };
const day = new Date().toISOString().slice(0, 10);
// list and download the day's signed PODs (Node 18+)
const { items } = await (await fetch(`${BASE}/pod?date=${day}`, { headers: H })).json();
for (const p of items.filter((i) => i.kind === 'signed_pdf')) {
const res = await fetch(`${BASE}/files/download?path=${encodeURIComponent(p.path)}`, { headers: H });
await require('fs/promises').writeFile(p.name, Buffer.from(await res.arrayBuffer()));
}Làm việc như FTP — tập lệnh đồng bộ thư mục
Các nhóm từng làm việc với FTP có thể giữ một thư mục trên máy chủ của mình đồng bộ với thư mục của công ty: một tác vụ theo lịch tải xuống các tệp mới (ví dụ các POD) và tải lên các tệp bạn đặt vào một thư mục cục bộ. Tập lệnh PowerShell dưới đây làm cả hai việc; hãy chạy nó vài phút một lần bằng Windows Task Scheduler (trên Linux, dùng các dòng curl với cron).
# optiroutes-sync.ps1 — download new PODs, upload what is in .\outbox (run every 5 minutes)
$Base = 'https://srv2.optiroutes.com/api/v1'
$H = @{ Authorization = "Bearer $env:OPTIROUTES_KEY" }
$Local = 'C:\OptiRoutes'
New-Item -ItemType Directory -Force "$Local\pod", "$Local\outbox", "$Local\sent" | Out-Null
# 1. today's and yesterday's PODs -> C:\OptiRoutes\pod\YYYY-MM-DD\
foreach ($d in (Get-Date), (Get-Date).AddDays(-1)) {
$day = $d.ToString('yyyy-MM-dd'); $dir = "$Local\pod\$day"
New-Item -ItemType Directory -Force $dir | Out-Null
$list = Invoke-RestMethod -Headers $H -Uri "$Base/pod?date=$day"
foreach ($f in $list.items) {
$dest = Join-Path $dir $f.name
if (-not (Test-Path $dest)) {
Invoke-WebRequest -Headers $H -OutFile $dest -Uri ("$Base/files/download?path=" + [uri]::EscapeDataString($f.path))
}
}
}
# 2. every file in C:\OptiRoutes\outbox -> orders_files/, then moved to C:\OptiRoutes\sent
Get-ChildItem "$Local\outbox" -File | ForEach-Object {
Invoke-RestMethod -Method Put -Headers $H -InFile $_.FullName -ContentType 'application/octet-stream' `
-Uri ("$Base/files?path=" + [uri]::EscapeDataString("orders_files/" + $_.Name)) | Out-Null
Move-Item $_.FullName "$Local\sent\" -Force
}Chuyển một công ty từ FTP sang API
Quản lý chuyển đổi trong Cài đặt → API và tệp → Truyền tệp qua: API. Từ thời điểm đó, không còn gì được gửi đến FTP của công ty, và mọi tệp đều nằm trong thư mục của công ty:
| Với FTP | Với API |
|---|---|
| Bạn đặt tệp đơn hàng lên FTP | PUT /api/v1/files?path=orders_files/YYYY-MM-DD.csv |
POD đã ký được đẩy vào /POD/ trên FTP của bạn | GET /api/v1/pod?date=… / /api/v1/pod/archive?date=… |
Tệp xuất tuyến được đẩy vào /orders/ | orders_files/routes_export_YYYY_MM_DD.csv |
Báo cáo được đẩy vào /orders/YYYY/MM/ | reports/YYYY/MM/ |
Các công ty mới làm việc với API ngay từ đầu. Chuyển lại sang FTP cũng bằng chính nút chuyển đó.
Công ty trên máy chủ OptiRoutes cũ
Công ty vẫn làm việc với máy chủ OptiRoutes cũ (WEB) có thể dùng API cho các POD đã ký: tạo khóa có quyền pod:read và dùng /api/v1/pod, /api/v1/pod/archive và /api/v1/files/download?path=pod/…. Các tệp khác vẫn được truyền như hiện nay, cho đến khi công ty chuyển sang máy chủ mới.
Lỗi
Khi có lỗi, phản hồi là {"ok": false, "error": "<code>", "message": "<explanation>"}.
| HTTP | error | Cách xử lý |
|---|---|---|
| 401 | missing_key / invalid_key | Gửi khóa; kiểm tra khóa chưa bị thu hồi hoặc hết hạn. |
| 403 | scope_missing | Khóa thiếu quyền — hãy tạo khóa có quyền đó. |
| 403 | ip_not_allowed | Gọi từ một địa chỉ được phép, hoặc cập nhật danh sách địa chỉ của khóa. |
| 403 | folder_read_only | Chỉ tải lên vào orders_files/, inbox/, podBaseFile/ hoặc pod/<file>.pdf. |
| 400 | invalid_path / invalid_date | Đường dẫn là tương đối (orders_files/a.csv), ngày có dạng YYYY-MM-DD. |
| 404 | not_found / no_pod_files | Không có tệp này / không có POD trong ngày đó. |
| 413 | file_too_large | Tối đa 50 MB mỗi tệp. |
| 429 | rate_limited | Đợi một phút rồi thử lại. |
| 502 / 503 | storage_unavailable / files_api_unavailable | Lỗi tạm thời — thử lại sau một phút. |
Giới hạn
- 300 yêu cầu mỗi phút cho mỗi khóa.
- 50 MB mỗi tệp.
- 20 khóa đang hoạt động cho mỗi công ty.
- Lệnh liệt kê thư mục trả về tối đa 5.000 mục; để xem thêm, hãy liệt kê các thư mục con (ví dụ POD của một ngày).
Trợ giúp
Quản lý của công ty xem được mọi khóa, lần dùng gần nhất và các lệnh gọi gần đây trong Cài đặt → API và tệp. Với mọi vấn đề khác, hãy liên hệ bộ phận hỗ trợ OptiRoutes, kèm số công ty và thời điểm của lệnh gọi — không bao giờ gửi chính khóa.