Skip to content
AIRO

API quickstart

Create an API key, send one request, read the routes. About five minutes.

1. Create an API key

In the portal open Connect AI, then API keys, and create a key. It starts with airo_sk_ and is shown once. Store it in your secrets manager, never in source control.

Check the key
curl https://ai-route-optimization.com/v1/me -H "Authorization: Bearer $AIRO_API_KEY"

2. Create an optimization

Send the depot, the fleet and the orders. Give each order an address or latitude and longitude. The Idempotency-Key header is required.

curl
curl -X POST https://ai-route-optimization.com/v1/optimizations \
  -H "Authorization: Bearer $AIRO_API_KEY" \
  -H "Idempotency-Key: so-2026-10-14-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Tuesday deliveries",
    "depot": { "label": "Main warehouse", "address": "100 King St W, Toronto, ON M5X 1A9" },
    "fleet": { "count": 2, "capacity": 60, "shift_start": "08:00", "shift_end": "17:00" },
    "orders": [
      { "id": "SO-1001", "address": "255 Bremner Blvd, Toronto, ON", "demand": 12, "service_minutes": 10,
        "time_window_start": "09:00", "time_window_end": "12:00" },
      { "id": "SO-1002", "address": "1 Blue Jays Way, Toronto, ON", "demand": 7 },
      { "id": "SO-1003", "latitude": 43.6677, "longitude": -79.3948, "demand": 20 }
    ]
  }'
Python
import os, uuid, requests

API = "https://ai-route-optimization.com"
HEADERS = {"Authorization": f"Bearer {os.environ['AIRO_API_KEY']}"}

payload = {
    "name": "Tuesday deliveries",
    "depot": {"label": "Main warehouse", "address": "100 King St W, Toronto, ON M5X 1A9"},
    "vehicles": [
        {"id": "van-1", "capacity": 60, "driver": "Sam", "shift_start": "08:00", "shift_end": "17:00"},
        {"id": "van-2", "capacity": 40},
    ],
    "orders": [
        {"id": "SO-1001", "address": "255 Bremner Blvd, Toronto, ON", "demand": 12,
         "time_window_start": "09:00", "time_window_end": "12:00"},
        {"id": "SO-1002", "address": "1 Blue Jays Way, Toronto, ON", "demand": 7},
    ],
}

# Reuse the same key when retrying the SAME request: it can never run or bill twice.
key = f"erp-run-{uuid.uuid4()}"
r = requests.post(f"{API}/v1/optimizations", json=payload,
                  headers={**HEADERS, "Idempotency-Key": key}, timeout=30)
r.raise_for_status()
opt = r.json()
print(opt["id"], opt["status"])
Node.js
const API = "https://ai-route-optimization.com";
const headers = { Authorization: `Bearer ${process.env.AIRO_API_KEY}` };

const res = await fetch(`${API}/v1/optimizations`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({
    depot: { address: "100 King St W, Toronto, ON M5X 1A9" },
    fleet: { count: 2, capacity: 60 },
    orders: [{ id: "SO-1001", address: "255 Bremner Blvd, Toronto, ON", demand: 12 }],
  }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
const optimization = await res.json();
Response: 202 Accepted
{
  "id": "0d1f0c3e-5b64-4c0e-9a7a-2f6d3d5c9a10",
  "name": "Tuesday deliveries",
  "status": "queued",
  "stage": "queued",
  "progress": 0,
  "strategy": "optimized",
  "orders": 3,
  "vehicles": 2,
  "error_code": null,
  "error_message": null,
  "created_at": "2026-10-14T13:02:11Z",
  "finished_at": null,
  "links": {
    "self": "https://ai-route-optimization.com/v1/optimizations/0d1f0c3e-5b64-4c0e-9a7a-2f6d3d5c9a10",
    "result": "https://ai-route-optimization.com/v1/optimizations/0d1f0c3e-5b64-4c0e-9a7a-2f6d3d5c9a10/result",
    "web": "https://ai-route-optimization.com/app/jobs/0d1f0c3e-5b64-4c0e-9a7a-2f6d3d5c9a10"
  }
}

3. Wait for the result

Optimizations are asynchronous: geocoding and solving take a few seconds. Poll the self link every 2 to 5 seconds, or register a webhook and skip polling.

Poll then read the routes
import time

while opt["status"] in ("queued", "running"):
    time.sleep(2)
    opt = requests.get(opt["links"]["self"], headers=HEADERS, timeout=30).json()

if opt["status"] != "completed":
    raise RuntimeError(opt["error_message"])

result = requests.get(opt["links"]["result"], headers=HEADERS, timeout=30).json()
for route in result["routes"]:
    print(route["vehicle_ref"], [s["order_ref"] for s in route["stops"]])

Next