{"openapi":"3.1.0","info":{"title":"Vepathos Route Optimization API","description":"Plan last-mile delivery routes over HTTP. Describe vehicles, fleets, depots and deliveries, group them into a delivery lot, and let Vepathos assign stops to vehicles and sequence every route.\n\nAuthenticate with `Authorization: Bearer <access_token>`, using a token from `POST /api/token`. Optimization is asynchronous: queue a plan with `POST /lots/{id}/plan`, then read it with `GET /lots/{id}/plan` until `state` is `PROCESSED`.\n\nPlan quotas and optimization options depend on your Vepathos plan. Requests over a limit return `403` with `error: \"plan_limit_exceeded\"` and are never charged.","version":"0.26.0","license":{"name":"GNU Affero General Public License","url":"https://www.gnu.org/licenses/agpl-3.0.html"}},"servers":[{"url":"https://api.vepathos.com"}],"security":[{"bearerJWT":[]}],"paths":{"/vehicles":{"get":{"tags":["vehicles"],"summary":"List vehicles","operationId":"vehicles_get_vehicles_get","responses":{"200":{"description":"All vehicles in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/VehicleResponse"},"type":"array","title":"Response Vehicles Get Vehicles Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}],"description":"Every vehicle type in your account."},"post":{"tags":["vehicles"],"summary":"Create vehicle","operationId":"vehicles_post_vehicles_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleCreate"},"example":{"name":"Cargo van","volume":8,"volume_unit":"CUBIC_METER","weight":900,"weight_unit":"KILOGRAMS","consumption":11,"consumption_unit":"LITERS_PER_100KM","category_type":"VAN","engine_type":"DIESEL"}}},"required":true},"responses":{"201":{"description":"The created vehicle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Adds a vehicle type to the catalog. How many units you have is set on a fleet. Returns `403` with `reason: \"max_vehicles\"` when the plan's catalog is full."}},"/vehicles/{id}":{"get":{"tags":["vehicles"],"summary":"Get vehicle","operationId":"vehicles_id_get_vehicles__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The vehicle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["vehicles"],"summary":"Update vehicle","operationId":"vehicles_id_patch_vehicles__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleUpdate"},"example":{"weight":950}}}},"responses":{"200":{"description":"The updated vehicle.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Send only the fields to change."},"delete":{"tags":["vehicles"],"summary":"Delete vehicle","operationId":"vehicles_id_delete_vehicles__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}},{"name":"strategy","in":"query","required":false,"description":"When `unlink-fleets`, removes fleet_vehicle links only and keeps the vehicle catalog row. Default: full delete with FK cleanup (api-doc gateway).","schema":{"type":"string","enum":["unlink-fleets"]}}],"responses":{"200":{"description":"Vehicle deleted or unlinked from fleets (gateway applies transactional FK cleanup).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleDeleteResponse"},"examples":{"deleted":{"value":{"code":"deleted","message":"Vehicle deleted","fleetNames":["Main fleet"]}},"unlinked":{"value":{"code":"unlinked","message":"Vehicle unlinked from fleets","fleetNames":["Main fleet"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Vehicle not found in tenant scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteHubDeleteNotFound"}}}},"409":{"description":"Vehicle still referenced by optimization history after cleanup (e.g. delivery_path FK).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehicleDeleteBlocked"}}}},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Deletes the vehicle and unlinks it from every fleet that used it; `fleetNames` lists them. With `?strategy=unlink-fleets` the vehicle stays in the catalog and is only removed from fleets. Returns `409` with `code: \"vehicle_in_use\"` when optimization history still references it."}},"/fleets":{"get":{"tags":["fleets"],"summary":"List fleets","operationId":"fleets_get_fleets_get","responses":{"200":{"description":"All fleets in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FleetResponse"},"type":"array","title":"Response Fleets Get Fleets Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}],"description":"Every fleet with its vehicle entries. Each entry repeats the vehicle's catalog fields next to `qty`, `alias`, `route` and `behavior`."},"post":{"tags":["fleets"],"summary":"Create fleet","operationId":"fleets_post_fleets_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetCreate"},"example":{"name":"Downtown fleet","vehicles":[{"id":"12","qty":3,"route":{"stops_max":60,"time_max":480,"time_unit":"MINUTE"},"behavior":{"priority":1}},{"id":"14","qty":2,"behavior":{"overflow_vehicle":true}}]}}},"required":true},"responses":{"201":{"description":"The created fleet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Returns `403` with `reason: \"max_fleets\"` when the account holds its plan's fleets, or `reason: \"max_fleet_units\"` when `vehicles[].qty` adds up past the plan's units per fleet."}},"/fleets/{id}":{"get":{"tags":["fleets"],"summary":"Get fleet","operationId":"fleets_id_get_fleets__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The fleet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["fleets"],"summary":"Update fleet","operationId":"fleets_id_patch_fleets__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetUpdate"},"example":{"vehicles":[{"id":"12","qty":5},{"id":"14","qty":2,"behavior":{"overflow_vehicle":true}}]}}}},"responses":{"200":{"description":"The updated fleet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"When `vehicles` is sent it replaces the list: entries you leave out are removed. Entries are matched by `alias`. The new total of `qty` must fit the plan's units per fleet."},"delete":{"tags":["fleets"],"summary":"Delete fleet","operationId":"fleets_id_delete_fleets__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"Fleet deleted (gateway unlinks fleet_vehicle rows and clears delivery_lot.fleet_id).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FleetDeleteResponse"},"example":{"code":"deleted","message":"Fleet deleted"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Fleet not found in tenant scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteHubDeleteNotFound"}}}},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Deletes the fleet and detaches it from any lot that referenced it. Vehicles in the catalog are kept."}},"/drivers":{"get":{"tags":["drivers"],"summary":"List drivers","operationId":"fleets_get_drivers_get","responses":{"200":{"description":"All drivers in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DriverResponse"},"type":"array","title":"Response Fleets Get Drivers Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["drivers"],"summary":"Create driver","operationId":"drivers_post_drivers_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverCreate"},"example":{"first_name":"Ana","last_name":"García","work_schedules":["DTSTART:20260105T080000Z\nDURATION:PT8H\nRRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"],"start_point":"+40.4168-3.7038","end_point":"+40.4168-3.7038","vehicles":[{"id":"12","qty":1}]}}},"required":true},"responses":{"201":{"description":"The created driver.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Driver schedules, start and end points and work areas are stored with the driver. The current optimizer plans from the fleet and does not apply them as routing constraints. Returns `403` with `reason: \"max_drivers\"` when the plan's cap is reached."}},"/drivers/{id}":{"get":{"tags":["drivers"],"summary":"Get driver","operationId":"drivers_id_get_drivers__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The driver.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["drivers"],"summary":"Update driver","operationId":"drivers_id_patch_drivers__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverUpdate"}}}},"responses":{"200":{"description":"The updated driver.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DriverResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Send only the fields to change."},"delete":{"tags":["drivers"],"summary":"Delete driver","operationId":"drivers_id_delete_drivers__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The driver was deleted.","content":{"application/json":{"schema":{}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/milestones":{"get":{"tags":["milestones"],"summary":"List milestones","operationId":"milestones_get_milestones_get","responses":{"200":{"description":"All milestones in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/MilestoneResponse"},"type":"array","title":"Response Milestones Get Milestones Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["milestones"],"summary":"Create milestone","operationId":"milestones_post_milestones_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneCreate"},"example":{"name":"Brooklyn depot","location":"+40.6782-73.9442","category":"DEPOT"}}},"required":true},"responses":{"201":{"description":"The created milestone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Returns `403` with `reason: \"max_milestones\"` when the plan's cap is reached."}},"/milestones/{id}":{"get":{"tags":["milestones"],"summary":"Get milestone","operationId":"milestones_id_get_milestones__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The milestone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["milestones"],"summary":"Update milestone","operationId":"milestones_id_patch_milestones__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneUpdate"}}}},"responses":{"200":{"description":"The updated milestone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MilestoneResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Send only the fields to change."},"delete":{"tags":["milestones"],"summary":"Delete milestone","operationId":"milestones_id_delete_milestones__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The milestone was deleted.","content":{"application/json":{"schema":{}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/deliveries":{"get":{"tags":["deliveries"],"summary":"List deliveries","operationId":"deliveries_get_deliveries_get","responses":{"200":{"description":"All deliveries in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DeliveryResponse"},"type":"array","title":"Response Deliveries Get Deliveries Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}],"description":"Every delivery in your account."},"post":{"tags":["deliveries"],"summary":"Create delivery","operationId":"deliveries_post_deliveries_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryCreate"},"example":{"milestone_id":"7","destination":"+40.7128-74.0060","method":"DELIVERY","schedules":["DTSTART:20260915T090000Z\nDURATION:PT4H"],"weight":2500,"weight_unit":"GRAMS","packaging":"BOX","handling":["FRAGILE"],"extra":{"order_id":"ORD-12345"}}}},"required":true},"responses":{"201":{"description":"The created delivery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Creates one stop. For many stops use `POST /deliveries/bulk`."}},"/deliveries/bulk":{"post":{"tags":["deliveries"],"summary":"Create deliveries in bulk","operationId":"deliveries_bulk_post_deliveries_bulk_post","requestBody":{"content":{"application/json":{"schema":{"title":"Post Data","oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/DeliveryCreate"}},{"type":"object","required":["deliveries"],"properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryCreate"}}}}]},"example":[{"milestone_id":"7","destination":"+40.6892-73.9857","weight":12,"weight_unit":"KILOGRAMS"},{"milestone_id":"7","lat":40.7033,"lng":-73.9881,"weight":4,"weight_unit":"KILOGRAMS"}]}},"required":true},"responses":{"200":{"description":"Per-row result of the batch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryBulkResponse"},"example":{"success":[{"idx":0,"id":"101"}],"failure":[{"idx":1,"err":[{"msg":"Milestone not found","inp":{"milestone_id":"999"},"loc":["milestone_id"]}]}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Accepts a JSON array of deliveries, or an object with a `deliveries` array. Every row is validated on its own: valid rows are created and listed in `success`, invalid rows are reported in `failure` with their index and errors.\n\nBulk rows may send `lat` and `lng` instead of `destination`, and time windows as `{ \"start\": \"...\", \"end\": \"...\" }` ISO timestamps. Schedule entries that cannot be parsed are dropped from the row."}},"/deliveries/{id}":{"get":{"tags":["deliveries"],"summary":"Get delivery","operationId":"deliveries_id_get_deliveries__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The delivery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["deliveries"],"summary":"Update delivery","operationId":"deliveries_id_patch_deliveries__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryUpdate"},"example":{"schedules":["DTSTART:20260915T130000Z\nDURATION:PT2H"]}}}},"responses":{"200":{"description":"The updated delivery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Send only the fields to change."},"delete":{"tags":["deliveries"],"summary":"Delete delivery","operationId":"deliveries_id_delete_deliveries__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The delivery was deleted.","content":{"application/json":{"schema":{}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/lots":{"get":{"tags":["lots"],"summary":"List lots","operationId":"delivery_lots_get_lots_get","responses":{"200":{"description":"All delivery lots in your account.","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DeliveryLotResponse"},"type":"array","title":"Response Delivery Lots Get Lots Get"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}},"security":[{"APIKeyHeader":[]}],"description":"Every delivery lot in your account with its state, depot, fleet and deliveries."},"post":{"tags":["lots"],"summary":"Create lot","operationId":"delivery_lots_post_lots_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLotCreate"},"example":{"milestone_id":"7","fleet_id":"3","deliveries":["101","102","103"],"route_limits":{"stops_max":40},"config":{"schedule":{"start_at":"2026-09-15T08:00:00Z","respect_delivery_windows":true},"rebalance":{"rebalance_by_volume":{"enabled":true,"min_volume_capacity_ratio_vehicle":0.6,"max_volume_capacity_ratio_vehicle":0.95}},"routing":{"service_time_min":4},"clustering":{"force_vehicles_fleet_match":false}}}}},"required":true},"responses":{"201":{"description":"The created delivery lot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLotResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"APIKeyHeader":[]}],"description":"Groups a depot, a fleet and deliveries for one optimization run, and reserves the lot's stops against your monthly allowance.\n\nReturns `403` with `reason` `max_stops_per_request`, `monthly_limit` or `max_stops_per_route` when the lot does not fit your plan."}},"/lots/{id}":{"get":{"tags":["lots"],"summary":"Get lot","operationId":"delivery_lots_id_get_lots__id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The delivery lot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLotResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["lots"],"summary":"Update lot","operationId":"delivery_lots_id_patch_lots__id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLotUpdate"},"example":{"deliveries":["101","102","103","104"]}}}},"responses":{"200":{"description":"The updated delivery lot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryLotResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Change deliveries, fleet, drivers or configuration before queueing a plan. All fields are optional."},"delete":{"tags":["lots"],"summary":"Delete lot","operationId":"delivery_lots_id_delete_lots__id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The delivery lot was deleted.","content":{"application/json":{"schema":{}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Deletes the lot and releases any stops it still has reserved."}},"/lots/{id}/plan":{"post":{"tags":["lots"],"summary":"Queue plan","description":"Sends the lot to the optimizer. No body. The lot moves to `PROCESSING`.\n\nReturns `409` when the lot is already `PROCESSING` or `OPTIMIZING`, and `422` when the fleet has no vehicles, the lot has no deliveries or its stop bounds cannot be met. Queueing a `PROCESSED` lot starts a fresh plan.","operationId":"delivery_lots_id_plan_post_lots__id__plan_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"202":{"description":"Plan queued. Returns the optimizer async session id for progress polling.","headers":{"X-Optimizer-Session-Id":{"description":"Optimizer run id, the same value as `session_id` in the body.","schema":{"type":"string","format":"uuid"}},"X-RouteHub-Tenant-Id":{"description":"Workspace id of the authenticated account. Informational.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueuePlanResponse"},"example":{"code":202,"message":"Delivery plan queued for processing","session_id":"123e4567-e89b-12d3-a456-426614174000","optimizer_session_id":"123e4567-e89b-12d3-a456-426614174000"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The lot is already `PROCESSING` or `OPTIMIZING`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"},"example":{"code":409,"message":"The plan is being processed"}}}},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["lots"],"summary":"Get plan","operationId":"delivery_lots_id_plan_get_lots__id__plan_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"The plan, or a short poll response while it is still running.","headers":{"X-RouteHub-Tenant-Id":{"description":"Workspace id of the authenticated account. Informational.","schema":{"type":"integer"}},"X-Optimizer-Session-Id":{"description":"Optimizer run id, the same value as `session_id` in the body.","schema":{"type":"string","format":"uuid"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryPlanResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Returns `state: \"PROCESSING\"` with `routes: null` while the optimizer works. Once it finishes, this call stores the routes, moves the lot to `PROCESSED` and returns the full plan. Keep calling it until `state` is `PROCESSED`; stops are charged at that moment.\n\nReturns `404` before any plan was queued."},"patch":{"tags":["lots"],"summary":"Re-sequence routes","operationId":"delivery_lots_id_plan_patch_lots__id__plan_patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DeliveryRouteUpdate"},"minItems":1,"title":"Patch Data"},"example":[{"id":"5012","deliveries":["101","104","102"]},{"id":"5013","deliveries":["103"]}]}}},"responses":{"202":{"description":"Routes queued for re-sequencing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"},"example":{"code":202,"message":"Routes queued for optimization"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/PlanLimitExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The lot is not `PROCESSED`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"},"example":{"code":409,"message":"The plan must be 'PROCESSED' to be updated"}}}},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"description":"Moves deliveries between routes of a `PROCESSED` plan and re-sequences the routes you send. Each item names a route `id` and the deliveries it should contain; an empty list removes the route. The lot moves to `OPTIMIZING`; read it with `GET /lots/{id}/plan` until it is `PROCESSED` again.\n\nReturns `409` when the lot is not `PROCESSED`, and `404` when a route or delivery does not belong to the lot."}},"/lots/{id}/plan/status":{"parameters":[{"name":"id","in":"path","required":true,"description":"Delivery lot id (same id used in POST /lots/{id}/plan)","schema":{"type":"integer","title":"Id"}}],"get":{"tags":["lots"],"summary":"Get plan progress","description":"Live optimizer progress (`progress_pct`, `phase`, `steps`, `details`) while the lot is `PROCESSING`. Poll every 2 to 3 seconds for progress UIs, and read the result with `GET /lots/{id}/plan`.\n\nReturns `409` when the lot is not `PROCESSING` and `404` when no plan was queued.","operationId":"delivery_lots_id_plan_status_get","security":[{"APIKeyHeader":[]}],"responses":{"200":{"description":"Optimizer progress payload (passthrough)","headers":{"X-Optimizer-Session-Id":{"description":"Optimizer run id, the same value as `session_id` in the body.","schema":{"type":"string","format":"uuid"}},"X-RouteHub-Tenant-Id":{"description":"Workspace id of the authenticated account. Informational.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/session_progress_response"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The lot is not `PROCESSING`, so there is no live progress."},"422":{"description":"The body or a parameter does not match the schema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/templates/package-templates":{"get":{"tags":["templates"],"summary":"List package templates","description":"Session-authenticated gateway endpoint, native to this app (not a RouteHub proxy). Returns the caller's package templates, sorted by name.","operationId":"templates_package_templates_get","security":[{"bearerJWT":[]}],"responses":{"200":{"description":"Package templates for the authenticated user.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PackageTemplate"}}}}}}},"401":{"description":"Not signed in"}}},"post":{"tags":["templates"],"summary":"Create a package template","description":"Rejected with 403 once the caller's plan quota (`PlanLimits.maxPackageTemplatesPerAccount`) is reached.","operationId":"templates_package_templates_post","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageTemplateInput"}}}},"responses":{"201":{"description":"Created package template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageTemplate"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"},"403":{"description":"Plan quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateQuotaExceededError"}}}}}}},"/api/templates/package-templates/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["templates"],"summary":"Update a package template","operationId":"templates_package_templates_id_patch","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageTemplatePatch"}}}},"responses":{"200":{"description":"Updated package template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageTemplate"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"},"404":{"description":"Not found, or not owned by the caller"}}},"delete":{"tags":["templates"],"summary":"Delete a package template","operationId":"templates_package_templates_id_delete","security":[{"bearerJWT":[]}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Not signed in"},"404":{"description":"Not found, or not owned by the caller"}}}},"/api/templates/package-templates/bulk":{"post":{"tags":["templates"],"summary":"Bulk-create package templates","description":"Creates up to 1000 templates from `{ \"items\": [...] }`. When the batch exceeds your remaining plan quota, what fits is created and the rest is reported in `rejected`; the call does not fail on quota.","operationId":"templates_package_templates_bulk_post","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":1000,"items":{"$ref":"#/components/schemas/PackageTemplateInput"}}}}}}},"responses":{"200":{"description":"Bulk-create result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageTemplateBulkResult"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"}}}},"/api/templates/stop-templates":{"get":{"tags":["templates"],"summary":"List stop templates","description":"Session-authenticated gateway endpoint, native to this app (not a RouteHub proxy). Returns the caller's saved stop presets, sorted by name.","operationId":"templates_stop_templates_get","security":[{"bearerJWT":[]}],"responses":{"200":{"description":"Stop templates for the authenticated user.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StopTemplate"}}}}}}},"401":{"description":"Not signed in"}}},"post":{"tags":["templates"],"summary":"Create a stop template","description":"Rejected with 403 once the caller's plan quota (`PlanLimits.maxStopTemplatesPerAccount`) is reached.","operationId":"templates_stop_templates_post","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopTemplateInput"}}}},"responses":{"201":{"description":"Created stop template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopTemplate"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"},"403":{"description":"Plan quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateQuotaExceededError"}}}}}}},"/api/templates/stop-templates/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["templates"],"summary":"Update a stop template","operationId":"templates_stop_templates_id_patch","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopTemplatePatch"}}}},"responses":{"200":{"description":"Updated stop template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopTemplate"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"},"404":{"description":"Not found, or not owned by the caller"}}},"delete":{"tags":["templates"],"summary":"Delete a stop template","operationId":"templates_stop_templates_id_delete","security":[{"bearerJWT":[]}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Not signed in"},"404":{"description":"Not found, or not owned by the caller"}}}},"/api/templates/stop-templates/bulk":{"post":{"tags":["templates"],"summary":"Bulk-create stop templates","description":"Creates up to 1000 templates from `{ \"items\": [...] }`. When the batch exceeds your remaining plan quota, what fits is created and the rest is reported in `rejected`; the call does not fail on quota.","operationId":"templates_stop_templates_bulk_post","security":[{"bearerJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":1000,"items":{"$ref":"#/components/schemas/StopTemplateInput"}}}}}}},"responses":{"200":{"description":"Bulk-create result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopTemplateBulkResult"}}}},"400":{"description":"Invalid request body"},"401":{"description":"Not signed in"}}}}},"components":{"schemas":{"DeliveryBulkResponse":{"properties":{"success":{"items":{"$ref":"#/components/schemas/Success"},"type":"array","title":"Success"},"failure":{"items":{"$ref":"#/components/schemas/Failure"},"type":"array","title":"Failure"}},"type":"object","required":["success","failure"],"title":"DeliveryBulkResponse"},"DeliveryCreate":{"properties":{"destination":{"type":"string","title":"Destination","description":"Stop location. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"method":{"anyOf":[{"$ref":"#/components/schemas/DeliveryMethod"},{"type":"null"}]},"schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Schedules","description":"Time windows. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width","description":"Package width, in `length_unit`. Integer."},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Package height, in `length_unit`. Integer."},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth","description":"Package depth, in `length_unit`. Integer."},"length_unit":{"anyOf":[{"$ref":"#/components/schemas/LengthUnit"},{"type":"null"}]},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Package volume, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Package weight, in `weight_unit`. Integer; use `GRAMS` for fractional kilograms."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"packaging":{"anyOf":[{"$ref":"#/components/schemas/PackagingType"},{"type":"null"}]},"handling":{"anyOf":[{"items":{"$ref":"#/components/schemas/SpecialHandling"},"type":"array"},{"type":"null"}],"title":"Handling"},"value_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value Cents","description":"Declared value in minor units (`5000` is 50.00)."},"value_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Currency","description":"ISO 4217 currency code."},"extra":{"anyOf":[{},{"type":"null"}],"title":"Extra","description":"Your own metadata, returned as sent. The planner reads `lat`, `lng`, `packages` and `zone` if present."},"milestone_id":{"type":"string","title":"Milestone Id","description":"Milestone the package leaves from."}},"type":"object","required":["destination","milestone_id"],"title":"DeliveryCreate"},"DeliveryLotCreate":{"properties":{"vehicle_limits":{"anyOf":[{"$ref":"#/components/schemas/VehicleLimits"},{"type":"null"}],"description":"Legacy fill bounds. Stored and returned but not applied; use `config.rebalance`."},"route_limits":{"anyOf":[{"$ref":"#/components/schemas/RouteLimits"},{"type":"null"}],"description":"Bounds applied to every route. Per-vehicle settings take precedence."},"milestone_id":{"type":"string","title":"Milestone Id","description":"Depot every route starts from."},"deliveries":{"items":{"type":"string"},"type":"array","title":"Deliveries","description":"Delivery ids to plan."},"fleet_id":{"type":"string","title":"Fleet Id","description":"Fleet available for this run."},"drivers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Drivers","description":"Driver ids attached to the lot."},"config":{"anyOf":[{"$ref":"#/components/schemas/LotConfig"},{"type":"null"}],"description":"Per-run settings: schedule, load balancing, per-vehicle overrides, routing and clustering."}},"type":"object","required":["milestone_id","deliveries","fleet_id"],"title":"DeliveryLotCreate"},"DeliveryLotResponse":{"properties":{"vehicle_limits":{"anyOf":[{"$ref":"#/components/schemas/VehicleLimits"},{"type":"null"}],"description":"Legacy fill bounds. Stored and returned but not applied; use `config.rebalance`."},"route_limits":{"anyOf":[{"$ref":"#/components/schemas/RouteLimits"},{"type":"null"}],"description":"Bounds applied to every route. Per-vehicle settings take precedence."},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"},"state":{"$ref":"#/components/schemas/DeliveryLotState"},"milestone":{"$ref":"#/components/schemas/MilestoneResponse"},"deliveries":{"items":{"$ref":"#/components/schemas/DeliveryResponse"},"type":"array","title":"Deliveries","description":"Delivery ids to plan."},"delivery_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delivery Count"},"fleet":{"anyOf":[{"$ref":"#/components/schemas/FleetResponse"},{"type":"null"}]},"drivers":{"anyOf":[{"items":{"$ref":"#/components/schemas/DriverResponse"},"type":"array"},{"type":"null"}],"title":"Drivers","description":"Driver ids attached to the lot."},"config":{"anyOf":[{"$ref":"#/components/schemas/LotConfig"},{"type":"null"}],"description":"Per-run settings: schedule, load balancing, per-vehicle overrides, routing and clustering."}},"type":"object","required":["id","state","milestone","deliveries"],"title":"DeliveryLotResponse"},"DeliveryLotState":{"type":"string","enum":["UNPROCESSED","PROCESSING","OPTIMIZING","PROCESSED","CANCELED"],"title":"DeliveryLotState"},"DeliveryLotUpdate":{"properties":{"vehicle_limits":{"anyOf":[{"$ref":"#/components/schemas/VehicleLimits"},{"type":"null"}],"description":"Legacy fill bounds. Stored and returned but not applied; use `config.rebalance`."},"route_limits":{"anyOf":[{"$ref":"#/components/schemas/RouteLimits"},{"type":"null"}],"description":"Bounds applied to every route. Per-vehicle settings take precedence."},"milestone_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Milestone Id","description":"Depot every route starts from."},"deliveries":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Deliveries","description":"Delivery ids to plan."},"fleet_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fleet Id","description":"Fleet available for this run."},"drivers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Drivers","description":"Driver ids attached to the lot."},"config":{"anyOf":[{"$ref":"#/components/schemas/LotConfig"},{"type":"null"}],"description":"Per-run settings: schedule, load balancing, per-vehicle overrides, routing and clustering."}},"type":"object","title":"DeliveryLotUpdate"},"DeliveryMethod":{"type":"string","enum":["DELIVERY","PICKUP","SIGNATURE"],"title":"DeliveryMethod"},"DeliveryPlanTotals":{"type":"object","title":"DeliveryPlanTotals","properties":{"total_routes":{"type":"integer"},"total_points":{"type":"integer"},"submitted_points":{"type":"integer","description":"Stops submitted to the optimizer (may exceed total_points when some are rejected)."},"unserved_points":{"type":"integer","description":"Submitted stops not assigned to any route."},"total_distance_km":{"type":"number"},"total_duration_sec":{"type":"number"},"execution_time_sec":{"type":"number"},"rejection_summary":{"type":"object","additionalProperties":{"type":"integer"},"description":"Counts of rejections by reason code."},"rejected_deliveries":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Per-delivery rejection details from the optimizer."},"fleet_metrics":{"type":"object","additionalProperties":true},"time_windows_global":{"type":"object","additionalProperties":true}}},"OptimizedWaypoint":{"type":"object","title":"OptimizedWaypoint","properties":{"order":{"type":"integer"},"lat":{"type":"number"},"lng":{"type":"number"},"delivery_id":{"type":"string","description":"Delivery id for this stop (mapped from package_id)."},"arrival_time":{"description":"Estimated arrival in minutes after midnight, including the route start.","anyOf":[{"type":"number"},{"type":"string"}]}}},"RoutePathData":{"type":"object","title":"RoutePathData","description":"Optimizer route_data persisted per delivery path (also surfaced on routes[] when merged).","properties":{"route_id":{"type":"string"},"route_index":{"type":"integer"},"route_geometry":{"type":"array","items":{"type":"array","items":{"type":"number"}}},"optimized_waypoints":{"type":"array","items":{"$ref":"#/components/schemas/OptimizedWaypoint"}},"stops":{"type":"array","items":{"$ref":"#/components/schemas/OptimizedWaypoint"},"description":"Alias of optimized_waypoints."},"arrival_times":{"type":"array","items":{"anyOf":[{"type":"number"},{"type":"string"},{"type":"null"}]}},"total_distance_km":{"type":"number"},"total_duration_sec":{"type":"number"},"num_points":{"type":"integer"}}},"DeliveryPlanResponse":{"properties":{"state":{"$ref":"#/components/schemas/DeliveryLotState"},"routes":{"anyOf":[{"items":{"$ref":"#/components/schemas/RouteResponse"},"type":"array"},{"type":"null"}],"title":"Routes","description":"Optimized routes. `null` while the plan is still running."},"delivery_paths":{"description":"Per-route optimizer payloads (route_data), including optimized_waypoints and arrival_times.","anyOf":[{"items":{"$ref":"#/components/schemas/RoutePathData"},"type":"array"},{"type":"null"}],"title":"Delivery Paths"},"totals":{"anyOf":[{"$ref":"#/components/schemas/DeliveryPlanTotals"},{"type":"null"}],"description":"Plan-wide totals, including stops that could not be placed."},"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"Optimizer run id. Poll `GET /lots/{id}/plan/status` for progress while `state` is `PROCESSING`."},"optimizer_session_id":{"type":"string","format":"uuid","title":"Optimizer Session Id","description":"Alias of session_id (same optimizer task UUID)."}},"type":"object","required":["state"],"title":"DeliveryPlanResponse","description":"Poll response while running (`state` `PROCESSING` or `OPTIMIZING`, `routes` null) or the full plan once `state` is `PROCESSED`."},"DeliveryResponse":{"properties":{"destination":{"type":"string","title":"Destination","description":"Stop location. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"method":{"anyOf":[{"$ref":"#/components/schemas/DeliveryMethod"},{"type":"null"}]},"schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Schedules","description":"Time windows. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width","description":"Package width, in `length_unit`. Integer."},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Package height, in `length_unit`. Integer."},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth","description":"Package depth, in `length_unit`. Integer."},"length_unit":{"anyOf":[{"$ref":"#/components/schemas/LengthUnit"},{"type":"null"}]},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Package volume, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Package weight, in `weight_unit`. Integer; use `GRAMS` for fractional kilograms."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"packaging":{"anyOf":[{"$ref":"#/components/schemas/PackagingType"},{"type":"null"}]},"handling":{"anyOf":[{"items":{"$ref":"#/components/schemas/SpecialHandling"},"type":"array"},{"type":"null"}],"title":"Handling"},"value_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value Cents","description":"Declared value in minor units (`5000` is 50.00)."},"value_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Currency","description":"ISO 4217 currency code."},"extra":{"anyOf":[{},{"type":"null"}],"title":"Extra","description":"Your own metadata, returned as sent. The planner reads `lat`, `lng`, `packages` and `zone` if present."},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"},"milestone":{"anyOf":[{"$ref":"#/components/schemas/MilestoneResponse"},{"type":"null"}]},"arrival_time":{"description":"Estimated arrival in minutes after midnight, including the route start from `config.schedule.start_at`. Present on deliveries inside plan routes.","anyOf":[{"type":"number"},{"type":"string"},{"type":"null"}]}},"type":"object","required":["destination","id","milestone"],"title":"DeliveryResponse"},"DeliveryRouteUpdate":{"properties":{"id":{"type":"string","title":"Id","description":"Route id from the processed plan."},"deliveries":{"items":{"type":"string"},"type":"array","title":"Deliveries","description":"Delivery ids the route should contain, in any order. An empty list removes the route."}},"type":"object","required":["id","deliveries"],"title":"DeliveryRouteUpdate"},"DeliveryUpdate":{"properties":{"destination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destination","description":"Stop location. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"method":{"anyOf":[{"$ref":"#/components/schemas/DeliveryMethod"},{"type":"null"}]},"schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Schedules","description":"Time windows. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width","description":"Package width, in `length_unit`. Integer."},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Package height, in `length_unit`. Integer."},"depth":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Depth","description":"Package depth, in `length_unit`. Integer."},"length_unit":{"anyOf":[{"$ref":"#/components/schemas/LengthUnit"},{"type":"null"}]},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Package volume, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Package weight, in `weight_unit`. Integer; use `GRAMS` for fractional kilograms."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"packaging":{"anyOf":[{"$ref":"#/components/schemas/PackagingType"},{"type":"null"}]},"handling":{"anyOf":[{"items":{"$ref":"#/components/schemas/SpecialHandling"},"type":"array"},{"type":"null"}],"title":"Handling"},"value_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value Cents","description":"Declared value in minor units (`5000` is 50.00)."},"value_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value Currency","description":"ISO 4217 currency code."},"extra":{"anyOf":[{},{"type":"null"}],"title":"Extra","description":"Your own metadata, returned as sent. The planner reads `lat`, `lng`, `packages` and `zone` if present."},"milestone_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Milestone Id","description":"Milestone the package leaves from."}},"type":"object","title":"DeliveryUpdate"},"DriverCreate":{"properties":{"first_name":{"type":"string","title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"work_schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Work Schedules","description":"Working hours. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"start_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Point","description":"Where the driver starts the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"end_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Point","description":"Where the driver ends the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"work_areas":{"anyOf":[{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},{"type":"null"}],"title":"Work Areas","description":"Polygons, each an array of `geo_point` vertices."},"vehicles":{"anyOf":[{"items":{"$ref":"#/components/schemas/DriverVehicleCreate"},"type":"array"},{"type":"null"}],"title":"Vehicles","description":"Vehicle types the driver can operate."}},"type":"object","required":["first_name"],"title":"DriverCreate"},"DriverResponse":{"properties":{"first_name":{"type":"string","title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"work_schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Work Schedules","description":"Working hours. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"start_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Point","description":"Where the driver starts the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"end_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Point","description":"Where the driver ends the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"work_areas":{"anyOf":[{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},{"type":"null"}],"title":"Work Areas","description":"Polygons, each an array of `geo_point` vertices."},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"},"vehicles":{"anyOf":[{"items":{"$ref":"#/components/schemas/DriverVehicleResponse"},"type":"array"},{"type":"null"}],"title":"Vehicles","description":"Vehicle types the driver can operate."}},"type":"object","required":["first_name","id"],"title":"DriverResponse"},"DriverUpdate":{"properties":{"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"work_schedules":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Work Schedules","description":"Working hours. RFC 5545 VEVENT: `DTSTART` plus `DTEND` or `DURATION`, optionally `RRULE`. Join lines with `\\n`."},"start_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Point","description":"Where the driver starts the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"end_point":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Point","description":"Where the driver ends the day. Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"work_areas":{"anyOf":[{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},{"type":"null"}],"title":"Work Areas","description":"Polygons, each an array of `geo_point` vertices."},"vehicles":{"anyOf":[{"items":{"$ref":"#/components/schemas/DriverVehicleCreate"},"type":"array"},{"type":"null"}],"title":"Vehicles","description":"Vehicle types the driver can operate."}},"type":"object","title":"DriverUpdate"},"DriverVehicleCreate":{"properties":{"qty":{"type":"integer","title":"Qty"},"id":{"type":"string","title":"Id"}},"type":"object","required":["qty","id"],"title":"DriverVehicleCreate"},"DriverVehicleResponse":{"properties":{"name":{"type":"string","title":"Name"},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume"},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight"},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"consumption":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Consumption"},"consumption_unit":{"anyOf":[{"$ref":"#/components/schemas/VehicleConsumptionUnit"},{"type":"null"}]},"category_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleCategoryType"},{"type":"null"}]},"engine_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleEngineType"},{"type":"null"}]},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"},"qty":{"type":"integer","title":"Qty"}},"type":"object","required":["name","id","qty"],"title":"DriverVehicleResponse"},"Error":{"properties":{"msg":{"type":"string","title":"Msg"},"inp":{"title":"Inp"},"loc":{"items":{},"type":"array","title":"Loc"}},"type":"object","required":["msg","inp","loc"],"title":"Error"},"Failure":{"properties":{"idx":{"type":"integer","title":"Idx"},"err":{"items":{"$ref":"#/components/schemas/Error"},"type":"array","title":"Err"}},"type":"object","required":["idx","err"],"title":"Failure"},"FleetCreate":{"properties":{"name":{"type":"string","title":"Name"},"vehicles":{"items":{"$ref":"#/components/schemas/FleetVehicleCreate"},"type":"array","title":"Vehicles"}},"type":"object","required":["name","vehicles"],"title":"FleetCreate"},"FleetResponse":{"properties":{"name":{"type":"string","title":"Name"},"vehicles":{"items":{"$ref":"#/components/schemas/FleetVehicleResponse"},"type":"array","title":"Vehicles"},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"}},"type":"object","required":["name","vehicles","id"],"title":"FleetResponse"},"FleetUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"vehicles":{"anyOf":[{"items":{"$ref":"#/components/schemas/FleetVehicleCreate"},"type":"array"},{"type":"null"}],"title":"Vehicles"}},"type":"object","title":"FleetUpdate"},"FleetVehicleCreate":{"properties":{"qty":{"type":"integer","title":"Qty","description":"Units of this vehicle type. The sum across the fleet counts against your plan's units per fleet."},"id":{"type":"string","title":"Id","description":"Vehicle id from `/vehicles`."},"alias":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias","description":"Name for this entry, unique within the fleet. Lets the same vehicle type appear more than once with different route or behavior limits."},"route":{"anyOf":[{"$ref":"#/components/schemas/VehicleRouteConfig"},{"type":"null"}]},"behavior":{"anyOf":[{"$ref":"#/components/schemas/VehicleBehaviorConfig"},{"type":"null"}]}},"type":"object","required":["qty","id"],"title":"FleetVehicleCreate"},"FleetVehicleResponse":{"properties":{"name":{"type":"string","title":"Name"},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume"},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight"},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"consumption":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Consumption"},"consumption_unit":{"anyOf":[{"$ref":"#/components/schemas/VehicleConsumptionUnit"},{"type":"null"}]},"category_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleCategoryType"},{"type":"null"}]},"engine_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleEngineType"},{"type":"null"}]},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"},"qty":{"type":"integer","title":"Qty"},"alias":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias","description":"Name for this entry, unique within the fleet. Lets the same vehicle type appear more than once with different route or behavior limits."},"route":{"anyOf":[{"$ref":"#/components/schemas/VehicleRouteConfig"},{"type":"null"}]},"behavior":{"anyOf":[{"$ref":"#/components/schemas/VehicleBehaviorConfig"},{"type":"null"}]}},"type":"object","required":["name","id","qty"],"title":"FleetVehicleResponse"},"FleetDeleteResponse":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["deleted"]},"message":{"type":"string"}},"title":"FleetDeleteResponse"},"VehicleDeleteResponse":{"type":"object","required":["code","message","fleetNames"],"properties":{"code":{"type":"string","enum":["deleted","unlinked","not_in_fleet"]},"message":{"type":"string"},"fleetNames":{"type":"array","items":{"type":"string"},"description":"Fleet names the vehicle was removed from (empty if none)."}},"title":"VehicleDeleteResponse"},"VehicleDeleteBlocked":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["vehicle_in_use"]},"message":{"type":"string"}},"title":"VehicleDeleteBlocked"},"RouteHubDeleteNotFound":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["not_found"]},"message":{"type":"string"}},"title":"RouteHubDeleteNotFound"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PackageTemplate":{"type":"object","description":"Saved dimension, weight and handling preset. Enum-like fields are stored as plain strings; the referenced enums document the accepted values rather than enforce them.","required":["id","name","method","weight","weight_unit","width","height","depth","length_unit","packaging","handling","value","value_currency","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"method":{"$ref":"#/components/schemas/DeliveryMethod"},"weight":{"type":"string"},"weight_unit":{"$ref":"#/components/schemas/WeightUnit"},"width":{"type":"string"},"height":{"type":"string"},"depth":{"type":"string"},"length_unit":{"$ref":"#/components/schemas/LengthUnit"},"packaging":{"$ref":"#/components/schemas/PackagingType"},"handling":{"type":"array","items":{"$ref":"#/components/schemas/SpecialHandling"}},"value":{"type":"string","description":"Declared value, in cents (e.g. \"5000\" = $50.00)."},"value_currency":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"title":"PackageTemplate"},"PackageTemplateInput":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"method":{"type":"string","description":"Defaults to DELIVERY when omitted.","maxLength":40},"weight":{"type":"string","maxLength":40},"weight_unit":{"type":"string","description":"Defaults to KILOGRAMS when omitted.","maxLength":40},"width":{"type":"string","maxLength":40},"height":{"type":"string","maxLength":40},"depth":{"type":"string","maxLength":40},"length_unit":{"type":"string","description":"Defaults to CENTIMETER when omitted.","maxLength":40},"packaging":{"type":"string","description":"Defaults to BOX when omitted.","maxLength":40},"handling":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":40}},"value":{"type":"string","maxLength":40},"value_currency":{"type":"string","description":"Defaults to USD when omitted.","maxLength":10}},"title":"PackageTemplateInput"},"PackageTemplatePatch":{"allOf":[{"$ref":"#/components/schemas/PackageTemplateInput"}],"required":[],"title":"PackageTemplatePatch","description":"Same fields as PackageTemplateInput, all optional. Only the fields you send are updated."},"PackageTemplateBulkResult":{"type":"object","required":["created","accepted","rejected","limit","used"],"properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/PackageTemplate"}},"accepted":{"type":"integer","description":"Number of items actually created."},"rejected":{"type":"integer","description":"Number of items dropped because the plan quota was reached."},"limit":{"type":"integer","nullable":true,"description":"Plan cap, or null when unlimited."},"used":{"type":"integer","description":"Template count before this bulk create."}},"title":"PackageTemplateBulkResult"},"StopTemplate":{"type":"object","required":["id","name","stop","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"stop":{"$ref":"#/components/schemas/StopTemplateStop"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"title":"StopTemplate"},"StopTemplateStop":{"type":"object","description":"Stored as sent. Only `lat` and `lng` are validated; extra fields are kept.","required":["lat","lng"],"additionalProperties":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"},"address":{"type":"string"},"milestoneId":{"type":"string"},"twStartMinutes":{"type":"integer","nullable":true,"description":"Minutes since UTC midnight."},"twEndMinutes":{"type":"integer","nullable":true,"description":"Minutes since UTC midnight."},"packages":{"type":"array","items":{"type":"object","description":"Same fields as PackageTemplateInput.","additionalProperties":true}}},"title":"StopTemplateStop"},"StopTemplateInput":{"type":"object","required":["name","stop"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"stop":{"$ref":"#/components/schemas/StopTemplateStop"}},"title":"StopTemplateInput"},"StopTemplatePatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"stop":{"$ref":"#/components/schemas/StopTemplateStop"}},"title":"StopTemplatePatch","description":"Same fields as StopTemplateInput, all optional. Only the fields you send are updated."},"StopTemplateBulkResult":{"type":"object","required":["created","accepted","rejected","limit","used"],"properties":{"created":{"type":"array","items":{"$ref":"#/components/schemas/StopTemplate"}},"accepted":{"type":"integer","description":"Number of items actually created."},"rejected":{"type":"integer","description":"Number of items dropped because the plan quota was reached."},"limit":{"type":"integer","nullable":true,"description":"Plan cap, or null when unlimited."},"used":{"type":"integer","description":"Template count before this bulk create."}},"title":"StopTemplateBulkResult"},"TemplateQuotaExceededError":{"type":"object","required":["error","message","limit","used"],"properties":{"error":{"type":"string","enum":["plan_quota_exceeded"]},"message":{"type":"string"},"limit":{"type":"integer"},"used":{"type":"integer"}},"title":"TemplateQuotaExceededError"},"QueuePlanResponse":{"type":"object","required":["code","message","session_id","optimizer_session_id"],"properties":{"code":{"type":"integer","example":202},"message":{"type":"string"},"session_id":{"type":"string","format":"uuid","description":"Optimizer run id. Also returned in `X-Optimizer-Session-Id`."},"optimizer_session_id":{"type":"string","format":"uuid","description":"Same UUID as session_id."}},"title":"QueuePlanResponse"},"LengthUnit":{"type":"string","enum":["CENTIMETER","METER","KILOMETER","INCH","FEET","MILE"],"title":"LengthUnit"},"LotConfig":{"properties":{"vehicles":{"anyOf":[{"$ref":"#/components/schemas/VehiclesConfig"},{"type":"null"}],"description":"Per-vehicle overrides for this run only."},"rebalance":{"anyOf":[{"$ref":"#/components/schemas/RebalanceConfig"},{"type":"null"}],"description":"Load-balancing strategies that move stops between routes."},"schedule":{"anyOf":[{"$ref":"#/components/schemas/ScheduleConfig"},{"type":"null"}],"description":"Route start time and delivery time-window handling."},"clustering":{"anyOf":[{"$ref":"#/components/schemas/ClusteringConfig"},{"type":"null"}]},"routing":{"anyOf":[{"$ref":"#/components/schemas/RoutingConfig"},{"type":"null"}]},"zone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zone","description":"Reserved grouping label. Leave unset unless Vepathos asks you to use it."}},"type":"object","title":"LotConfig","description":"Per-run settings for a delivery lot. Every section is optional."},"MilestoneCategory":{"type":"string","enum":["DEPOT","DISTRIBUTION_CENTER","LOADING_POINT","WAREHOUSE","TRANSFER_POINT"],"title":"MilestoneCategory"},"MilestoneCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Display name."},"location":{"type":"string","title":"Location","description":"Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"category":{"anyOf":[{"$ref":"#/components/schemas/MilestoneCategory"},{"type":"null"}],"description":"Kind of location."}},"type":"object","required":["name","location"],"title":"MilestoneCreate"},"MilestoneResponse":{"properties":{"name":{"type":"string","title":"Name","description":"Display name."},"location":{"type":"string","title":"Location","description":"Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"category":{"anyOf":[{"$ref":"#/components/schemas/MilestoneCategory"},{"type":"null"}],"description":"Kind of location."},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"}},"type":"object","required":["name","location","id"],"title":"MilestoneResponse"},"MilestoneUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Display name."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Coordinates in ISO 6709 decimal degrees, latitude then longitude with signs, e.g. `+40.7128-74.0060`."},"category":{"anyOf":[{"$ref":"#/components/schemas/MilestoneCategory"},{"type":"null"}],"description":"Kind of location."}},"type":"object","title":"MilestoneUpdate"},"PackagingType":{"type":"string","enum":["BOX","ENVELOPE","BAG","CARTON","PALLET","SHRINK_WRAP"],"title":"PackagingType"},"RebalanceByDistanceConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true,"description":"Even out the distance each vehicle drives."}},"type":"object","title":"RebalanceByDistanceConfig"},"RebalanceBySizeConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true,"description":"Even out the number of stops per route."}},"type":"object","title":"RebalanceBySizeConfig"},"RebalanceByTimeConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true,"description":"Apply this strategy. Defaults to `true` when the object is present."},"min_time_minutes_per_route":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Time Minutes Per Route","description":"Target minimum route duration in minutes."},"max_time_minutes_per_route":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Time Minutes Per Route","description":"Target maximum route duration in minutes."}},"type":"object","title":"RebalanceByTimeConfig"},"RebalanceByVolumeConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true,"description":"Apply this strategy. Defaults to `true` when the object is present."},"min_volume_capacity_ratio_vehicle_initial":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Volume Capacity Ratio Vehicle Initial","description":"Minimum volume fill ratio (0 to 1) during the first clustering pass."},"max_volume_capacity_ratio_vehicle_initial":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Volume Capacity Ratio Vehicle Initial","description":"Maximum volume fill ratio (0 to 1) during the first clustering pass."},"min_volume_capacity_ratio_vehicle":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Volume Capacity Ratio Vehicle","description":"Minimum volume fill ratio (0 to 1) for final routes."},"max_volume_capacity_ratio_vehicle":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Volume Capacity Ratio Vehicle","description":"Maximum volume fill ratio (0 to 1) for final routes."}},"type":"object","title":"RebalanceByVolumeConfig"},"RebalanceByWeightConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true,"description":"Apply this strategy. Defaults to `true` when the object is present."},"min_weight_capacity_ratio_vehicle":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Weight Capacity Ratio Vehicle","description":"Minimum weight fill ratio (0 to 1)."},"max_weight_capacity_ratio_vehicle":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Weight Capacity Ratio Vehicle","description":"Maximum weight fill ratio (0 to 1)."}},"type":"object","title":"RebalanceByWeightConfig"},"RebalanceConfig":{"properties":{"rebalance_by_volume":{"anyOf":[{"$ref":"#/components/schemas/RebalanceByVolumeConfig"},{"type":"null"}]},"rebalance_by_size":{"anyOf":[{"$ref":"#/components/schemas/RebalanceBySizeConfig"},{"type":"null"}]},"rebalance_by_weight":{"anyOf":[{"$ref":"#/components/schemas/RebalanceByWeightConfig"},{"type":"null"}]},"rebalance_by_time":{"anyOf":[{"$ref":"#/components/schemas/RebalanceByTimeConfig"},{"type":"null"}]},"rebalance_by_distance":{"anyOf":[{"$ref":"#/components/schemas/RebalanceByDistanceConfig"},{"type":"null"}]}},"type":"object","title":"RebalanceConfig"},"RouteLimits":{"properties":{"stops_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stops Min"},"stops_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stops Max"},"length_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Length Min"},"length_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Length Max"},"length_unit":{"anyOf":[{"$ref":"#/components/schemas/LengthUnit"},{"type":"null"}]},"time_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Time Min"},"time_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Time Max"},"time_unit":{"anyOf":[{"$ref":"#/components/schemas/TimeUnit"},{"type":"null"}]}},"type":"object","title":"RouteLimits"},"RouteResponse":{"properties":{"id":{"type":"string","title":"Id"},"milestone":{"$ref":"#/components/schemas/MilestoneResponse"},"deliveries":{"items":{"$ref":"#/components/schemas/DeliveryResponse"},"type":"array","title":"Deliveries"},"vehicle":{"anyOf":[{"$ref":"#/components/schemas/VehicleResponse"},{"type":"null"}]},"driver":{"anyOf":[{"$ref":"#/components/schemas/DriverResponse"},{"type":"null"}]},"route_id":{"type":"string"},"route_index":{"type":"integer"},"route_geometry":{"type":"array","items":{"type":"array","items":{"type":"number"}}},"optimized_waypoints":{"type":"array","items":{"$ref":"#/components/schemas/OptimizedWaypoint"}},"stops":{"type":"array","items":{"$ref":"#/components/schemas/OptimizedWaypoint"}},"arrival_times":{"type":"array","items":{"anyOf":[{"type":"number"},{"type":"string"},{"type":"null"}]}},"total_distance_km":{"type":"number"},"total_duration_sec":{"type":"number"},"total_packages":{"type":"integer"},"load_percentage":{"type":"number"},"tw_stats":{"type":"object","additionalProperties":true}},"type":"object","required":["id","milestone","deliveries"],"title":"RouteResponse"},"ScheduleConfig":{"properties":{"start_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start At","description":"ISO 8601 date-time routes start, read in UTC."},"respect_delivery_windows":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Respect Delivery Windows","description":"When `true`, stops with `schedules` are only placed where the arrival falls inside a window."},"time_windows":{"anyOf":[{"$ref":"#/components/schemas/TimeWindowsConfig"},{"type":"null"}],"description":"Tolerances around each window."}},"type":"object","title":"ScheduleConfig"},"SpecialHandling":{"type":"string","enum":["FRAGILE","PERISHABLE","HAZARDOUS","REFRIGERATED"],"title":"SpecialHandling"},"Success":{"properties":{"idx":{"type":"integer","title":"Idx"},"id":{"type":"string","title":"Id"}},"type":"object","required":["idx","id"],"title":"Success"},"TimeUnit":{"type":"string","enum":["SECOND","MINUTE","HOUR"],"title":"TimeUnit"},"TimeWindowsConfig":{"properties":{"early_tolerance_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Early Tolerance Min","description":"Minutes a vehicle may arrive before a window opens."},"late_tolerance_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Late Tolerance Min","description":"Minutes a vehicle may arrive after a window closes."}},"type":"object","title":"TimeWindowsConfig"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VehicleBehaviorConfig":{"properties":{"priority":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priority","description":"Dispatch priority. Higher values are used first when types are interchangeable."},"overflow_vehicle":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Overflow Vehicle","description":"Hold this type back until the primary types are full."}},"type":"object","title":"VehicleBehaviorConfig"},"VehicleCapacityConfig":{"properties":{"volume_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume Max"},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight Max"},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]}},"type":"object","title":"VehicleCapacityConfig"},"VehicleCategoryType":{"type":"string","enum":["TRUCK","VAN","PICKUP","MOTORCYCLE","BICYCLE"],"title":"VehicleCategoryType"},"VehicleConsumptionUnit":{"type":"string","enum":["LITERS_PER_100KM","KILOMETERS_PER_LITER","MILES_PER_GALLON","GALLONS_PER_MILE"],"title":"VehicleConsumptionUnit"},"VehicleCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Display name."},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Cargo volume capacity, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Maximum payload, in `weight_unit`. Integer."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"consumption":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Consumption","description":"Fuel or energy consumption, in `consumption_unit`. Integer."},"consumption_unit":{"anyOf":[{"$ref":"#/components/schemas/VehicleConsumptionUnit"},{"type":"null"}]},"category_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleCategoryType"},{"type":"null"}],"description":"Vehicle class."},"engine_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleEngineType"},{"type":"null"}],"description":"Propulsion type."}},"type":"object","required":["name"],"title":"VehicleCreate"},"VehicleEngineType":{"type":"string","enum":["GASOLINE","DIESEL","CNG","ELECTRIC","HYBRID","MECHANIC"],"title":"VehicleEngineType"},"VehicleLimits":{"properties":{"volume_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume Min"},"volume_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume Max"},"capacity_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Capacity Min"},"capacity_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Capacity Max"}},"type":"object","title":"VehicleLimits"},"VehicleOverride":{"properties":{"capacity":{"anyOf":[{"$ref":"#/components/schemas/VehicleCapacityConfig"},{"type":"null"}]},"route":{"anyOf":[{"$ref":"#/components/schemas/VehicleRouteConfig"},{"type":"null"}]},"behavior":{"anyOf":[{"$ref":"#/components/schemas/VehicleBehaviorConfig"},{"type":"null"}]},"vehicle_id":{"type":"string","title":"Vehicle Id","description":"Vehicle this override applies to."}},"type":"object","required":["vehicle_id"],"title":"VehicleOverride"},"VehicleResponse":{"properties":{"name":{"type":"string","title":"Name","description":"Display name."},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Cargo volume capacity, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Maximum payload, in `weight_unit`. Integer."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"consumption":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Consumption","description":"Fuel or energy consumption, in `consumption_unit`. Integer."},"consumption_unit":{"anyOf":[{"$ref":"#/components/schemas/VehicleConsumptionUnit"},{"type":"null"}]},"category_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleCategoryType"},{"type":"null"}],"description":"Vehicle class."},"engine_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleEngineType"},{"type":"null"}],"description":"Propulsion type."},"id":{"anyOf":[{"type":"string"},{"type":"integer"}],"title":"Id"}},"type":"object","required":["name","id"],"title":"VehicleResponse"},"VehicleRouteConfig":{"properties":{"stops_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stops Min"},"stops_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stops Max"},"distance_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Min"},"distance_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Max"},"distance_unit":{"anyOf":[{"$ref":"#/components/schemas/LengthUnit"},{"type":"null"}]},"time_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Time Min"},"time_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Time Max"},"time_unit":{"anyOf":[{"$ref":"#/components/schemas/TimeUnit"},{"type":"null"}]}},"type":"object","title":"VehicleRouteConfig"},"VehicleRunConfig":{"properties":{"capacity":{"anyOf":[{"$ref":"#/components/schemas/VehicleCapacityConfig"},{"type":"null"}]},"route":{"anyOf":[{"$ref":"#/components/schemas/VehicleRouteConfig"},{"type":"null"}]},"behavior":{"anyOf":[{"$ref":"#/components/schemas/VehicleBehaviorConfig"},{"type":"null"}]}},"type":"object","title":"VehicleRunConfig"},"VehicleUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Display name."},"volume":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Volume","description":"Cargo volume capacity, in `volume_unit`. Integer."},"volume_unit":{"anyOf":[{"$ref":"#/components/schemas/VolumeUnit"},{"type":"null"}]},"weight":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weight","description":"Maximum payload, in `weight_unit`. Integer."},"weight_unit":{"anyOf":[{"$ref":"#/components/schemas/WeightUnit"},{"type":"null"}]},"consumption":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Consumption","description":"Fuel or energy consumption, in `consumption_unit`. Integer."},"consumption_unit":{"anyOf":[{"$ref":"#/components/schemas/VehicleConsumptionUnit"},{"type":"null"}]},"category_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleCategoryType"},{"type":"null"}],"description":"Vehicle class."},"engine_type":{"anyOf":[{"$ref":"#/components/schemas/VehicleEngineType"},{"type":"null"}],"description":"Propulsion type."}},"type":"object","title":"VehicleUpdate"},"VehiclesConfig":{"properties":{"defaults":{"anyOf":[{"$ref":"#/components/schemas/VehicleRunConfig"},{"type":"null"}],"description":"Settings applied to every vehicle in the run."},"overrides":{"anyOf":[{"items":{"$ref":"#/components/schemas/VehicleOverride"},"type":"array"},{"type":"null"}],"title":"Overrides","description":"Per-vehicle settings that win over `defaults`."}},"type":"object","title":"VehiclesConfig"},"VolumeUnit":{"type":"string","enum":["CUBIC_CENTIMETER","CUBIC_METER","LITER","CUBIC_INCH","CUBIC_FEET","GALLON"],"title":"VolumeUnit"},"WeightUnit":{"type":"string","enum":["GRAMS","KILOGRAMS","OUNCES","POUNDS"],"title":"WeightUnit"},"session_progress_response":{"type":"object","title":"SessionProgressResponse","description":"Live progress of an optimizer run. Available from `GET /lots/{id}/plan/status` while the lot is `PROCESSING`. When `status` is `completed`, read the routes with `GET /lots/{id}/plan`.","required":["session_id","status","phase","phase_label","progress_pct","elapsed_seconds","message","steps"],"properties":{"session_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["processing","completed","failed","not_found"]},"phase":{"type":"string","enum":["queued","clustering","consolidating_clustering","downloading_graphs","routing","consolidating","completed","failed","not_found"]},"phase_label":{"type":"string"},"progress_pct":{"type":"integer","minimum":0,"maximum":100},"elapsed_seconds":{"type":"integer","minimum":0},"message":{"type":"string"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"state":{"type":"string","enum":["pending","active","done"]}}}},"details":{"$ref":"#/components/schemas/session_progress_details"}}},"session_progress_graphs_details":{"type":"object","description":"Map/graph download progress. Phase stays downloading_graphs while active_downloads > 0, waiting_for_download > 0, or graphs_loaded < unique_graphs_started. progress_pct caps at ~55% until downloads finish.","properties":{"active_downloads":{"type":"integer","minimum":0,"description":"Downloads currently in progress"},"waiting_for_download":{"type":"integer","minimum":0,"description":"Workers waiting for a graph (PASO 5: ESPERANDO)"},"download_attempts":{"type":"integer","minimum":0,"description":"Total download attempts including retries"},"unique_graphs_started":{"type":"integer","minimum":0,"description":"Unique bboxes that started downloading"},"unique_graphs_estimated":{"type":"integer","minimum":0,"description":"Estimated unique graphs for this run"},"graphs_loaded":{"type":"integer","minimum":0,"description":"Graphs successfully loaded"},"completed_downloads":{"type":"integer","minimum":0,"description":"Completed download operations"},"cached_loads":{"type":"integer","minimum":0,"description":"Graphs loaded from cache (Redis/disk)"},"current_download_elapsed_sec":{"type":"integer","minimum":0,"description":"Elapsed seconds for the current file download"},"current_download_timeout_sec":{"type":"integer","minimum":0,"description":"Timeout seconds for the current file download"},"current_bbox_key":{"type":"string","description":"Bbox key of the graph currently downloading"}}},"session_progress_routing_details":{"type":"object","properties":{"completed_routes":{"type":"integer","minimum":0},"total_routes":{"type":"integer","minimum":0}}},"session_progress_clustering_details":{"type":"object","properties":{"completed_chunks":{"type":"integer","minimum":0},"total_chunks":{"type":"integer","minimum":0}}},"session_progress_details":{"type":"object","properties":{"clustering":{"$ref":"#/components/schemas/session_progress_clustering_details"},"routing":{"$ref":"#/components/schemas/session_progress_routing_details"},"graphs":{"$ref":"#/components/schemas/session_progress_graphs_details"},"queue":{"type":"object","additionalProperties":true}}},"PlanLimitExceededError":{"type":"object","required":["error","reason","detail"],"properties":{"error":{"type":"string","const":"plan_limit_exceeded","description":"Gateway rejected the request because a plan quota or entitlement was exceeded."},"reason":{"type":"string","enum":["max_milestones","max_vehicles","max_fleets","max_drivers","max_fleet_units","max_stops_per_request","monthly_limit","max_stops_per_route","plan_feature_not_allowed"],"description":"Machine-readable limit or entitlement that blocked the request."},"detail":{"type":"string","description":"Human-readable explanation and upgrade guidance."},"feature":{"type":"string","description":"Present when `reason` is `plan_feature_not_allowed`: the optimization option your plan does not include, for example `rebalance_by_volume`."}},"title":"PlanLimitExceededError"},"GatewayError":{"type":"object","title":"GatewayError","description":"Error returned by the Vepathos gateway before a request reaches the planning engine.","required":["error"],"properties":{"error":{"type":"string","description":"Machine-readable code, such as `unauthorized` or `routehub_unreachable`."},"detail":{"type":"string","description":"Human-readable explanation."}}},"Generic":{"type":"object","title":"Generic","description":"Status envelope used by the planning engine for acknowledgements and errors.","required":["code"],"properties":{"code":{"type":"integer","description":"HTTP status code."},"message":{"type":"string","description":"Human-readable message."}}},"ClusteringConfig":{"type":"object","title":"ClusteringConfig","description":"Clustering options a run may set. Other clustering settings are managed by Vepathos.","properties":{"force_vehicles_fleet_match":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Force Vehicles Fleet Match","description":"`true` sizes routes so the plan uses the whole fleet as declared. `false` lets the planner build longer routes and leave vehicles unused when fewer are enough. When omitted, route sizes are derived from the fleet size."}}},"RoutingConfig":{"type":"object","title":"RoutingConfig","description":"Routing options a run may override. Other routing settings are managed by Vepathos and ignored if sent.","properties":{"service_time_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Service Time Min","description":"Minutes spent at each stop. Used for arrival times and route durations."},"avg_speed_kph":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Speed Kph","description":"Average travel speed in km/h used to estimate travel time."}}}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"Authorization","description":"Access token from `POST /api/token`, sent as `Authorization: Bearer <access_token>`. Create the credential in Dashboard, Credentials."},"bearerJWT":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Short-lived JWT, from `POST /api/token` or the signed-in web session, sent as `Authorization: Bearer <token>`."}},"responses":{"PlanLimitExceeded":{"description":"A plan quota or optimization option blocks the request. `reason` names the limit. Nothing is reserved or charged.","headers":{"X-RouteHub-Tenant-Id":{"description":"Workspace id of the authenticated account. Informational.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanLimitExceededError"},"examples":{"maxVehicles":{"summary":"Vehicle type catalog cap","value":{"error":"plan_limit_exceeded","reason":"max_vehicles","detail":"Your plan allows up to 15 vehicles. Remove one or upgrade to add more."}},"maxFleetUnits":{"summary":"Units per fleet cap","value":{"error":"plan_limit_exceeded","reason":"max_fleet_units","detail":"Your plan allows up to 100 vehicles per fleet (sum of qty). This fleet requests 125. Reduce quantities or upgrade to a higher plan."}},"stopsPerRequest":{"summary":"Stops per request","value":{"error":"plan_limit_exceeded","reason":"max_stops_per_request","detail":"This request exceeds your plan's per-request limit of 500 stops."}},"monthlyStops":{"summary":"Monthly stop allowance","value":{"error":"plan_limit_exceeded","reason":"monthly_limit","detail":"This run would exceed your monthly limit of 2,000 stops."}},"featureNotAllowed":{"summary":"Optimization option not in plan","value":{"error":"plan_limit_exceeded","reason":"plan_feature_not_allowed","feature":"rebalance_by_volume","detail":"Volume adjustments across routes is not included in your current plan. Upgrade to unlock this option."}}}}}},"Unauthorized":{"description":"Missing, expired or invalid access token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"},"example":{"error":"unauthorized","detail":"Missing or invalid Bearer token."}}}},"NotFound":{"description":"The resource does not exist in your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"},"example":{"code":404,"message":"Delivery lot not found"}}}}}},"tags":[{"name":"vehicles","description":"Vehicle types with the volume, weight and consumption the planner works with."},{"name":"fleets","description":"How many units of each vehicle type a run can use. The sum of `vehicles[].qty` counts against your plan's units per fleet."},{"name":"drivers","description":"Driver records with schedules, start and end points and work areas."},{"name":"milestones","description":"Depots, warehouses and the other fixed places routes start from."},{"name":"deliveries","description":"Stops with a destination, package details and optional time windows."},{"name":"lots","description":"Delivery lots, optimization runs and the routes they produce."},{"name":"templates","description":"Package and stop presets for the web planner. Accepts the web session, not API access tokens."}]}