Recipes

Split a day's stops across a fleet

Hand the optimizer more stops than one vehicle can finish and cap each route, so the work comes back split across drivers.

Two vans, one list of stops, and a shift that ends at a fixed hour. You want the split decided by the solver, not by hand.

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.

Plan requirement. maxRoutes, maxRouteDurationSeconds and maxRouteDistanceMeters are Pro and above. On a Free key the request is rejected before the optimization is queued.

What this shows

  • —maxRoutes caps how many vehicles the work may be split across.
  • —maxRouteDurationSeconds and maxRouteDistanceMeters bound a single driver's day — every field in this API carries its unit in its name.
  • —The response comes back as an array of routes — one per vehicle — each with its own ordered stops.
  • —Stops the caps make impossible are returned as unrouted rather than silently dropped.

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,
      "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
    },
    {
      "address": "129 Court St, Brooklyn, NY",
      "lat": 40.687,
      "lng": -73.996,
      "serviceTimeSeconds": 600
    },
    {
      "address": "200 5th Ave, Brooklyn, NY",
      "lat": 40.671,
      "lng": -73.9814,
      "serviceTimeSeconds": 900,
      "timeWindowStart": "08:30",
      "timeWindowEnd": "08:55",
      "priority": 3
    }
  ],
  "parameters": {
    "travelMode": "driving",
    "roundTrip": true,
    "routeStartAt": "2026-04-14T08:00",
    "timezone": "America/New_York",
    "optimizeMode": "Time",
    "maxRoutes": 2,
    "maxRouteDurationSeconds": 3600,
    "maxRouteDistanceMeters": 120000
  },
  "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