Docs menu
Quickstart
Submit a job and collect the result, end to end.
The SDK is not released. What follows uses plain HTTP.
The whole sequence: hold an API key, submit a job with an Idempotency-Key, wait for a terminal state, then fetch the result. The example below is TypeScript and runs on your server.
import { randomUUID } from "node:crypto";
const BASE = "https://<your-host>/api/v1/partners/addons/route-optimization";
const headers = { "api-key": process.env.ROUTE4GREEN_API_KEY! };
// The minimal valid body: one vehicle, one order, every required field
// filled in. See the POST /jobs reference for the full field list.
const body = {
external_reference: "your-own-id",
optimization_options: {
delivery_mode: "1",
kind_of_plan: "1",
tour_mode: "1;0;0;0;0;0",
},
vehicles: [
{
external_vehicle_id: "veh-01",
resource_id: 1,
from_address: "118 Tay Son, Dong Da, Ha Noi",
from_lat: 21.0122,
from_lon: 105.8252,
from_working_time: "2026-09-04T07:00:00+07:00",
to_working_time: "2026-09-04T18:00:00+07:00",
handling_unit_ids: [1],
height_of_vehicle: 180,
length_of_vehicle: 420,
width_of_vehicle: 190,
vehicle_tonnage: 1500,
},
],
orders: [
{
external_order_id: "ord-01",
transport_mode: "lastmile",
handling_unit_id: 1,
service_id: 1,
pickup_address: "118 Tay Son, Dong Da, Ha Noi",
pickup_lat: 21.0122,
pickup_lon: 105.8252,
pickup_date_time: "2026-09-04T08:00:00+07:00",
pickup_date_time_to: "2026-09-04T09:00:00+07:00",
drop_address: "72 Nguyen Trai, Thanh Xuan, Ha Noi",
drop_lat: 20.9971,
drop_lon: 105.8032,
drop_date_time: "2026-09-04T09:30:00+07:00",
drop_date_time_to: "2026-09-04T11:00:00+07:00",
rlength: 40,
rwidth: 30,
rheight: 30,
rweight: 5,
count_of_parcels: 1,
},
],
};
// 1. Submit. Generate the key once, reuse it for every retry of THIS submit.
const idempotencyKey = randomUUID();
const submitted = await fetch(`${BASE}/jobs`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": idempotencyKey, "content-type": "application/json" },
body: JSON.stringify(body),
}).then((r) => r.json());
if (!submitted.success) throw new Error(submitted.error_code);
const jobId: string = submitted.data.id;
// 2. Wait. Stop on any terminal state, and bound the loop.
const TERMINAL = new Set(["SUCCEEDED", "PARTIAL", "FAILED", "CANCELLED"]);
let status = "QUEUED";
const deadline = Date.now() + 30 * 60 * 1000;
while (!TERMINAL.has(status) && Date.now() < deadline) {
await new Promise((r) => setTimeout(r, 5_000));
const polled = await fetch(`${BASE}/jobs/${jobId}`, { headers }).then((r) => r.json());
if (!polled.success) throw new Error(polled.error_code);
status = polled.data.status;
}
// 3. Collect, but only from a state that has a result.
if (status === "SUCCEEDED" || status === "PARTIAL") {
const result = await fetch(`${BASE}/jobs/${jobId}/result`, { headers }).then((r) => r.json());
if (result.success) use(result.data);
}API keys are issued by hand today. If you do not have one, request a trial first.