OptiRoad API Documentation
Introduction
The OptiRoad API lets you optimize delivery routes, geocode addresses, and manage contacts programmatically. Access requires a Business plan and an API key.
Base URL:
https://optiroad.io/api/v1All requests must include the Authorization header. Responses are JSON. Dates are ISO 8601 strings. Distances are in kilometers, durations in minutes.
Authentication
Authenticate using your API key in the Authorization :
curl https://optiroad.io/api/v1/usage \
-H "Authorization: Bearer or_live_YOUR_KEY"API keys are created in Settings → API Keys. Each key is shown only once at creation. Maximum 5 keys per account.
JavaScript example
const BASE = "https://optiroad.io/api/v1";
const KEY = process.env.OPTIROAD_API_KEY;
const res = await fetch(`${BASE}/usage`, {
headers: { Authorization: `Bearer ${KEY}` },
});
const data = await res.json();Python example
import os, requests
BASE = "https://optiroad.io/api/v1"
KEY = os.environ["OPTIROAD_API_KEY"]
resp = requests.get(
f"{BASE}/usage",
headers={"Authorization": f"Bearer {KEY}"}
)
data = resp.json()Optimize a route
/api/v1/optimizeCompute the optimal visiting order for a set of addresses.Request body
{
"addresses": [
{ "label": "Dépôt", "lat": 48.8566, "lng": 2.3522 },
{ "label": "Client A", "lat": 48.8737, "lng": 2.2950 },
{ "label": "Client B", "lat": 48.8416, "lng": 2.3224 }
],
"options": {
"mode": "driving",
"startAddress": 0,
"roundTrip": true
}
}Parameters
| Field | Type | Description |
|---|---|---|
| addresses | array | Required. List of stops (min 2, max 150). Each item: { label, lat, lng }. |
| options.mode | string | Routing profile: driving (default), walking, cycling. |
| options.startAddress | number | Index of the start/depot address in the array (default: 0). |
| options.roundTrip | boolean | Return to start after the last stop (default: true). |
Response
{
"optimizedOrder": [0, 2, 1],
"totalDistanceKm": 12.4,
"totalDurationMin": 22,
"legs": [
{ "from": 0, "to": 2, "distanceKm": 5.1, "durationMin": 9 },
{ "from": 2, "to": 1, "distanceKm": 4.2, "durationMin": 8 },
{ "from": 1, "to": 0, "distanceKm": 3.1, "durationMin": 5 }
],
"googleMapsUrl": "https://www.google.com/maps/dir/...",
"usageRemaining": 487
}Geocode an address
/api/v1/geocodeConvert a free-text address to lat/lng coordinates.// Request
{ "address": "10 Downing Street, London" }
// Response
{
"lat": 51.5034,
"lng": -0.1276,
"label": "10 Downing Street, Westminster, London, UK"
}Contacts
Manage your saved address book. All operations are scoped to your account.
/api/v1/contactsList contacts (paginated).GET /api/v1/contacts?page=1&limit=20&search=Paris{
"contacts": [
{
"id": "clx...",
"name": "Entrepôt Paris",
"address": "12 rue de Rivoli, 75001 Paris",
"lat": 48.856,
"lng": 2.352,
"phone": "+33 1 23 45 67 89",
"createdAt": "2026-03-01T10:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 20
}/api/v1/contactsCreate a contact.// Request
{
"name": "Entrepôt Paris",
"address": "12 rue de Rivoli, 75001 Paris",
"lat": 48.856,
"lng": 2.352,
"phone": "+33 1 23 45 67 89"
}
// Response — 201 Created
{ "id": "clx...", "name": "...", ... }/api/v1/contacts/:idUpdate a contact./api/v1/contacts/:idDelete a contact.// Response — 204 No ContentVehicles
/api/v1/vehiclesList vehicles.GET /api/v1/vehicles?status=active&type=van{
"vehicles": [
{
"id": "clx...",
"name": "Camion 1",
"type": "truck",
"status": "active",
"depotAddress": "ZI Nord, 59000 Lille",
"depotLat": 50.651,
"depotLng": 3.074
}
]
}Optimization history
/api/v1/historyList past optimizations (paginated).GET /api/v1/history?page=1&limit=20&from=2026-01-01&to=2026-04-01{
"items": [
{
"id": "clx...",
"addressCount": 8,
"totalDistanceKm": 34.2,
"totalDurationMin": 61,
"createdAt": "2026-03-15T08:30:00.000Z"
}
],
"total": 42
}API usage
/api/v1/usageRequest counts for the current key.{
"keyPrefix": "or_live_ab12",
"today": { "optimize": 3, "geocode": 12 },
"thisMonth": { "optimize": 47, "geocode": 203 },
"allTime": { "optimize": 312, "geocode": 1024 }
}Rate limits
Limits apply per API key. Response headers always include the current window state.
| Endpoint type | Per minute | Per hour | Per day |
|---|---|---|---|
| Light (geocode, contacts, vehicles) | 100 | 1 000 | — |
| Heavy (optimize) | 10 | 100 | 500 |
When a limit is hit the API returns 429 Too Many Requests with a Retry-After header (seconds).
Rate-limit headers
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1744012800 # Unix timestamp (UTC)
Retry-After: 38 # Only present on 429Error codes
| HTTP | error | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or malformed Authorization header. |
| 401 | INVALID_API_KEY | Key not found or revoked. |
| 402 | QUOTA_EXCEEDED | Monthly optimization quota reached. Upgrade your plan. |
| 403 | PLAN_REQUIRED | This endpoint requires a Business plan. |
| 422 | VALIDATION_ERROR | Request body failed validation (details in message). |
| 422 | MAX_KEYS_REACHED | You already have 5 API keys. Revoke one first. |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests. Check Retry-After. |
| 500 | INTERNAL_ERROR | Unexpected server error. Please retry. |
Error response shape
{
"error": "QUOTA_EXCEEDED",
"message": "Monthly quota reached (5/5). Upgrade to Pro for unlimited optimizations.",
"statusCode": 402
}Questions? Contact support@optiroad.io
OptiRoad API v1 · 2026