Documentation menu
routing
POST/v1/errands/plan
API key required, sent as Authorization: Bearer snk_… or ?api_key=snk_….
What it does
Returns 200 whether or not the chain fits: an infeasible chain is an
answer, with the errand that costs the most named and the largest set
that does fit planned out in full. The precedent is POST /v1/ev/plan,
which answers feasible: false with a named cause rather than
inventing a journey, and the reasoning is identical. A driver who
cannot do all three things needs to be told which two they can.
Call it
bash
curl -fsS -X POST "https://api.mapmap.ai/v1/errands/plan" \
-H "Authorization: Bearer $MAPMAP_KEY" \
-H "Content-Type: application/json" \
-d @request.jsonRequest body
application/json · ErrandPlanRequest
| Field | Type | Required | Description |
|---|---|---|---|
| arrive_by | string | yes | The hard arrival time, RFC 3339 with an offset. |
| costing_options | not stated | no | Valhalla costing options, passed to every engine call. The costing
itself is always auto. |
| depart_at | string | no | When they set off, RFC 3339. Defaults to now, in the offset
arrive_by carries. |
| destination | Destination | yes | Where they have to be, and what to call it. |
| errands | ErrandInput[] | yes | The errands, in any order: the answer decides the order. |
| max_detour_minutes | number | no | How far off the direct route a candidate may sit, as a detour in
minutes. Default [DEFAULT_MAX_DETOUR_MINUTES]. |
| origin | Point | yes | Where the driver sets off from. |
Responses
200The plan, feasible or honestly not:
{feasible, departure, arrive_by, arrival, slack_s, plan: {stops[]: {errand, kind, category, place: {name, label, lat, lon, id}, arrive, depart, dwell_s, drive_s, distance_m, hours: {verdict, tag, source, message}}, final_leg, total_drive_s, total_dwell_s, total_duration_s, total_distance_m}, errands[], search, opening_hours, geometry_polyline6, usage, verification, attribution}. geometry_note replaces geometry_polyline6 when the follow-up route through the stops failed: the plan stands, only the drawn line is missing. hours_note appears when the window crosses the hour a clock change can fall on and a stop was reached after it: those stops read unknown whatever their tag says. When feasible is false the answer carries reason {code, message, over_by_s, blocking: {errand, adds_s}} and, where anything at all fits, achievable: the largest set of errands that does fit, planned in full, with dropped naming what had to go400Invalid request, including an instant more than 366 days from now and an
arrive_by more than 18 hours after departure401Missing or invalid API key
422The chain is too large or too spread out for the engine's matrix limits
429Quota or rate limit exceeded
501A
category errand on a deployment with no first-party place index (SN_GEOCODE_DIR unset)502Upstream routing engine failed
Error bodies follow the shared problem model documented on API conventions.
Also under routing
POST /centroidPOST /isochronePOST /locatePOST /matrixPOST /optimisePOST /optimise/replanPOST /routePOST /route/alongPOST /route/progressPOST /route/reportGET /route/v1/{profile}/{coordinates}POST /trace_attributesPOST /trace_routePOST /v1/cameras/alongPOST /v1/charging/alongPOST /v1/clusterPOST /v1/ev/planPOST /v1/fuel/alongPOST /v1/incidents/alongPOST /v1/jobs/matrixPOST /v1/jobs/optimisePOST /v1/jobs/replanPOST /v1/route/heritagePOST /v1/route/observationsPOST /v1/weather/alongGET /v1/zones
Generated from https://api.mapmap.ai/openapi.json on 2026-09-22 · operationId post_errand_plan