Your first route optimization

In about five minutes you will send three delivery stops to the Otiggo route optimization API and read back the best visiting order, the distance, the duration and the arrival time at each stop. Everything runs on a free sandbox key: nothing is charged.

1. Create a free sandbox key

Open the console and create a test key. It starts with otg_test_ and is shown only once, so copy it now.

2. Store the key as an environment variable

export OTIGGO_API_KEY="otg_test_..."

Never put a key in your source code or in a mobile app: call the API from your backend.

3. Write and run the script

The request needs a start point and at least two stops, each with a unique id. Stop A has a deadline of 10:30 and a 2-minute service time; the API plans around both.

// optimize.mjs — Node 18+ (built-in fetch), no dependency
const API_KEY = process.env.OTIGGO_API_KEY; // otg_test_...

const res = await fetch("https://app.otiggo.com/api/v1/optimize", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    start: { latitude: 48.8566, longitude: 2.3522 },
    stops: [
      { id: "A", latitude: 48.8738, longitude: 2.295, deadline: "10:30", serviceSeconds: 120 },
      { id: "B", latitude: 48.8606, longitude: 2.3376 },
      { id: "C", latitude: 48.853, longitude: 2.3499 },
    ],
  }),
});

const data = await res.json();
if (!res.ok) {
  console.error(res.status, data.error, data.message);
  process.exit(1);
}

console.log("Order:", data.order.join(" -> "));
console.log(data.totalDistanceKm + " km, " + data.estimatedTimeMin + " min");
for (const { colisId, arrivee } of data.schedule ?? []) {
  console.log(colisId, "arrives at", arrivee);
}
if (data.lateStops) console.warn("Late stops:", data.lateStops);
node optimize.mjs
# or
python optimize.py

4. Read the result

The output looks like this (distances and times will differ):

Example output
Order: A -> B -> C
6.1 km, 32 min
A arrives at 2026-10-20T05:40:00Z
B arrives at 2026-10-20T05:52:00Z
C arrives at 2026-10-20T05:58:00Z
  • order — your stop ids in the optimal visiting order.
  • schedule — the estimated arrival time at each stop.
  • lateStops — the stops that would arrive after their deadline (otherwise null).
  • stopsCharged — 0 in sandbox; the number of stops debited with a live key.

5. If something goes wrong

  • 401 unauthorized — missing, invalid or revoked key.
  • 400 invalid_request — the message names the faulty field (for example stops[1].id).
  • 400 sandbox_addresses_unsupported — use coordinates with a test key.
  • 429 sandbox_rate_limited — wait for the Retry-After delay.

Every error code is listed on the errors page.

6. Go to production

  1. Buy a stop pack: the live key (otg_live_…) is emailed after payment. Prepaid, no subscription, and a failed call is never charged.
  2. Replace the key. You can now send up to 200 stops per call and give full addresses (street, postalCode, city) instead of coordinates; they are geocoded for you.
  3. Check your remaining stops any time with GET /balance.