Recipes

Optimize a multi-stop delivery run

Turn 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.

You have a van, a depot, and a morning's worth of drops. You want the order that finishes soonest — not the order the stops were entered in.

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

  • —isDepot: true marks where the driver starts; its position in the array does not matter.
  • —roundTrip: true brings the van back to the depot at the end.
  • —serviceTimeSeconds is the time spent AT a stop, so the ETAs account for unloading.
  • —optimizeMode: "Time" optimises the clock; switch to Distance to optimise fuel.

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": 900
    },
    {
      "address": "1155 Manhattan Ave, Brooklyn, NY",
      "lat": 40.7304,
      "lng": -73.954,
      "serviceTimeSeconds": 600,
      "timeWindowStart": "09:00",
      "timeWindowEnd": "10:30",
      "priority": 1
    },
    {
      "address": "238 Bedford Ave, Brooklyn, NY",
      "lat": 40.7135,
      "lng": -73.967,
      "serviceTimeSeconds": 900
    },
    {
      "address": "1 Front St, Brooklyn, NY",
      "lat": 40.7033,
      "lng": -73.9881,
      "serviceTimeSeconds": 600,
      "priority": 2
    },
    {
      "address": "445 Albee Square W, Brooklyn, NY",
      "lat": 40.6926,
      "lng": -73.9873,
      "serviceTimeSeconds": 1200
    }
  ],
  "parameters": {
    "travelMode": "driving",
    "optimizeMode": "Time",
    "roundTrip": true,
    "routeStartAt": "2026-04-14T08:00",
    "timezone": "America/New_York"
  },
  "webhookUrl": "https://your-server.com/webhooks/r4m"
}'

# 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