V3 is in beta. General availability (GA) is planned for January 2027.
All three are served from
https://api.solvice.io and take a JSON body with your API key in the Authorization header.
Add ?validate_only=true to any of them to check a request without solving it: it runs every check the real call runs before its travel-matrix fetch, then returns 200 {"valid": true, "warnings": []} or the same 400 the real call would return. No matrix fetch, no search, not billed. Request bodies may be gzip-compressed (Content-Encoding: gzip); the 10 MiB limit applies after decompression. See Limits for the other caps.
A solve that should run longer than 300 seconds, or without holding a connection, can be submitted as an async run instead: POST /v3/routing/runs takes the same body.
This guide covers /v3/routing/solve, the one you’ll use first.
Your first solve
1
Get your API key
Sign up at platform.solvice.io and copy your API key from Settings → API Keys. See Authentication for the full flow.
2
Send a solve request
3
Read the response
The response carries a How to read it:
summary, one entry per non-empty routes[], the same routes as a plan, and any unassigned jobs with structured reasons. Stop times are instants in the shift’s own UTC offset (+02:00 here); distances and durations come from the road network. The figures below are illustrative: a live solve returns the road-network values for your coordinates.- Identity.
routes[].vehicleandroutes[].shiftare the plainidstrings from the request. - Stops. Each stop’s
locationis the coordinate you sent;snapped_locationis the same point snapped to the road network, when available.arrivalis before any waiting: the 1,945 s ofwait_satdelivery-1is the truck arriving before that job’s window opens.service_startis when service begins, after the wait:09:00atdelivery-1, the moment its window opens, and the same asarrivalatdelivery-2. - Load.
deliveryon a job is goods loaded at the depot and dropped off at the job, soload_afterstarts at 30 on thestartstop and falls to 0. Usepickupon a job for goods that go onto the vehicle there, which makesload_afterrise instead. See Jobs. - Durations.
time.travel_sis driving time only.time.span_sis the route’s span from its start to its finish, including service and waiting. - Cost. This request set no
objective, so the default rates apply: 0.20 per km ofdistance_mand 35 per hour oftime.span_s. That gives thedistanceandtimecomponents above: 187.321 km × 0.20 = 37.4642, and 12,500 s × 0.00972 = 121.5. They sum toscore.cost. The hourly rate is applied per second at a resolution of 5 decimals, so 35 per hour is charged as 0.00972 per second. Expect thetimecomponent to come out a few cents under hours × 35. - Score. Every entry of
score.componentsis always present.score.currencyis absent here because noobjective.currencylabel was sent. - Coverage.
tasks.unservedis0because nothing is unassigned. If some jobs cannot be placed the call still returns 200, withtasks.unservedabove0and oneunassigned[]entry per job explaining why. - Plan.
plancarries the same routes in the request’splanvocabulary. Feed it straight intoevaluate,suggest, or a warm-startedsolve.
Got a
400 instead? The body names the offending field in errors[].pointer. See Errors.What’s different from V2
Next steps
The V3 API model
How the full request and response are structured: jobs, shipments, vehicles, relations, objective.
Field service day
A worked example: one day of service jobs solved, then a manual change scored with
evaluate and a new job placed with suggest.Constraints
Every field-level constraint the solver enforces, hard vs. soft.
Evaluate
Score an existing plan and list the rules it breaks.
Suggest
Rank where a new job fits into an existing plan.
Errors
The error body, every error code, and what to retry.
Limits
Request size, count, and time-limit caps.
Migration from V2
Map V2 concepts and fields onto V3.
API reference
Base URL, authentication, and the full schema of every endpoint.