OptiRoutes Files API

Hướng dẫn dành cho các nhóm phần mềm kết nối một công ty với OptiRoutes: tải đơn hàng lên, nhận POD, tệp xuất và báo cáo — an toàn, qua HTTPS.

EN · HE · AR · RU · ES · IT · CS · RO · EL · DE · FR · PT · JA · KO · ZH · NL · PL · TR · SV · DA · NB · FI · HU · SK · HR · BG · UK · ID · MS · TH · VI · HI · LT · SL

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.

Bắt đầu trong 3 bước

  1. 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.
  2. Kiểm tra kết nối.
    curl -H "Authorization: Bearer $OPTIROUTES_KEY" https://srv2.optiroutes.com/api/v1/me
  3. 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

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Khó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ụcNội dungBê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ọiQuyềnChức năng
GET /api/v1/mebấ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:writeTả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:writeXó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:readCá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:readMọ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 FTPVới API
Bạn đặt tệp đơn hàng lên FTPPUT /api/v1/files?path=orders_files/YYYY-MM-DD.csv
POD đã ký được đẩy vào /POD/ trên FTP của bạnGET /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>"}.

HTTPerrorCách xử lý
401missing_key / invalid_keyGửi khóa; kiểm tra khóa chưa bị thu hồi hoặc hết hạn.
403scope_missingKhóa thiếu quyền — hãy tạo khóa có quyền đó.
403ip_not_allowedGọi từ một địa chỉ được phép, hoặc cập nhật danh sách địa chỉ của khóa.
403folder_read_onlyChỉ tải lên vào orders_files/, inbox/, podBaseFile/ hoặc pod/<file>.pdf.
400invalid_path / invalid_dateĐường dẫn là tương đối (orders_files/a.csv), ngày có dạng YYYY-MM-DD.
404not_found / no_pod_filesKhông có tệp này / không có POD trong ngày đó.
413file_too_largeTối đa 50 MB mỗi tệp.
429rate_limitedĐợi một phút rồi thử lại.
502 / 503storage_unavailable / files_api_unavailableLỗi tạm thời — thử lại sau một phút.

Giới hạn

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.