resources (vehicles/drivers) and orders (what needs to be done) — plus plan-level fields that add constraints spanning several of them. See First API call for the request/response shapes and How the optimization engine works for what the engine does with these fields.
Resource (vehicle-driver pair)
One vehicle-driver pair for the duration of the plan — id, working hours, capacities, skills, breaks, and travel constraints. See theresources schema.
Vehicle profiles
Mode of transport and its travel constraints (fly, pedestrian, bicycle, scooter, motorbike, car, truck), nested under each resource’s vehicleProfile. The fly profile additionally takes a kmph field — a constant travel speed used to compute crow-fly travel times, since it has no road network to derive one from. On a truck profile, height, width, and length are in metres and grossWeight in kilograms. See the resources schema.
Order, stop
An order is one or more stops that must all be planned onto the same resource, in array order. See theorders schema.
A stop’s kind (pickup, delivery, or acknowledgement) sets which way its capacities move, from the resource’s point of view: a pickup loads its quantity at the stop, and a delivery unloads it there. A negative quantity reverses that direction: a delivery of -100 has the same effect as a pickup of 100.
Within one order, a pickup and a delivery carry the same goods: the resource loads them at the first stop and unloads them at the second. A delivery whose order has no pickup is assumed loaded at departure, which shows in the tour’s filledCapacitiesAtBegin. Pickups and deliveries from different orders are distinct goods, even when their quantities match.
Capacities
Free-form map tracking what a resource carries and what a stop consumes or releases, declared on both resources and stops. See theresources and orders schemas.
A solution reports filledCapacitiesAtBegin/filledCapacitiesAtEnd/filledCapacitiesAfterStop (capacities loaded at the start, end, and after each stop) and maxFilledCapacities (the peak reached during the tour) — see the Tour and WayPointStop schemas in the API reference. A capacity declared on a resource with a ceiling no tour can reach reads back as a read-only KPI (for example nbPackages) without affecting the optimization.
Shared capacity pools
Plan-levelsharedCapacities flag pooling a capacity key across all of a resource’s stops, regardless of order. See the sharedCapacities schema.
Time windows
TimeWindow (plain {begin, end}) and TaggedTimeWindow (the same shape plus optional resourceTags), used for working hours, breaks, and a stop’s authorized/preferred windows. See the resources and orders schemas.
Dates and time zones
Every datetime you send lives inside the plan object, and the API accepts three ways to write one.
A
Z or an offset always wins over tz. For example, with "tz": "Europe/Paris", the value 2026-10-20T10:00:00-05:00 is 17:00 in Paris.
Use one form for every datetime of a plan. The API accepts a plan that mixes local datetimes with Z or offset datetimes, and returns no error, but it reads each value in its own way, so a window can shrink without warning. For example, with "tz": "Asia/Tokyo", a workingTimeWindow from 2026-10-20T07:00:00+02:00 to 2026-10-20 17:00 runs from 14:00 to 17:00 in Tokyo: three hours instead of ten.
A local datetime needs the space between date and time. The T form with no Z and no offset (2026-10-20T10:00:00) is rejected with an INVALID_INPUT error, even when tz is set. This is the form that Python’s datetime.isoformat() writes for a datetime without a time zone, so add the correct UTC offset before you send it, or convert the value to UTC first and then add the Z. Adding a Z to a local time without converting it moves every hour.
A local datetime also needs tz. If the plan has no tz, the API does not read the value as UTC. It rejects the whole plan with an HTTP 400 INVALID_INPUT error, and the message does not mention tz. The tz value must be an IANA identifier such as Europe/Paris. A value such as Paris is rejected as well.
The offset depends on the date, so the same local time does not always mean the same instant. For Europe/Paris, 2026-10-20 10:00 is stored as 2026-10-20T10:00:00+02:00, and 2026-11-05 10:00 is stored as 2026-11-05T10:00:00+01:00. On the night the clocks go back, one local hour happens twice. For datetimes close to a clock change, send an explicit offset so there is no doubt.
When the plan has a tz, the API writes every datetime back at the offset of that zone, even if you sent it as Z or at another offset. The stored plan and the solution both use it. Without tz, the stored plan keeps each datetime in the form you sent (apart from the milliseconds), and the solution is written in Z. Read-only fields such as createdAt, updatedAt and the solution timestamp are always in Z. For this reason, set tz in every plan, even when all your datetimes carry an offset.
The API never scans properties sub-objects for local datetimes, so a local datetime written there is not converted. See the Plan schema for the tz field.
Breaks
A resource’sbreaks array, mixing timeWindowBreak, workingDurationSlidingBreak, and travelDurationSlidingBreak entries. See the resources schema.
Currently, the engine schedules a break only where the vehicle already stands, at the start of its tour or at a stop, never in the middle of a drive. A single drive longer than the allowed gap between two breaks makes that drive impossible for the vehicle. The engine leaves the stops that need it unplaced, returns no error, and no violation names the break. If every tour of the vehicle needs that drive, the vehicle is not used at all. See Where a break can fall.
Constraints catalog
additionalConstraints (scoped to specific tags) and globalConstraints (scoped to the whole fleet) beyond what resources/orders/stops express directly. See the additionalConstraints and globalConstraints schemas.
Plan-level fields
Fields that configure the plan as a whole:agencyId, tz, lateDeparture, maxOptimizationDuration, sharedCapacities, objectives, additionalConstraints, globalConstraints, accessDurationsByStopTag, overlappingCapacitiesByStopTag, setupDurations, additionalOperationDurations. See the Plan schema.
Status and state
Two read-only fields track a plan’s lifecycle:status (a detailed breakdown per stage — waiting room, creation, optimization, and traffic fetching) and state (a single summary value, optimized once no better solution can be found). See How the optimization engine works for the full polling pattern, and GET /plans/{planId}/state to retrieve state directly.
Positions and geocoding
Every position in a plan (each stop’sposition, and a resource’s departure/arrival) is a {lat, lon} pair in decimal degrees. The API does not geocode addresses: geocode them on your side before building the plan, with whichever geocoding provider your integration already uses. If you can’t geocode your addresses yourself, contact customer.success@kardinal.ai: the team can geocode an address set for you on request.
A wrongly geocoded position raises no error: it silently routes to the wrong place. Spot-check a sample of geocoded stops on a map before submitting. If an address can’t be geocoded precisely, treat it as a data-quality gap rather than falling back to an approximation such as a town or postal-code centroid, since stops sharing that point collapse onto it. See §5 of the AI agent checklist, and Geocoding and addresses for the questions to settle with the operations team.
Depot vs. position
Depots are not first-class objects in this API — there is noDepot schema. A resource’s departure/arrival positions (a raw {lat, lon}, or "atFirstPosition" for arrival) are how a depot is represented: resolve it to its position on the client side before building the plan. A “depot” tag such as "depot:main" (see Multi-trip tours) is an arbitrary stop tag your integration defines, not a reference to any API object. See the resources schema.
See also
- Hard vs soft constraints — which of the preceding bend under pressure and which don’t.
- Modeling advanced constraints — worked examples for capacities, skills, breaks, time windows, and optional steps that gate a mandatory stop.
- How the optimization engine works — objectives and the optimization loop that consumes this data.

