How to Optimize Pickup and Delivery Routes

API or service
Route Planner API
Task
Pickup-delivery orders and agents → feasible optimized route
Examples
URL
Difficulty
Intermediate
Time
9 min

Optimize pickup and delivery routes

You have orders that must be collected at one location and delivered to another. Each pickup must happen before its delivery, and both actions must be assigned to the same courier or vehicle.

Represent every order as a Route Planner shipment. The optimizer chooses the agent and interleaves pickup and delivery actions with other work while preserving each shipment's precedence and assignment constraints.

Task flow: agents and pickup-delivery orders → Route Planner API → feasible assignments, stop order, and execution schedule.

Create paired shipments

The example has one Berlin courier and two orders. order-101 starts at the courier's depot; order-102 has a different pickup location. All coordinates use [longitude, latitude] order, and all durations use seconds.

POST https://api.geoapify.com/v1/routeplanner?apiKey=YOUR_API_KEY
Content-Type: application/json
{
  "mode": "drive",
  "agents": [
    {
      "id": "courier-a",
      "start_location": [13.4132, 52.5219],
      "end_location": [13.4132, 52.5219],
      "time_windows": [[0, 14400]]
    }
  ],
  "shipments": [
    {
      "id": "order-101",
      "pickup": {
        "location": [13.4132, 52.5219],
        "duration": 120
      },
      "delivery": {
        "location": [13.3777, 52.5163],
        "duration": 180
      }
    },
    {
      "id": "order-102",
      "pickup": {
        "location": [13.3694, 52.5251],
        "duration": 120
      },
      "delivery": {
        "location": [13.4397, 52.505],
        "duration": 180
      }
    }
  ]
}

The relative time window [0, 14400] makes the courier available for four hours. Choose what time zero means in your application—for example, 08:00—and add returned seconds to that reference when displaying clock times.

Read the optimized pickup and delivery sequence

The accepted request produces the following action sequence. The payload is reduced to the fields needed to verify assignment and precedence.

Reduced response:

{
  "type": "FeatureCollection",
  "features": [
    {
      "properties": {
        "agent_id": "courier-a",
        "distance": 18575,
        "time": 2239,
        "start_time": 0,
        "end_time": 2239,
        "actions": [
          {"type": "start", "start_time": 0, "waypoint_index": 0},
          {"type": "pickup", "shipment_id": "order-101", "start_time": 0, "duration": 120, "waypoint_index": 0},
          {"type": "delivery", "shipment_id": "order-101", "start_time": 398, "duration": 180, "waypoint_index": 1},
          {"type": "pickup", "shipment_id": "order-102", "start_time": 901, "duration": 120, "waypoint_index": 2},
          {"type": "delivery", "shipment_id": "order-102", "start_time": 1750, "duration": 180, "waypoint_index": 3},
          {"type": "end", "start_time": 2239, "waypoint_index": 4}
        ]
      }
    }
  ]
}

For both shipment IDs, the pickup action appears before the delivery action. The optimizer may interleave different shipments, but it cannot reverse an individual shipment or split its two actions between agents.

Distance is returned in meters with the default metric units. Times and durations are relative seconds.

Add shipment constraints

  • Add amount to shipments and a compatible capacity to agents when the vehicle load matters.
  • Put time windows on the individual pickup or delivery stop when the two locations have different availability.
  • Add duration separately to pickup and delivery so loading and unloading time affect the schedule.
  • Add shipment requirements and agent capabilities for refrigerated goods, hazardous materials, accessibility equipment, or other eligibility rules.
  • Use priority from 0 to 100 when some shipments should be assigned ahead of less important work.
  • Use stable shipment and agent IDs. Array indexes are valid mappings, but IDs survive application-side filtering and reordering more safely.
  • Inspect properties.issues.unassigned_shipments before publishing the plan. A valid API response can still contain orders that could not satisfy the available agents and constraints.

Do not convert a shipment into two jobs merely to make it fit. Relax the conflicting capacity, time-window, or capability constraint, or add an eligible agent while preserving the pickup-delivery relationship.