Time Windows
Time windows let you specify when each stop must be visited. The optimizer arranges the stop order to satisfy as many windows as possible. Any stop that cannot be reached within its window is still visited - the response reports the violation so you can act on it.
Time windows require the Optimized Routing endpoint and departureTime.
How time windows work
Section titled “How time windows work”Each stop can have a time window defined by an open and close time. The optimizer treats these as scheduling constraints when deciding the visit order.
08:00 09:00 10:00 11:00 12:00 ├───────┼───────┼───────┼───────┤
A [═══════════════] 09:00–11:00 ↑ 08:50 early: waits 10 min
B [═══════════] 10:30–12:00 ↑ 10:45 matched
C [═══════] 09:00–10:00 ↑ 11:20 late: 4800s past closeEarly arrival
Section titled “Early arrival”The vehicle arrives before the window opens. It waits at the stop until open, then begins service. The wait time is reported as violation_seconds. Subsequent stops are delayed by the same amount - this is the most common reason a tight window on one stop causes a cascade of late arrivals on others.
Matched
Section titled “Matched”The vehicle arrives within the window. No wait, no violation.
Late arrival
Section titled “Late arrival”The vehicle arrives after the window closes. The stop is still served immediately - the vehicle does not skip it. violation_seconds reports how far past close the vehicle arrived. Late violations cannot be recovered; the optimizer tried all orderings and this was the best result possible given the constraints.
Request
Section titled “Request”POST https://api.roadgis.dev/directions/v1/optimizedAuthorization: Bearer YOUR_API_KEYAdd timeWindow to any intermediate stop alongside stopDuration. First and last locations (depot) do not accept time windows.
{ "profile": "auto", "departureTime": "08:00", "locations": [ { "address_structured": { "postcode": "28216", "city": "Utena", "street": "Metalo g. 3" } }, { "id": "LT000000001", "stopDuration": 120, "address_structured": { "postcode": "28214", "city": "Utena", "street": "J. Basanavičiaus g. 108E" } }, { "id": "LT000000002", "stopDuration": 150, "address_structured": { "postcode": "28150", "city": "Utena", "street": "Aušros g. 78" }, "timeWindow": { "open": "08:30", "close": "12:00" } }, { "id": "LT000000003", "stopDuration": 120, "address_structured": { "postcode": "28142", "city": "Utena", "street": "Basanavičiaus g. 52" }, "timeWindow": { "open": "08:00", "close": "09:00" } }, { "address_structured": { "postcode": "28216", "city": "Utena", "street": "Metalo g. 3" } } ], "routeModifiers": { "excludeUnpaved": false, "topSpeed": 80, "shortest": false }, "computeOptions": { "steps": false }}timeWindow fields
Section titled “timeWindow fields”| Field | Type | Required | Description |
|---|---|---|---|
open | string | yes | Earliest allowed arrival in HH:MM |
close | string | yes | Latest allowed arrival in HH:MM |
departureTime is required whenever any location includes a timeWindow. The request returns 400 with code: InvalidInput if time windows are present but departureTime is omitted.
Response
Section titled “Response”Waypoints with a timeWindow include a timeWindowStatus object.
{ "code": "Ok", "waypoints": [ { "id": null, "originalIndex": 0, "location": { "lat": 55.49894, "lng": 25.631195 }, "matchedAddress": "Metalo g. 3, LT-28216 Utena", "relevance": 0.8727, "arrivalTime": "08:00" }, { "id": "LT000000003", "originalIndex": 3, "location": { "lat": 55.497962, "lng": 25.596965 }, "matchedAddress": "J. Basanavi\u010diaus g. 52, LT-28142 Utena", "relevance": 0.7965, "arrivalTime": "08:05", "timeWindowStatus": { "matched": true } }, { "id": "LT000000002", "originalIndex": 2, "location": { "lat": 55.507264, "lng": 25.595426 }, "matchedAddress": "Au\u0161ros g. 78, LT-28150 Utena", "relevance": 0.8727, "arrivalTime": "08:12", "timeWindowStatus": { "matched": false, "violation": "early", "violation_seconds": 1033 } }, { "id": "LT000000001", "originalIndex": 1, "location": { "lat": 55.505768, "lng": 25.623086 }, "matchedAddress": "J. Basanavi\u010diaus g. 108E, LT-28214 Utena", "relevance": 0.8727, "arrivalTime": "08:37" }, { "id": null, "originalIndex": 4, "location": { "lat": 55.49894, "lng": 25.631195 }, "matchedAddress": "Metalo g. 3, LT-28216 Utena", "relevance": 0.8727, "arrivalTime": "08:44" } ], "routes": [...]}timeWindowStatus fields
Section titled “timeWindowStatus fields”| Field | Type | Description |
|---|---|---|
matched | boolean | true if the vehicle arrived within the window |
violation | string | "early" or "late". Present only when matched is false |
violation_seconds | integer | Seconds outside the window. Present only when matched is false |
Stops without a timeWindow do not have timeWindowStatus in the response.
Violation outcomes
Section titled “Violation outcomes”| Outcome | Meaning |
|---|---|
| matched | Arrival falls within open-close. No wait, no violation. |
| early | Vehicle arrives before open. It waits at the stop until the window opens before departing. violation_seconds is the wait time. |
| late | Vehicle arrives after close. The delivery is late. violation_seconds is how far past the close time. |