resources (vehicle-driver pairs), orders (each grouping one or more stops), and optional constraints and objectives. The SDKs don’t add a modeling layer of their own: their models are generated from the API’s OpenAPI specification, field for field. This page covers how to build a plan in code; what each field means is documented once, in the API Reference and the Data model.
Typed models and the API spec
- Python
- TypeScript
Models are
pydantic classes, under kardinal.routing.models (Resource, SingleStop, Position, TimeWindow, and every other schema of the spec). PlanCreate and Order come from kardinal.routing.plans. A model refuses a misspelled key and a value of the wrong type as soon as you build it.workingTimeWindow, operationDuration): what you write is what the API receives. Only method and argument names follow each language’s convention, such as plans.get_status in Python and plans.getStatus in TypeScript.
PlanCreate and Plan
Two shapes describe a plan, as in the API:
PlanCreateis what you submit. It has noid: the server assigns one. Settingidyourself is refused before sending.Planis whatsubmit,get, andupdatereturn: the same content plus the fields the server manages (id,version,status,state,agencyId). To change a plan, modify thePlanyou read and pass it toupdate.
Order.stops, and Plan.orders is the list of orders. An order groups the stops that must be served by the same resource, such as a pickup and its delivery.
Starting from the example plan
The fastest way to a valid plan is to adapt the example both SDKs ship: two resources, eight single-stop orders, and a 10-second optimization. Each call returns a fresh plan you can modify freely.Loading an existing JSON payload
If you already have a plan as JSON — exported from your own system, written by hand, or copied from a modeling example — load it into the SDK’s model rather than rebuilding it:submit: a missing required field, a wrong type, or a misspelled key fails here, with its path in the plan, before anything is sent.
Validating locally before you spend credits
Every check below runs on your machine, with no API call and no credits:- Structure and types: building a Python model, or
parsePlanCreatein TypeScript, fails on a missing required field or a value of the wrong type. - Unknown keys:
submitrefuses a key no model declares, and lists each one with its path and the closest real field name. To run that check yourself before sending, callunknown_fields(plan)(Python, fromkardinal.routing) orunknownFields(plan)(TypeScript). - A plan file:
kardinal routing plans validate plan.jsonruns both checks on a JSON file, from a shell or a CI job — see Local validation.
- Python
- TypeScript
Every object of the plan is checked, including the rarer nested ones (
cost, breaks, objectives, constraints). pydantic accepts a string holding a number or a boolean, such as "1" or "true", and converts it.Where field documentation lives
The API Reference is the reference for every field: its meaning, unit, default, and constraints. The SDKs carry the same descriptions, generated from the same specification, so your editor shows them on hover. If the two ever disagree, the API Reference is right: report it as an issue on the SDK’s repository.Using the SDKs with AI coding agents
An agent writing integration code gets the most out of the typed models: wrong field names and types fail fast, with the exact path, instead of producing a valid but wrong plan.- Run
kardinal initin your project: it writes.kardinal/SKILL.md, a short pointer that tells a coding assistant the SDK is there and how to call it. - Point the agent at the AI agent modeling checklist before it models your operation.
- Have it validate every payload locally, with the checks on this page, before submitting anything with a production key.

