Skip to main content
V3 is in beta. General availability (GA) is planned for January 2027.

Overview

POST /v3/routing/solve holds the connection open until the plan is ready and caps the search at 300 seconds. An async run takes the same request body, answers at once, and solves in the background, with a search of up to 3,600 seconds. You then poll the run and fetch the plan when it is done. Only solve runs in the background. Evaluate and suggest are quick, and stay synchronous. All four are served from https://api.solvice.io and take your API key in the Authorization header, as on the other endpoints. A run belongs to your account: another account’s run id is a 404.

The life of a run

succeeded, failed and cancelled are final.

Submit a run

Send the body you would send to /v3/routing/solve: a problem, and optionally a plan and options. These differ from solve:
  • options.time_limit_s may be up to 3600 (solve: 300).
  • callback is not supported yet. A body that has it is a 400 with the item code not_supported at /callback.
  • The request is validated before the run is accepted, with the same checks and the same error body as solve, so a bad body is a 400 here and never a failed run later.
The answer is 202 with the run. Keep its id:
202 Accepted
Send an X-Request-Id header of 1 to 128 visible ASCII characters to trace the call. It is echoed in the x-request-id response header, and a generated req_… id is used when it is absent or malformed.

The run

Every endpoint but /result answers with the run:
string (UUID)
The run id, for the paths above.
string
queued, running, succeeded, failed or cancelled. See The life of a run.
self and result: the paths to poll and to fetch the plan from, relative to the API host.
object
On failed only: status, code, message and, for an invalid request, errors[], in the shape of the error body. The code is invalid_request, matrix_provider_error, internal or worker_lost.
string (RFC 3339, UTC)
When a worker claimed the run. Absent while it is queued.
string (RFC 3339, UTC)
When the run became final. Absent before then.
string (RFC 3339, UTC)
When the run and its plan are deleted: finished_at plus 365 days. Absent before the run is final.

Poll a run

Poll every few seconds until status is final. While the worker runs:
200 OK, running
And when it is done:
200 OK, succeeded
A run that stops without saying so does not stay running for ever. Each poll checks the worker, and the run turns failed with error.code worker_lost when the worker is gone or the run is older than 6,000 seconds. A run that is still queued after 30 minutes turns failed with internal.

Fetch the plan

For a succeeded run the answer is 200 with exactly the response POST /v3/routing/solve returns: summary, routes, plan and unassigned. See The V3 API model for every field, and send plan back in a later request to re-optimise. The plan is kept until expires_at. For any other status /result answers 409:

Cancel a run

The answer is 200 with the run: cancelled, or unchanged when it had already finished, since finishing wins a race. A run is cancelled whether it is queued or running.
200 OK, cancelled
Cancelling does not stop the worker. A cancelled run keeps counting toward the limit of 10 runs until its worker stops, and its plan is never served: /result is a 409 with no_result.

Limits

The other request limits apply as on solve. Over the rate limit the answer is a 429 as on every endpoint.

Errors

A bad request body is answered with the error body of solve, with the same 400, 403, 413 and 415 cases. The gateway answers the rest in its own shape, so branch on the HTTP status first: Each of these has a message that begins with a code, then a colon and a sentence. Never parse the sentence.

Next steps

The V3 API model

The request, and the plan a run returns

Errors

The error body and every code