Docs menu
Optimize a route
Turn a start point plus 2–100 stops into an optimized visiting order with per-stop ETAs and a driver-ready hand-off link. This is the whole golden path — create, poll, read — and every command runs on a free test key.
That range is the API's absolute bound. Your plan sets the per-route ceiling — starter 20, growth 40, trial and pro 100 — and a request above your own ceiling is refused with 402 quota_exceeded carrying metric: "stops" and your actual limit, so it fails loudly rather than silently truncating.
Before you start
- Mint a test key. Open Settings → API keys and create a
dk_test_key. Test keys are free and instant on a trial account. - Know your base URL. Your Darb API base is the origin that serves the API (the hosted portal wires it from
PUBLIC_API_URL). Set it as a shell variable so the examples below run as-is. - Authenticate with a Bearer header. Every request carries
Authorization: Bearer dk_test_...— Darb never accepts keys as query parameters.
# Your Darb API base URL (the hosted portal wires this from PUBLIC_API_URL)
export DARB_API_BASE="https://<your-darb-api-host>"
# A test key minted in Settings -> API keys
export DARB_KEY="dk_test_..."1. Create the route
POST /api/v1/routes accepts the route synchronously and returns 202 with an id and status: "optimizing". Send an Idempotency-Keyheader on the POST so a retried request never creates a duplicate route — replaying the same key echoes the original route and reserves no additional quota.
curl -sS -X POST "$DARB_API_BASE/api/v1/routes" \
-H "Authorization: Bearer $DARB_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: route-2026-07-14-0001" \
-d '{
"start": { "lat": 23.60, "lng": 58.40, "label": "Depot" },
"stops": [
{ "lat": 23.61, "lng": 58.41, "label": "A" },
{ "lat": 23.62, "lng": 58.42, "label": "B" }
]
}'import httpx
resp = httpx.post(
f"{DARB_API_BASE}/api/v1/routes",
headers={
"Authorization": f"Bearer {DARB_KEY}",
"Idempotency-Key": "route-2026-07-14-0001",
},
json={
"start": {"lat": 23.60, "lng": 58.40, "label": "Depot"},
"stops": [
{"lat": 23.61, "lng": 58.41, "label": "A"},
{"lat": 23.62, "lng": 58.42, "label": "B"},
],
},
)
route_id = resp.json()["id"]The 202 response is the poll seed — the stops echo your input, not yet ordered:
{
"id": "b6f1c0e2-4d3a-4c1b-9f22-0a1b2c3d4e5f",
"status": "optimizing",
"stops": [
{ "seq_input": 1, "seq_optimized": null, "eta": null, "label": "A", "lat": 23.61, "lng": 58.41 },
{ "seq_input": 2, "seq_optimized": null, "eta": null, "label": "B", "lat": 23.62, "lng": 58.42 }
],
"total_distance_m": null,
"total_duration_s": null,
"polyline": null,
"handoff_url": null
}2. Poll for the optimized result
Optimization runs in the background (see Conventions → Asynchronous jobs). Poll GET /api/v1/routes/{id} untilstatus becomes optimized (or failed).
# Poll until "status" is "optimized" (or "failed"). Use the id from the create response.
curl -sS "$DARB_API_BASE/api/v1/routes/$ROUTE_ID" \
-H "Authorization: Bearer $DARB_KEY"Once optimized, each stop carries its seq_optimized visiting order and a per-stopeta, the route carries its totals, and handoff_url is a driver-ready link you can send straight to a driver:
{
"id": "b6f1c0e2-4d3a-4c1b-9f22-0a1b2c3d4e5f",
"status": "optimized",
"stops": [
{ "seq_input": 1, "seq_optimized": 2, "eta": "2026-07-14T08:12:00Z", "label": "A", "lat": 23.61, "lng": 58.41 },
{ "seq_input": 2, "seq_optimized": 1, "eta": "2026-07-14T08:04:00Z", "label": "B", "lat": 23.62, "lng": 58.42 }
],
"total_distance_m": 8450,
"total_duration_s": 1320,
"polyline": "yz{|@_ulpE...",
"handoff_url": "https://<your-darb-app-host>/d/8f3c1a2b"
}Test-mode caps
Test-mode caps: 100 routes, 200 WhatsApp, 100 SMS per month. Test usage never touches your live quota or your bill. If you exhaust a test cap the API returns a402 quota_exceeded — see Conventions → Quotas & billing.
Going live
Next: run a campaign to collect customer locations by phone number, or read the conventions shared by every endpoint.