Skip to main content
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.

Quickstart | Route4Green