resources such as vehicles, orders, and constraints), and you retrieve the solution the engine computes for it. This tutorial walks through both, using the smallest possible plan.
Access to the API is self-service — see Authentication and API keys for how to sign up and what account structure it creates.
Step 1 — Authenticate
Kardinal uses JWT authentication. Every request needs a long-term API token, which you generate once from the Console and reuse as a bearer token for as long as it’s valid. Log in to the Console, then go to API Keys in the sidebar to generate your token. Keep it — every following request in this tutorial uses it as a bearer token. It’s valid for 366 days; see Authentication and API keys for the full authentication model.Step 2 — Submit a minimal plan
A plan is created withPOST /plans — the service generates the plan’s id, returned in the response; an id sent in this request is ignored and replaced by a generated one. Here is the smallest viable plan: one resource and three pickup-only orders in Paris.
Response (abridged)
id from the response — every request below uses it in place of {planId}.
maxOptimizationDuration and other duration fields use ISO 8601 duration syntax: PT1M reads as “period, time, 1 minute.”Step 3 — Retrieve the solution
item field and gives you, per resource, the ordered list of stops (tours[].wayPoints) with arrival/departure times, plus any stop that couldn’t be planned:
Response (abridged)
fly profile’s 20 km/h, the 10.5 km tour takes about 31 minutes of travel, plus 5 minutes 30 seconds at each of the three stops.
unaffectedStopIds lists stops that couldn’t be planned within hard constraints, and unusedResourceIds lists resources left with nothing assigned — both empty here since this minimal plan has no constraints to violate. See Why a stop, not always the problem, becomes infeasible for the full picture.
For a small test plan like this one, the solution is typically ready within seconds — for larger plans, poll GET /plans/{planId}/state until it returns state: "optimized" — the plan goes through states such as waiting, processing, and optimizing first (see Polling the state and the solution for the polling interval, the other end states, and why an early solution can be empty).
Next steps
PUT /plans/{planId}with the complete plan (the same resources and orders, plus your change) to see interactive re-optimization in action — read How the optimization engine works first to understand what happens on update.- Add time windows, capacities, and skills to your orders and resources — see the full data model reference.
- Move from crow-fly (
fly) to a real vehicle profile (car,truck) before going further than a smoke test — with a production token, since the sandbox always computes crow-fly. - Size
maxOptimizationDurationfor your real volumes:PT1Monly suits this three-stop test. See SizingmaxOptimizationDurationfor a large problem.

