Recipes
Plan deliveries with customer time windows
Give each stop the window the customer agreed to and let the optimizer sequence the day around them.
Your customers were promised slots — 9 to 10:30, 1 to 4 — and a route that ignores them is worse than no route at all.
The prompt is a complete brief — the task, this request body, the rules the API validates against, and the result shape to check against. Paste it into Claude Code, Cursor or any coding agent. The MCP setup connects an agent to the live API instead, so it can run the optimization itself.
What this shows
- —
timeWindowStart/timeWindowEndare LOCAL times of day, written without a zone suffix. - —Because they are local,
routeStartAt(which day) andtimezone(whose clock) are both required. - —A stop must finish inside its window, so a window shorter than the stop's
serviceTimeSecondsis rejected before it reaches the solver. - —
prioritybreaks ties between stops the windows leave equally free.
The request
You send
curl -X POST https://r4m.ai/api/v1/optimizations \
-H "Authorization: Bearer acc_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"addresses": [
{
"address": "Depot — 25 Kent Ave, Brooklyn, NY",
"lat": 40.7218,
"lng": -73.9615,
"isDepot": true,
"serviceTimeSeconds": 600
},
{
"address": "1155 Manhattan Ave, Brooklyn, NY",
"lat": 40.7304,
"lng": -73.954,
"serviceTimeSeconds": 900,
"timeWindowStart": "09:00",
"timeWindowEnd": "10:30"
},
{
"address": "238 Bedford Ave, Brooklyn, NY",
"lat": 40.7135,
"lng": -73.967,
"serviceTimeSeconds": 600,
"timeWindowStart": "09:30",
"timeWindowEnd": "12:00"
},
{
"address": "1 Front St, Brooklyn, NY",
"lat": 40.7033,
"lng": -73.9881,
"serviceTimeSeconds": 1200,
"timeWindowStart": "13:00",
"timeWindowEnd": "16:00",
"priority": 1
},
{
"address": "445 Albee Square W, Brooklyn, NY",
"lat": 40.6926,
"lng": -73.9873,
"serviceTimeSeconds": 900,
"timeWindowStart": "14:00",
"timeWindowEnd": "17:00"
}
],
"parameters": {
"travelMode": "driving",
"optimizeMode": "Time",
"roundTrip": true,
"routeStartAt": "2026-04-14T08:00",
"timezone": "America/New_York"
}
}'
# 202 Accepted — this call returns immediately; the solver keeps working (2-60s)
# { "success": true, "data": { "id": "550e8400-…", "status": "pending" } }
#
# That id is how you collect the finished plan. Either:
# webhook — we POST it to your webhookUrl the moment it is ready, or
# polling — GET /api/v1/optimizations/{id} until status is "completed"You get back
The POST answers immediately with a pending id; this is the completed optimization, abridged. Collect it by polling or webhook.
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"priceMicros": 10000,
"webhookUrl": "https://your-server.com/webhooks/r4m",
"webhookStatus": "delivered",
"result": {
"routes": [
{
"routeStartAt": "2026-04-14T08:00:00-04:00",
"totalDistanceMeters": 19473,
"totalTimeSeconds": 8285,
"polyline": "ulpwFpplbMl@qA@CLOYYIIIK…",
"waypoints": [
{
"index": 0,
"arrivalAt": "2026-04-14T08:00:00-04:00",
"departureAt": "2026-04-14T08:15:00-04:00",
"waitTimeSeconds": 0,
"cumulativeDistanceMeters": 0,
"cumulativeTimeSeconds": 0,
"polylineToNext": "ulpwFpplbMl@qA@CLOYYIIIK…"
},
{
"index": 1,
"arrivalAt": "2026-04-14T09:00:00-04:00",
"departureAt": "2026-04-14T09:10:00-04:00",
"waitTimeSeconds": 2543,
"cumulativeDistanceMeters": 1416,
"cumulativeTimeSeconds": 3600,
"polylineToNext": "}brwFhckbMI{A?IGkAIqBMkC…"
}
]
}
],
"unroutedStops": []
},
"createdAt": "2026-04-14T11:58:12Z",
"updatedAt": "2026-04-14T11:58:41Z"
}
}Read next
Other recipes
Optimize a multi-stop delivery runTurn a depot and a list of stops into the order to drive them in, with per-stop service time and a return to the depot.Split a day's stops across a fleetHand the optimizer more stops than one vehicle can finish and cap each route, so the work comes back split across drivers.Optimize a route from plain addressesTurn a spreadsheet of address strings into coordinates, then into an optimized route — the two calls in the right order, and when one call is enough.