ETA for a delivery or pickup
In the SWAT system, estimated times are critical for managing expectations for both drivers and end-customers. There are three primary types of timestamps available for nodes
(pickups/drop-offs):- Planned Schedule (
scheduled_ts): Calculated during the initial optimization. This is the baseline plan. - Realistic ETA (
estimated_scheduled_ts): The most accurate real-time prediction. It considers current vehicle location, service times of previous stops, and route constraints. - Optimistic ETA (
estimated_earliest_arrival_ts): Represents the physically earliest possible arrival if the vehicle drove non-stop, ignoring some service buffers.
ETA Calculation Logic
The estimated_scheduled_ts is the recommended field for consuming applications. It is dynamically updated and calculated as follows:
# It cannot be earlier than the 'earliest physical arrival'
# AND it cannot be earlier than the node's scheduled open time (earliness constraint)
estimated_scheduled_ts = max(estimated_earliest_arrival_ts, node.open_time_ts)
If a vehicle arrives early (before open_time_ts), it must wait. This waiting time is implicitly included in the estimated_scheduled_ts.
Update Frequency
- Trigger: Updates happen approximately every 5 minutes per simulation.
- Scope: Only vehicles with assigned nodes are updated.
- Conditions: The vehicle must be online (sending GPS) or have a valid start time.
Event Lifecycle Example
To understand how ETA evolves, let's look at a lifecycle of a delivery node "B".
Scenario:
- Node A: Start/Pickup (Service time: 5m)
- Node B: Drop-off (Time window: 10:00 AM - 11:00 AM)
- Travel A -> B: 10 minutes.
1. Optimization Phase
The route is planned.
scheduled_ts: 10:00 AM (Planned arrival).estimated_scheduled_ts: 10:00 AM.
2. Execution Phase (On Time)
Vehicle departs A at 9:45 AM.
estimated_earliest_arrival_ts: 9:45 AM + 10m drive = 9:55 AM.estimated_scheduled_ts: max(9:55 AM, 10:00 AM open window) = 10:00 AM.- vehicle waits 5 minutes at location
3. Execution Phase (Delayed)
Traffic occurs. Vehicle departs A at 9:55 AM.
estimated_earliest_arrival_ts: 9:55 AM + 15m drive (traffic) = 10:10 AM.estimated_scheduled_ts: max(10:10 AM, 10:00 AM) = 10:10 AM.- The system now predicts a 10-minute delay compared to the original schedule.
Node Data Fields
| Field | Description |
|---|---|
scheduled_ts | Baseline. The planned arrival time from the optimization engine. |
estimated_scheduled_ts | Best ETA. The most realistic expected arrival time. Recalculated ~5 mins. |
estimated_earliest_arrival_ts | Optimistic ETA. Earliest physical arrival ignoring some constraints. |
arrived_to_location_ts | Actual. Timestamp when the driver marked "Arrived". |
completed_service_at | Actual. Timestamp when the node was marked "Completed". |
failed_to_deliver_at_ts | Actual. Timestamp if the delivery failed (e.g., customer not home). |
slack | The amount of time the vehicle expects to wait at this location before service can start. |
service_time | Duration required to service this node (e.g., loading/unloading). |
Retrieving ETA
There are three methods to access ETA data, depending on your latency requirements.
For a broader integration context on orders and delivery tracking, refer to the Integration of Orders and POD guide.
1. Polling Node Data
You can query a specific node to get its latest status and timestamps.
GET /api/v2/node/{node_id}
View JSON Response
{
"id": 50801567,
"node_type": "dropoff",
"status": "assigned",
"scheduled_ts": "2024-10-08T06:36:39+00:00",
"estimated_scheduled_ts": "2024-10-08T06:36:39+00:00",
"estimated_earliest_arrival_ts": "2024-10-08T06:32:00+00:00",
"arrived_to_location_ts": null,
"completed_service_at": null,
"slack": 238.8,
"service_time": 180,
"booking": "/api/v2/booking/23286180"
}
2. Webhooks & Websockets (Recommended)
For real-time updates, subscribe to vehicle_arrival events. This pushes updates for all vehicles in the simulation.
- Agent Type:
vehicle_group - Message Type:
vehicle_arrival
{
"simulation_id": 123,
"agent_type": "vehicle_group",
"message_type": "vehicle_arrival",
"data": {
"vehicle_id": 101,
"booking_id": 5002,
"booking_uid": "uuid-1234",
"node_id": 9001,
"estimated_earliest_arrival_ts": "2025-04-01T12:00:00+00:00",
"estimated_scheduled_ts": "2025-04-01T12:05:00+00:00",
"scheduled_ts": "2025-04-01T12:00:00+00:00"
},
"current_sim_ts": "2025-04-01T11:55:00+00:00"
}
See Webhooks Documentation for configuration details.
3. Client-Side Calculation (Routing API)
If you need ETA on-demand and cannot wait for the 5-minute update cycle (e.g., for a smooth driver app UI), you can calculate it using the Routing API + Vehicle Position.
- Get vehicle's next assigned nodes:
GET /api/v2/vehicle/<vehicle_id>/assigned_nodes - Get route from current GPS to the next node:
GET /vehicle_route_proxy/<vehicle_id>/<current_gps_lat,lon>;<node_lat,lon>
View Route Response
{
"code": "Ok",
"routes": [
{
"duration": 149.6,
"distance": 832.1,
"legs": [
{ "duration": 133.7, "distance": 771.4 }
]
}
],
"waypoints": [
{ "location": [100.516, 13.690] },
{ "location": [100.518, 13.692] }
]
}
Calculation: ETA = CurrentTime + route.duration