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.py4. 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:00Zorder— your stop ids in the optimal visiting order.schedule— the estimated arrival time at each stop.lateStops— the stops that would arrive after theirdeadline(otherwisenull).stopsCharged—0in 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 examplestops[1].id).400 sandbox_addresses_unsupported— use coordinates with a test key.429 sandbox_rate_limited— wait for theRetry-Afterdelay.
Every error code is listed on the errors page.
6. Go to production
- Buy a stop pack: the live key (
otg_live_…) is emailed after payment. Prepaid, no subscription, and a failed call is never charged. - 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. - Check your remaining stops any time with GET /balance.