Types of triggering disruptions
Every one of these is the same operation: mutate the relevant part of your local copy of the plan, then
PUT the whole plan back — there is no endpoint that targets a single resource or order in isolation anymore.
How this differs from a full recalculation
Submitting any of the preceding updates keeps the plan’sid unchanged, so it isn’t treated as a new problem: the engine repairs the previous solution, adjusting it only as much as needed to be valid for the new data, then keeps improving from there — it does not restart optimization from scratch. This is normally much faster than the plan’s original optimization, which had to learn the problem’s shape for the first time.
If an older version of the plan is still optimizing when a disruption update lands, the engine drops the stale version in favor of the newest one — you never get two versions “optimized” at once.
The engine starts from the previous solution even when the previous optimization has already finished, and for an update sent hours or days later. It starts from the best solution it found for the plan, which it keeps for a limited time. The same applies when you restart the current version with PUT /plans/{planId}/running. Starting from the previous solution doesn’t freeze it: to keep stops that are already started or announced in place, lock them with state.assignments (see Live supervision as a tour progresses).
An update starts from scratch instead when no previous solution is available: once that limited time has passed, or once the plan has been archived. A plan that hasn’t been updated for 14 days is archived automatically (see Data retention), and a PUT on an archived plan is refused unless you add force=true, which unarchives it first. That forced update always creates a new version and re-optimizes the plan, even if its content is identical, so every stop is billed again (see Pricing and credits). Don’t add force=true by default.
An update also starts from empty tours when the previous tours break a maxCumulatedCost cap in globalConstraints, for example after you lower its maximum (see Capping a fleet-wide cost).
In all these cases, whether the update starts from scratch or from empty tours, the result is still valid, but the update can take as long as a first optimization, and the tours can change a lot.
There is no way to start a plan from another plan’s solution: the stored solution belongs to the plan’s id, and the API has no field to supply one.
An update only consumes credits for stops that are new or have changed — a new id, or a move of more than about 11 metres — and for all stops once per 24-hour period since the plan’s creation. Changing resources or constraints costs nothing extra; see Pricing and credits.
Best practices for call frequency
- Batch disruptions that arrive close together into a single update where possible, rather than issuing one
PUTper individual change — every update re-triggers optimization, and consecutive updates just cause the engine to keep abandoning a version it hasn’t finished with yet. - Poll before you push another update. Check the plan’s
status, orGET /plans/{planId}/statefor a simpler single-fieldoptimizedcheck (see How the optimization engine works), to see whether the previous update has already settled; there’s little value in sending a new disruption update while the engine is still mid-search on the last one, beyond the disruption itself needing to be reflected immediately. - Don’t reduce
maxOptimizationDurationfor these updates just because they feel like small edits — the field caps this version’s remaining search time, and a busy fleet mid-shift can still take real time to re-settle around a disruption; size it the same way you would for the initial plan (see Handling large volumes).
See also
- How the optimization engine works — what happens when a plan is updated with the same
id, and the three integration patterns for retrieving a solution. - Re-optimizing with
update— the same update from the Python or TypeScript SDK. - Handling infeasibility — diagnosing a disruption that leaves a stop unplannable rather than just delayed.
- Manual assignment and supervision — locking stops in place so an update doesn’t move them.
- Data model — an overview of
ResourceandOrder, each linking to its schema in the API reference — the two objects most commonly touched by a disruption.

