Skip to main content
Reference for kardinal-ai 1.0.0. Install it with pip install kardinal-ai, import it as kardinal. Every method below is synchronous. Field-level documentation for plans and solutions lives in the API Reference.

Client

Kardinal

The methods hang off k.routing.plans and k.routing.solutions. The client holds an httpx connection pool: use it as a context manager (with Kardinal() as k:) or call k.close(). See Client configuration.

Plans

plans.submit

POST /plans. Creates the plan and starts its optimization. Returns the stored Plan, with the id the server assigned and .warnings. Raises UnknownFieldError, before sending, for a key no model declares, unless named in allow_unknown. Consumes credits with a production key. Never retried.

plans.get

GET /plans/{planId}. Returns the plan as currently stored. Raises KardinalNotFoundError if it doesn’t exist.

plans.update

PUT /plans/{planId}. Replaces the whole plan: anything left out is removed. The version increments, and the plan is re-optimized, only if the content changed; an identical update is a free no-op. Fields unknown to this SDK version that get read are sent back untouched; a key you added that no model declares raises UnknownFieldError, unless named in allow_unknown. On a plan not read from the API, a likely typo only emits an UnknownFieldWarning. force=True unarchives an archived plan first. Retried.

plans.delete

DELETE /plans/{planId}. Permanently deletes the plan and its solution, and stops any optimization in progress. Retried.

plans.list

GET /plans. Returns one page of plans, in their light form. A page past the last one returns the last page.

plans.iter_all

GET /plans, every page. Iterates over every plan, fetching pages as it goes.

plans.start

PUT /plans/{planId}/running. Restarts the optimization of the current version, without changing its content or version. Returns agencyId, planId, planVersion, and warnings. Retried.

plans.stop

PUT /plans/{planId}/running. Stops the optimization in progress, without changing the plan’s content or version. Retried.

plans.get_status

GET /plans/{planId}/state. Returns the plan’s current state, a single value: waiting, processing, optimizing, optimized, stopped, interrupted, and so on. A state this SDK version doesn’t know comes back as its raw string. Not the detailed PlanStatus object found in Plan.status.

Solutions

solutions.wait

GET /plans/{planId}/state, then /solution. Blocks until the optimization of the current version is over, then returns its solution. Reads the state every 10 seconds at first, up to every 60 seconds. solution.final_state tells how it ended: optimized, interrupted, or stopped. Raises KardinalOptimizationError (NO_SOLUTION, PLAN_SUPERSEDED, OPTIMIZATION_STALLED), KardinalNotFoundError if the plan is deleted meanwhile, and KardinalTimeoutError once timeout seconds have elapsed. See Waiting for the solution.

solutions.get

GET /plans/{planId}/solution. Returns the current best solution right away, without waiting. Raises KardinalNotFoundError until the engine has a first solution.

solutions.get_objectives

GET /plans/{planId}/solution/objectives. Returns the value of each objective, without the tours: a plain list of SolutionObjective, with a .warnings attribute.

Examples

examples.small_delivery_plan

A ready-to-submit plan: two resources, eight single-stop orders around central Paris, and a 10-second optimization. The working window starts tomorrow at 8:00. Each call returns a new object.

Local checks

unknown_fields

Runs the check submit makes, without sending anything: every key no model declares, with its path and, when one is close, the real field name it was likely meant to be. Empty when the plan is clean.

Types

PlanCreate

From kardinal.routing.plans. The plan you submit: no id, the server assigns it. Built from kardinal.routing.models objects, or loaded from JSON with PlanCreate.model_validate_json(text). Its orders are kardinal.routing.plans.Order objects.

Plan

From kardinal.routing.plans. The plan as stored, returned by submit, get, and update: the same content plus id, version, status, state, and agencyId, and .warnings from the call that returned it.

Page

From kardinal. Returned by plans.list: items, page, total_pages, total, next_page (None on the last page), previous_page (None on the first page), and items_per_page.

Model types

kardinal.routing.models holds a pydantic model for every schema of the API specification (Resource, SingleStop, AlternativesStop, Position, TimeWindow, Solution, Tour, Warning, and so on), with the API’s field names and descriptions.

Exceptions

All importable from kardinal, all subclasses of KardinalError. See Errors, retries, and warnings. UnknownFieldWarning, also importable from kardinal, is a warning, not an exception: see Client-side errors. Every exception carries .code, .status, .errors, .details, .retryable, .warnings, and .request_id.

Known limitations

  • The client is synchronous; there’s no asyncio client.
  • pydantic converts a string holding a number or a boolean ("1", "true") instead of refusing it.
  • .request_id is usually None: the API sends an X-Request-Id header only on some responses.
  • The kardinal command needs the cli extra: pip install "kardinal-ai[cli]".