{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}
{
"code": "feature_not_enabled",
"message": "travel.engine: 'tomtom_real_time' is not enabled for this account; use engine 'tomtom'",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "FORBIDDEN"
}
The same body as POST /v3/routing/evaluate, plus optional options.
Given the committed plan over problem, ranks the feasible insertion
positions for every task of problem that is not in plan — the tasks a
solve would place and an evaluate would report as unassigned. Each task
(or unit — a shipment, or tasks tied by one sequence/same_vehicle/
same_day/same_route relation) is ranked independently against the same
committed plan; the plan is never modified.
{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}
{
"code": "feature_not_enabled",
"message": "travel.engine: 'tomtom_real_time' is not enabled for this account; use engine 'tomtom'",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "FORBIDDEN"
}
{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}
{"docsConfig":{"theme":"maple","$schema":"https://mintlify.com/docs.json","name":"Solvice Docs","description":"Solvice API documentation for cloud-native optimization solvers. Build powerful route optimization, workforce scheduling, and resource allocation solutions with our VRP, shift planning, and clustering APIs.","colors":{"primary":"#0f62fe","light":"#0f62fe","dark":"#0f62fe"},"logo":{"light":"https://mintcdn.com/solvice-68592f22/1KJ_2AIotizI1Bng/logo/light.svg?fit=max\u0026auto=format\u0026n=1KJ_2AIotizI1Bng\u0026q=85\u0026s=e93560fee320491613107060a1afc094","dark":"https://mintcdn.com/solvice-68592f22/1KJ_2AIotizI1Bng/logo/dark.svg?fit=max\u0026auto=format\u0026n=1KJ_2AIotizI1Bng\u0026q=85\u0026s=1baeb15bf7826f571444a1d6a36fb31a"},"favicon":"https://mintcdn.com/solvice-68592f22/noMIHjSWP2Tg_tTz/favicon.png?fit=max\u0026auto=format\u0026n=noMIHjSWP2Tg_tTz\u0026q=85\u0026s=beff99df9d507e0794596b5437be687f","api":{"mdx":{"auth":{"method":"key","name":"Authorization"}}},"navbar":{"links":[{"href":"mailto:support@solvice.io","label":"Support"},{"href":"https://www.solvice.io","label":"Solvice website"}],"primary":{"type":"button","label":"Dashboard","href":"https://platform.solvice.io"}},"footer":{"socials":{"website":"https://www.solvice.io","x":"https://x.com/solvice_io","github":"https://github.com/solvice","linkedin":"https://linkedin.com/company/solvice"}},"seo":{"metatags":{"og:image":"link to your default meta tag image","charset":"UTF-8","viewport":"width=device-width, initial-scale=1.0","description":"Solvice API documentation for cloud-native optimization solvers. Build powerful route optimization, workforce scheduling, and resource allocation solutions with our VRP, shift planning, and clustering APIs.","keywords":"Route Optimization, Route API, Optimization API, Workforce Scheduling, Solvice","author":"Christophe Van Huele","robots":"index, follow","googlebot":"index, follow","google":"notranslate","google-site-verification":"verification_token"},"indexing":"all"},"integrations":{"ga4":{"measurementId":"G-2L8R78J6J9"}},"banner":{"content":"Solvice VRP API v3 is in beta. General availability (GA) is planned for January 2027.","dismissible":false},"contextual":{"options":["claude","copy"],"display":"header"},"styling":{"latex":true},"navigation":{"global":{"anchors":[{"anchor":"Dashboard","icon":"book-open-cover","href":"https://platform.solvice.io"},{"anchor":"Website","icon":"planet-ringed","href":"https://www.solvice.io"},{"anchor":"Blog","icon":"newspaper","href":"https://www.solvice.io/blog/news"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"solvice-68592f22","hasAudioNarration":false,"actualSubdomain":"solvice-68592f22","customDomains":["docs.solvice.io"],"gitSource":{"type":"gitlab","owner":"solvice","repo":"solver2","projectId":44919668,"deployBranch":"main","contentDirectory":"mintlify","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ad205466244a69b2931f7fb","collectionId":"8ef7747f-3efd-4d3f-b092-798010502a52","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ad205466244a69b2931f7fb"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"DISABLED"},"REMOVE_BRANDING":{"status":"DISABLED"}},"buildId":"6ae30814d48146ed4e44ffe1","clientVersion":"0.0.4006","searchFilterCounts":[{"language":"default","tag":"Guides","count":81},{"language":"default","tag":"VRP API","count":49},{"language":"default","tag":"Features","count":32},{"language":"default","tag":"Routing API","count":28},{"language":"default","tag":"API Reference","count":26},{"language":"default","tag":"Fill API","count":20},{"language":"default","tag":"Platform","count":10},{"language":"default","tag":"Examples","count":9},{"language":"default","tag":"Concepts","count":9},{"language":"default","tag":"Info","count":6}]},"assistantConfig":{"deflection":{"enabled":true,"email":"support@solvice.io","showHelpButton":true}},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-reference/vrp/v3/validate-suggest","slug":"/api-reference/vrp/v3/validate-suggest","pageMetadata":{"title":"Validate suggest","openapi":"vrp-v3 POST /v3/routing/validate/suggest","description":"Check a suggest request without running it","href":"/api-reference/vrp/v3/validate-suggest"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Check a suggest request without running it\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={p:`p`,strong:`strong`,..._provideComponents(),...props.components},{Info}=_components;if(!Info)_missingMdxReference(`Info`,true);return _jsx(Info,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`V3 is in beta.`}),` General availability (GA) is planned for January 2027.`]})})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Validate suggest","openapi":"vrp-v3 POST /v3/routing/validate/suggest","description":"Check a suggest request without running it","href":"/api-reference/vrp/v3/validate-suggest"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Routing"],"summary":"Check a suggest request without running it","description":"Check a suggest request without running it","operationId":"validate_suggest","requestBody":"90a4623d-9ed3-418c-a6d7-64003ea69cad","responses":{"200":"19aab307-5994-4839-bffb-6106d915b694","400":"d7710125-24ed-4033-bfed-f6631a996cfd","401":"1a341c44-e67d-414d-a550-aa059286dc6d","403":"2b7215a4-b32b-432c-8e5e-f72d9b754303","413":"aa52ea89-715c-4bcd-8a3a-4fca06fad029","415":"928345e2-0309-4fdf-8241-511d7b7d0d27","429":"319b651a-3d91-4499-b8b1-85e399ed3ca9","500":"524bb7f4-078c-4bfe-8cad-2f9140f462a8"},"method":"post","type":"path","servers":["201228c4-350a-441d-b6ae-257ddac506eb"],"security":["9ccad23f-2998-47f5-b1b2-2885a0d8c12b"],"path":"/v3/routing/validate/suggest","baseUrlOptions":["https://api.solvice.io"],"title":"Check a suggest request without running it","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"content":{"application/json":{"schema":{"type":"object","description":"Request body for `POST /v3/routing/suggest`.\n\nThe same body as `POST /v3/routing/evaluate`, plus optional `options`.\nGiven the committed `plan` over `problem`, ranks the feasible insertion\npositions for every task of `problem` that is not in `plan` — the tasks a\nsolve would place and an evaluate would report as unassigned. Each task\n(or unit — a shipment, or tasks tied by one `sequence`/`same_vehicle`/\n`same_day`/`same_route` relation) is ranked independently against the same\ncommitted plan; the plan is never modified.","required":["problem","plan"],"properties":{"plan":{"type":"object","description":"The committed plan. Never modified, never reordered. On suggest,\n`locked_count` keeps insertions after a route's dispatched prefix.","required":["routes"],"properties":{"routes":{"type":"array","items":{"type":"object","description":"One vehicle shift's route: every trip of the shift, split by `reload` stops.","required":["vehicle","shift","stops"],"properties":{"shift":{"type":"string","description":"Shift id, within that vehicle.","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].shift","typeLabel":"string"},"stops":{"type":"array","items":{"oneOf":[{"type":"object","title":"PlanStopJob","description":"One stop of a plan route. Start, end and breaks are placed by the solver\nand are not listed.","required":["id","type"],"example":{"id":"parts-9:pickup","type":"pickup"},"properties":{"id":{"type":"string","description":"Job id.","example":"boiler-17","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.0.id","typeLabel":"string"},"type":{"type":"string","description":"Discriminator: always `job`.","enum":["job"],"isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.0.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.0","typeLabel":"PlanStopJob · object"},{"type":"object","title":"PlanStopPickup","description":"One stop of a plan route. Start, end and breaks are placed by the solver\nand are not listed.","required":["id","type"],"example":{"id":"parts-9:pickup","type":"pickup"},"properties":{"id":{"type":"string","description":"The leg's stop id: its own `id`, else `{shipment}:pickup`.","example":"parts-9:pickup","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.1.id","typeLabel":"string"},"type":{"type":"string","description":"Discriminator: always `pickup`.","enum":["pickup"],"isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.1.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.1","typeLabel":"PlanStopPickup · object"},{"type":"object","title":"PlanStopDelivery","description":"One stop of a plan route. Start, end and breaks are placed by the solver\nand are not listed.","required":["id","type"],"example":{"id":"parts-9:pickup","type":"pickup"},"properties":{"id":{"type":"string","description":"The leg's stop id: its own `id`, else `{shipment}:delivery`.","example":"parts-9:delivery","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.2.id","typeLabel":"string"},"type":{"type":"string","description":"Discriminator: always `delivery`.","enum":["delivery"],"isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.2.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.2","typeLabel":"PlanStopDelivery · object"},{"type":"object","title":"PlanStopReload","description":"One stop of a plan route. Start, end and breaks are placed by the solver\nand are not listed.","required":["depot","type"],"example":{"type":"pickup"},"properties":{"depot":{"type":"string","description":"A depot id from the shift's `reloads`.","example":"gent","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.3.depot","typeLabel":"string"},"type":{"type":"string","description":"Discriminator: always `reload`.","enum":["reload"],"isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.3.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX].oneOf.3","typeLabel":"PlanStopReload · object"}],"uniqueKey":"plan.routes.items.[INDEX].stops.items.[INDEX]","typeLabel":"PlanStopJob · object | PlanStopPickup · object | PlanStopDelivery · object | PlanStopReload · object"},"description":"Stops in visiting order.","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].stops","typeLabel":"(PlanStopJob · object | PlanStopPickup · object | PlanStopDelivery · object | PlanStopReload · object)[]"},"vehicle":{"type":"string","description":"Vehicle id.","isRequired":true,"uniqueKey":"plan.routes.items.[INDEX].vehicle","typeLabel":"string"},"locked_count":{"oneOf":[{"type":"integer","format":"int32","description":"On solve, the first `locked_count` stops stay where they are (already\ndispatched). Counts every listed stop. Cannot be combined with a\n`reload` stop, and must not exceed the route's stop count — both are\nvalidated on every endpoint that takes a plan. Otherwise inert on\nevaluate. On suggest, no insertion lands before them.","example":1,"minimum":0,"uniqueKey":"plan.routes.items.[INDEX].locked_count.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"On solve, the first `locked_count` stops stay where they are (already\ndispatched). Counts every listed stop. Cannot be combined with a\n`reload` stop, and must not exceed the route's stop count — both are\nvalidated on every endpoint that takes a plan. Otherwise inert on\nevaluate. On suggest, no insertion lands before them.","example":1,"minimum":0,"uniqueKey":"plan.routes.items.[INDEX].locked_count.oneOf.1","typeLabel":"null"}],"uniqueKey":"plan.routes.items.[INDEX].locked_count","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"shift":"mon","stops":[{"id":"boiler-17","type":"job"}],"vehicle":"van-3"},"uniqueKey":"plan.routes.items.[INDEX]","typeLabel":"object"},"description":"One entry per vehicle shift that serves something.","isRequired":true,"uniqueKey":"plan.routes","typeLabel":"object[]"}},"additionalProperties":false,"isRequired":true,"uniqueKey":"plan","typeLabel":"object"},"problem":{"type":"object","description":"Problem definition — identical to `POST /v3/routing/solve`. Every task\nof it that is not in `plan` is a task to place.","required":["vehicles"],"properties":{"vehicles":{"type":"array","items":{"type":"object","description":"A vehicle type available to serve tasks.","required":["id","shifts"],"properties":{"id":{"type":"string","description":"Vehicle id: 1 to 128 characters, unique across `vehicles[]`; echoed as\n`routes[].vehicle`.","example":"v1","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].id","typeLabel":"string"},"shifts":{"type":"array","items":{"type":"object","description":"One working shift for a vehicle.","required":["id","from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Shift start (RFC 3339 instant, UTC offset required).","example":"2026-07-01T08:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].from","typeLabel":"string\u003cdate-time>"},"id":{"type":"string","description":"Shift id: 1 to 128 characters, unique within this vehicle.","example":"mon","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].id","typeLabel":"string"},"to":{"type":"string","format":"date-time","description":"Shift end (RFC 3339 instant, UTC offset required; hard unless `max_overtime_s` set). The\nroute must be finished by then, end-depot unload included.","example":"2026-07-01T17:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].to","typeLabel":"string\u003cdate-time>"},"breaks":{"oneOf":[{"type":"array","items":{"oneOf":[{"type":"object","title":"Windowed","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["duration_s","time_window","type"],"example":{"duration_s":1800,"type":"triggered"},"properties":{"duration_s":{"type":"integer","format":"int32","description":"Break duration in seconds. Must be `> 0`.","minimum":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.duration_s","typeLabel":"integer\u003cint32>"},"time_window":{"type":"object","description":"The window bounding the break's **start**.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Earliest break start (RFC 3339 instant, UTC offset required).","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.time_window.from","typeLabel":"string\u003cdate-time>"},"to":{"type":"string","format":"date-time","description":"Latest break start (RFC 3339 instant, UTC offset required).","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.time_window.to","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"example":{"from":"2026-07-01T12:00:00+02:00","to":"2026-07-01T13:30:00+02:00"},"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.time_window","typeLabel":"object"},"type":{"type":"string","description":"Discriminator: always `windowed`.","enum":["windowed"],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.type","typeLabel":"enum\u003cstring>"},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.id.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.id","typeLabel":"string | null"},"location":{"oneOf":[{"type":"null","description":"Not supported on V3: a windowed break is taken wherever the\nvehicle is when it starts, so a `location` here is rejected with\nHTTP 400 `not_supported`. Set only by the V2 compatibility mapper.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"Not supported on V3: a windowed break is taken wherever the\nvehicle is when it starts, so a `location` here is rejected with\nHTTP 400 `not_supported`. Set only by the V2 compatibility mapper.","maxItems":2,"minItems":2,"example":[3.725,51.05],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0.location","typeLabel":"null | number\u003cdouble>[]"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.0","typeLabel":"Windowed · object"},{"type":"object","title":"Triggered","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["duration_s","after","threshold_s","type"],"example":{"after":"drive","duration_s":1800,"threshold_s":14400,"type":"triggered"},"properties":{"after":{"type":"string","description":"What to accumulate: drive time or duty time.","enum":["drive","duty"],"example":"drive","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.after","typeLabel":"enum\u003cstring>"},"duration_s":{"type":"integer","format":"int32","description":"Break duration in seconds. Must be `> 0`.","minimum":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.duration_s","typeLabel":"integer\u003cint32>"},"threshold_s":{"type":"integer","format":"int64","description":"Trigger threshold in seconds (strict `>` — the break fires when the\naccumulator exceeds this). EU 561/2006 drive rule: `16200` (4 h 30).\nMust be `> 0` and fit in 32 bits.","example":14400,"maximum":2147483647,"minimum":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.threshold_s","typeLabel":"integer\u003cint64>"},"type":{"type":"string","description":"Discriminator: always `triggered`.","enum":["triggered"],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.type","typeLabel":"enum\u003cstring>"},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.id.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1.id","typeLabel":"string | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.1","typeLabel":"Triggered · object"},{"type":"object","title":"Fixed","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["from","to","type"],"example":{"type":"triggered"},"properties":{"from":{"type":"string","format":"date-time","description":"Start of the break (RFC 3339 instant, UTC offset required).","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.from","typeLabel":"string\u003cdate-time>"},"to":{"type":"string","format":"date-time","description":"End of the break (RFC 3339 instant, UTC offset required).","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.to","typeLabel":"string\u003cdate-time>"},"type":{"type":"string","description":"Discriminator: always `fixed`.","enum":["fixed"],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.type","typeLabel":"enum\u003cstring>"},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.id.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2.id","typeLabel":"string | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX].oneOf.2","typeLabel":"Fixed · object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0.items.[INDEX]","typeLabel":"Windowed · object | Triggered · object | Fixed · object"},"description":"Scheduled driver breaks within this shift — see the `Break` schema for\nthe supported forms. Injected breaks appear as `break` stops in the\nresponse routes.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.0","typeLabel":"(Windowed · object | Triggered · object | Fixed · object)[]"},{"type":"null","items":{"oneOf":[{"type":"object","title":"Windowed","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["duration_s","time_window","type"],"example":{"duration_s":1800,"type":"triggered"},"properties":{"duration_s":{"type":"integer","format":"int32","description":"Break duration in seconds. Must be `> 0`.","minimum":1},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1}]},"location":{"oneOf":[{"type":"null","description":"Not supported on V3: a windowed break is taken wherever the\nvehicle is when it starts, so a `location` here is rejected with\nHTTP 400 `not_supported`. Set only by the V2 compatibility mapper."},{"type":"array","items":{"type":"number","format":"double"},"description":"Not supported on V3: a windowed break is taken wherever the\nvehicle is when it starts, so a `location` here is rejected with\nHTTP 400 `not_supported`. Set only by the V2 compatibility mapper.","maxItems":2,"minItems":2,"example":[3.725,51.05]}]},"time_window":{"type":"object","description":"The window bounding the break's **start**.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Earliest break start (RFC 3339 instant, UTC offset required)."},"to":{"type":"string","format":"date-time","description":"Latest break start (RFC 3339 instant, UTC offset required)."}},"additionalProperties":false,"example":{"from":"2026-07-01T12:00:00+02:00","to":"2026-07-01T13:30:00+02:00"}},"type":{"type":"string","description":"Discriminator: always `windowed`.","enum":["windowed"]}},"additionalProperties":false},{"type":"object","title":"Triggered","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["duration_s","after","threshold_s","type"],"example":{"after":"drive","duration_s":1800,"threshold_s":14400,"type":"triggered"},"properties":{"after":{"type":"string","description":"What to accumulate: drive time or duty time.","enum":["drive","duty"],"example":"drive"},"duration_s":{"type":"integer","format":"int32","description":"Break duration in seconds. Must be `> 0`.","minimum":1},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1}]},"threshold_s":{"type":"integer","format":"int64","description":"Trigger threshold in seconds (strict `>` — the break fires when the\naccumulator exceeds this). EU 561/2006 drive rule: `16200` (4 h 30).\nMust be `> 0` and fit in 32 bits.","example":14400,"maximum":2147483647,"minimum":1},"type":{"type":"string","description":"Discriminator: always `triggered`.","enum":["triggered"]}},"additionalProperties":false},{"type":"object","title":"Fixed","description":"A scheduled break within a shift. Tagged by `type`:\n\n- `windowed`: a break of `duration_s` that starts inside its window.\n- `triggered`: a break of `duration_s` taken once drive or duty time\n passes `threshold_s` (the EU-561 mechanism).\n- `fixed`: a hard off-duty interval from `from` to `to`.\n\nBreaks are injected between stops and appear in the response as `break`\nstops, carrying the break's `id` when it has one.\n\nA `triggered` break always resets its accumulator after a qualifying break\nand is taken wherever the vehicle is: `resets_accumulator` and `location`\ndo not exist on it. A `windowed` break takes exactly one `time_window` and\nis also taken wherever the vehicle is: a `location` on it is HTTP 400\n`not_supported`.\n\nThere is no paid/unpaid cost accounting: a break's duration is never\nseparately priced, and no `paid` field exists on this schema — sending one\nis rejected as an unknown field (HTTP 400, `unknown_field`), like any other extra key.","required":["from","to","type"],"example":{"type":"triggered"},"properties":{"from":{"type":"string","format":"date-time","description":"Start of the break (RFC 3339 instant, UTC offset required)."},"id":{"oneOf":[{"type":"string","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1},{"type":"null","description":"Optional break id: 1 to 128 characters, unique within the shift.\nEchoed as `id` on the `break` stop that realises this break.","example":"lunch","maxLength":128,"minLength":1}]},"to":{"type":"string","format":"date-time","description":"End of the break (RFC 3339 instant, UTC offset required)."},"type":{"type":"string","description":"Discriminator: always `fixed`.","enum":["fixed"]}},"additionalProperties":false}]},"description":"Scheduled driver breaks within this shift — see the `Break` schema for\nthe supported forms. Injected breaks appear as `break` stops in the\nresponse routes.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].breaks","typeLabel":"(Windowed · object | Triggered · object | Fixed · object)[] | null"},"capacity":{"oneOf":[{"type":"null","description":"Capacity for this shift only. Each dimension named here replaces the\nvehicle's value for that dimension; dimensions not named keep the\nvehicle's `capacity`.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].capacity.oneOf.0","typeLabel":"null"},{"type":"object","description":"Capacity for this shift only. Each dimension named here replaces the\nvehicle's value for that dimension; dimensions not named keep the\nvehicle's `capacity`.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].capacity.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].capacity.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].capacity","typeLabel":"null | object"},"costs":{"oneOf":[{"type":"null","description":"Costs for this shift only. Each field set here replaces the same\nfield of the vehicle's `costs` (or, when the vehicle does not set it,\nof `objective.costs`) for this shift; fields not set keep that value.\n`per_used_vehicle` is not accepted here: it prices the vehicle, not a\nshift.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.0","typeLabel":"null"},{"type":"object","description":"Costs for this shift only. Each field set here replaces the same\nfield of the vehicle's `costs` (or, when the vehicle does not set it,\nof `objective.costs`) for this shift; fields not set keep that value.\n`per_used_vehicle` is not accepted here: it prices the vehicle, not a\nshift.","example":{"per_route":50,"per_travel_km":0.3},"properties":{"per_overtime_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour this route finishes past the shift's `to`, as\n`Costs.per_overtime_hour`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_overtime_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour this route finishes past the shift's `to`, as\n`Costs.per_overtime_hour`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_overtime_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_overtime_hour","typeLabel":"number\u003cdouble> | null"},"per_route":{"oneOf":[{"type":"number","format":"double","description":"Flat charge for this used shift, as `Costs.per_route`.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Flat charge for this used shift, as `Costs.per_route`.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route","typeLabel":"number\u003cdouble> | null"},"per_route_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour of this route's wall-clock span, as `Costs.per_route_hour`.","example":35,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour of this route's wall-clock span, as `Costs.per_route_hour`.","example":35,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_route_hour","typeLabel":"number\u003cdouble> | null"},"per_travel_km":{"oneOf":[{"type":"number","format":"double","description":"Per kilometre driven on this shift, as `Costs.per_travel_km`.","example":0.2,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_travel_km.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per kilometre driven on this shift, as `Costs.per_travel_km`.","example":0.2,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_travel_km.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_travel_km","typeLabel":"number\u003cdouble> | null"},"per_wait_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour spent waiting for a time window to open on this shift, as\n`Costs.per_wait_hour`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_wait_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour spent waiting for a time window to open on this shift, as\n`Costs.per_wait_hour`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_wait_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1.per_wait_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].costs","typeLabel":"null | object"},"end":{"oneOf":[{"type":"null","description":"Where the shift ends. Absent = open end.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.0","typeLabel":"null"},{"type":"object","description":"Where the shift ends. Absent = open end.","required":["location"],"example":{"depot":"gent"},"properties":{"location":{"oneOf":[{"type":"null","description":"An inline place. Excludes `depot`.","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"An inline place. Excludes `depot`.","maxItems":2,"minItems":2,"example":[3.725,51.05],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.location","typeLabel":"null | number\u003cdouble>[]"},"depot":{"oneOf":[{"type":"string","description":"A `depots[].id`. Excludes `location`.","example":"gent","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.depot.oneOf.0","typeLabel":"string"},{"type":"null","description":"A `depots[].id`. Excludes `location`.","example":"gent","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.depot.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.depot","typeLabel":"string | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1.service_duration_s","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.1","typeLabel":"object"},{"type":"object","description":"Where the shift ends. Absent = open end.","required":["depot"],"example":{"depot":"gent"},"properties":{"depot":{"oneOf":[{"type":"string","description":"A `depots[].id`. Excludes `location`.","example":"gent","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.depot.oneOf.0","typeLabel":"string"},{"type":"null","description":"A `depots[].id`. Excludes `location`.","example":"gent","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.depot.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.depot","typeLabel":"string | null"},"location":{"oneOf":[{"type":"null","description":"An inline place. Excludes `depot`.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"An inline place. Excludes `depot`.","maxItems":2,"minItems":2,"example":[3.725,51.05],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.location","typeLabel":"null | number\u003cdouble>[]"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2.service_duration_s","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end.oneOf.2","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].end","typeLabel":"null · object · object"},"free_end_travel":{"oneOf":[{"type":"boolean","description":"Symmetric to `free_start_travel` for travel from the last task to\n`end`; `true` without `end` is a 400.","example":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_end_travel.oneOf.0","typeLabel":"boolean"},{"type":"null","description":"Symmetric to `free_start_travel` for travel from the last task to\n`end`; `true` without `end` is a 400.","example":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_end_travel.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_end_travel","typeLabel":"boolean | null"},"free_start_travel":{"oneOf":[{"type":"boolean","description":"When `true`, travel from `start` to the first task is free: it takes\nno time and costs nothing, and is left out of the route's distance\nand duration. The depot is still reported (a real stop, snapped\ncoordinate, departure time). Distinct from omitting `start` (an open\nroute, which drops the depot entirely). `true` without `start` is\nrejected with HTTP 400 `conflicting_fields`. Default `false`.","example":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_start_travel.oneOf.0","typeLabel":"boolean"},{"type":"null","description":"When `true`, travel from `start` to the first task is free: it takes\nno time and costs nothing, and is left out of the route's distance\nand duration. The depot is still reported (a real stop, snapped\ncoordinate, departure time). Distinct from omitting `start` (an open\nroute, which drops the depot entirely). `true` without `start` is\nrejected with HTTP 400 `conflicting_fields`. Default `false`.","example":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_start_travel.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].free_start_travel","typeLabel":"boolean | null"},"initial_load":{"oneOf":[{"type":"null","description":"Load already on the vehicle at shift start (pre-loaded), per\ndimension. Occupies capacity on the first trip only — flushed at the\nfirst reload — so it reduces first-trip room per dimension, enforced\nby the per-trip capacity constraint. Not validated against\n`capacity` at request time: a value at or beyond capacity is\naccepted and surfaces as a solve-time result (jobs left unassigned,\nor deferred until the vehicle's first reload flushes it), not an\nHTTP 400. A dimension named here but absent from `capacity` behaves\nthe same as capacity `0` in that dimension.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].initial_load.oneOf.0","typeLabel":"null"},{"type":"object","description":"Load already on the vehicle at shift start (pre-loaded), per\ndimension. Occupies capacity on the first trip only — flushed at the\nfirst reload — so it reduces first-trip room per dimension, enforced\nby the per-trip capacity constraint. Not validated against\n`capacity` at request time: a value at or beyond capacity is\naccepted and surfaces as a solve-time result (jobs left unassigned,\nor deferred until the vehicle's first reload flushes it), not an\nHTTP 400. A dimension named here but absent from `capacity` behaves\nthe same as capacity `0` in that dimension.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].initial_load.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].initial_load.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].initial_load","typeLabel":"null | object"},"limits":{"oneOf":[{"type":"null","description":"Limits for this shift only. Each field set here replaces the\nvehicle's `limits` value; fields not set keep it.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.0","typeLabel":"null"},{"type":"object","description":"Limits for this shift only. Each field set here replaces the\nvehicle's `limits` value; fields not set keep it.","example":{"max_stops":12},"properties":{"max_distance_m":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on this shift's route distance, in metres. `0` to\n`2147483647`, as on the vehicle.","example":200000,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_distance_m.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on this shift's route distance, in metres. `0` to\n`2147483647`, as on the vehicle.","example":200000,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_distance_m.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_distance_m","typeLabel":"integer\u003cint64> | null"},"max_route_duration_s":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on this shift's route span, in seconds. `0` to\n`2147483647`, as on the vehicle.","example":32400,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_route_duration_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on this shift's route span, in seconds. `0` to\n`2147483647`, as on the vehicle.","example":32400,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_route_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_route_duration_s","typeLabel":"integer\u003cint64> | null"},"max_stops":{"oneOf":[{"type":"integer","format":"int32","description":"Maximum stops served in this shift; a job counts as one stop.\nStart, end, break and reload stops in `routes[].stops` do not count; a\nshipment counts as two stops.","example":50,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_stops.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Maximum stops served in this shift; a job counts as one stop.\nStart, end, break and reload stops in `routes[].stops` do not count; a\nshipment counts as two stops.","example":50,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1.max_stops","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].limits","typeLabel":"null | object"},"max_overtime_s":{"oneOf":[{"type":"integer","format":"int32","description":"Maximum allowed overtime beyond `to` in seconds. Overtime is reached\nby working late, never by waiting: a `synchronized` or `time_lag`\nhold stops at `to`. Default: none (`to` is hard). Must be `>= 0`.","example":1800,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_overtime_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Maximum allowed overtime beyond `to` in seconds. Overtime is reached\nby working late, never by waiting: a `synchronized` or `time_lag`\nhold stops at `to`. Default: none (`to` is hard). Must be `>= 0`.","example":1800,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_overtime_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_overtime_s","typeLabel":"integer\u003cint32> | null"},"max_trips":{"oneOf":[{"type":"integer","format":"int32","description":"Maximum trips (depot legs) in this shift, across all reload depots.\nCounts trips, not reloads: `trips = reloads_used + 1`. `max_trips: 1`\nmeans a single trip — reloads are permitted in `reloads` but the cap\nprevents ever using one. `reloads` present with `max_trips` absent\nmeans unlimited trips. A single reload depot can only be\nrevisited up to 8 times per shift regardless of `max_trips`;\na `max_trips` beyond that against one depot\nis accepted but the extra headroom is unreachable — list more than\none reload depot to raise the practical ceiling. `0` is rejected with\nHTTP 400 (the first trip already counts as trip 1).","example":2,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_trips.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Maximum trips (depot legs) in this shift, across all reload depots.\nCounts trips, not reloads: `trips = reloads_used + 1`. `max_trips: 1`\nmeans a single trip — reloads are permitted in `reloads` but the cap\nprevents ever using one. `reloads` present with `max_trips` absent\nmeans unlimited trips. A single reload depot can only be\nrevisited up to 8 times per shift regardless of `max_trips`;\na `max_trips` beyond that against one depot\nis accepted but the extra headroom is unreachable — list more than\none reload depot to raise the practical ceiling. `0` is rejected with\nHTTP 400 (the first trip already counts as trip 1).","example":2,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_trips.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].max_trips","typeLabel":"integer\u003cint32> | null"},"reloads":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].reloads.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Depots (by `depots[].id`, each at most once) the vehicle may return to\nmid-shift to reload and start a fresh trip. Each visit takes that\ndepot's `service_duration_s` and `per_reload`. Cap trips with\n`max_trips`.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].reloads.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Depots (by `depots[].id`, each at most once) the vehicle may return to\nmid-shift to reload and start a fresh trip. Each visit takes that\ndepot's `service_duration_s` and `per_reload`. Cap trips with\n`max_trips`.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].reloads.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].reloads","typeLabel":"string[] | null"},"serves_tags":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].serves_tags.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Hard tag scope: when set (non-empty), this shift\nserves only tasks carrying at least one of these tags. Untagged tasks\nremain serveable by every shift. Absent or empty = serves everything.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].serves_tags.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Hard tag scope: when set (non-empty), this shift\nserves only tasks carrying at least one of these tags. Untagged tasks\nremain serveable by every shift. Absent or empty = serves everything.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].serves_tags.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].serves_tags","typeLabel":"string[] | null"},"service_factor":{"oneOf":[{"type":"number","format":"double","description":"Work-rate factor for this shift only. It REPLACES\n`vehicles[].service_factor` for the shift when set (absent = inherit the\nvehicle's value, which itself defaults to 1.0); a task's\n`service_factors[].factor` for this vehicle multiplies it.\n\nSame meaning, direction, and `[0.001, 5]` range as the vehicle-level\nfield: service time is DIVIDED by it, effective service time =\n`service_duration_s / service_factor`, so above `1` is faster. Use it\nwhen the same driver works at a different rate on different days — a\nmeasured per-day efficiency, a trainee shift, a two-person crew on\nFridays — instead of collapsing those days into one vehicle-level mean.\n\nScope is identical to the vehicle-level field: task\n`service_duration_s` only, never `setup_duration_s`, depot handling\n(`depots[].service_duration_s`, `start`/`end.service_duration_s`),\nwaiting, or breaks.","maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].service_factor.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Work-rate factor for this shift only. It REPLACES\n`vehicles[].service_factor` for the shift when set (absent = inherit the\nvehicle's value, which itself defaults to 1.0); a task's\n`service_factors[].factor` for this vehicle multiplies it.\n\nSame meaning, direction, and `[0.001, 5]` range as the vehicle-level\nfield: service time is DIVIDED by it, effective service time =\n`service_duration_s / service_factor`, so above `1` is faster. Use it\nwhen the same driver works at a different rate on different days — a\nmeasured per-day efficiency, a trainee shift, a two-person crew on\nFridays — instead of collapsing those days into one vehicle-level mean.\n\nScope is identical to the vehicle-level field: task\n`service_duration_s` only, never `setup_duration_s`, depot handling\n(`depots[].service_duration_s`, `start`/`end.service_duration_s`),\nwaiting, or breaks.","maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].service_factor.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].service_factor","typeLabel":"number\u003cdouble> | null"},"skills":{"oneOf":[{"type":"array","items":{"type":"object","description":"A capability a vehicle or shift provides, at a proficiency level:\n`{ \"name\": \"gas\", \"level\": 3 }`. Always an object; a bare string is\nrejected at parse.","required":["name"],"properties":{"name":{"type":"string","description":"Skill name.","example":"gas","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0.items.[INDEX].name","typeLabel":"string"},"level":{"oneOf":[{"type":"integer","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0.items.[INDEX].level.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0.items.[INDEX].level.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0.items.[INDEX].level","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"level":3,"name":"gas"},"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Capabilities this shift provides, replacing the vehicle's `skills`\nfor this shift only (a technician covering another region on one\nday, a crew that only carries a certification on some shifts). A\njob's `required_skills` must all appear in the skills of the shift that\nserves it, at a level of at least the job's `min_level`. Same entry\nshape as `vehicles[].skills`. Absent = the vehicle's `skills`; `[]` =\nthis shift provides none.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A capability a vehicle or shift provides, at a proficiency level:\n`{ \"name\": \"gas\", \"level\": 3 }`. Always an object; a bare string is\nrejected at parse.","required":["name"],"properties":{"level":{"oneOf":[{"type":"integer","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1},{"type":"null","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1}]},"name":{"type":"string","description":"Skill name.","example":"gas"}},"additionalProperties":false,"example":{"level":3,"name":"gas"}},"description":"Capabilities this shift provides, replacing the vehicle's `skills`\nfor this shift only (a technician covering another region on one\nday, a crew that only carries a certification on some shifts). A\njob's `required_skills` must all appear in the skills of the shift that\nserves it, at a level of at least the job's `min_level`. Same entry\nshape as `vehicles[].skills`. Absent = the vehicle's `skills`; `[]` =\nthis shift provides none.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].skills","typeLabel":"object[] | null"},"start":{"oneOf":[{"type":"null","description":"Where the shift starts. Absent = open start.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.0","typeLabel":"null"},{"type":"object","description":"Where the shift starts. Absent = open start.","required":["location"],"example":{"depot":"gent"},"properties":{"location":{"oneOf":[{"type":"null","description":"An inline place. Excludes `depot`.","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"An inline place. Excludes `depot`.","maxItems":2,"minItems":2,"example":[3.725,51.05],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.location","typeLabel":"null | number\u003cdouble>[]"},"depot":{"oneOf":[{"type":"string","description":"A `depots[].id`. Excludes `location`.","example":"gent","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.depot.oneOf.0","typeLabel":"string"},{"type":"null","description":"A `depots[].id`. Excludes `location`.","example":"gent","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.depot.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.depot","typeLabel":"string | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1.service_duration_s","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.1","typeLabel":"object"},{"type":"object","description":"Where the shift starts. Absent = open start.","required":["depot"],"example":{"depot":"gent"},"properties":{"depot":{"oneOf":[{"type":"string","description":"A `depots[].id`. Excludes `location`.","example":"gent","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.depot.oneOf.0","typeLabel":"string"},{"type":"null","description":"A `depots[].id`. Excludes `location`.","example":"gent","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.depot.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.depot","typeLabel":"string | null"},"location":{"oneOf":[{"type":"null","description":"An inline place. Excludes `depot`.","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"An inline place. Excludes `depot`.","maxItems":2,"minItems":2,"example":[3.725,51.05],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.location","typeLabel":"null | number\u003cdouble>[]"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Handling time in seconds at this end: the morning load at `start`, the\nevening unload at `end`. Overrides the depot's `service_duration_s`;\ndefault: the depot's value, or 0 for a `location` end. Not applied on\nfree travel (`free_start_travel`/`free_end_travel`). Not scaled by\n`service_factor`.\n\nThe unload must finish by the shift's `to` (or `to + max_overtime_s`):\na route whose unload would run past it is infeasible. A shift whose\nload and unload alone exceed it is rejected with HTTP 400.","example":600,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2.service_duration_s","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start.oneOf.2","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX].start","typeLabel":"null · object · object"}},"additionalProperties":false,"example":{"end":{"location":[3.7174,51.0543]},"from":"2026-07-01T08:00:00+02:00","id":"mon","start":{"location":[3.7174,51.0543]},"to":"2026-07-01T17:00:00+02:00"},"uniqueKey":"problem.vehicles.items.[INDEX].shifts.items.[INDEX]","typeLabel":"object"},"description":"One or more working shifts. A vehicle without shifts is rejected with\nHTTP 400.","minItems":1,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].shifts","typeLabel":"object[]"},"capacity":{"oneOf":[{"type":"null","description":"Named capacity dimensions.","uniqueKey":"problem.vehicles.items.[INDEX].capacity.oneOf.0","typeLabel":"null"},{"type":"object","description":"Named capacity dimensions.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].capacity.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.vehicles.items.[INDEX].capacity.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].capacity","typeLabel":"null | object"},"compatible_with":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.vehicles.items.[INDEX].compatible_with.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Vehicles this one may serve a `compatible_vehicles` relation's tasks\ntogether with, by id. Absent: any vehicle. A list is a veto, so a\none-sided list still binds both vehicles: two vehicles may share a\nrelation only if neither's list excludes the other. A vehicle always\npairs with itself and all its shifts count as one vehicle; to pair a\nvehicle with no other, list only its own id. An empty list is rejected\nwith HTTP 400 (it would read as \"everyone\" in a client that drops empty\narrays), and so is an id that names no vehicle. Inert unless a\n`compatible_vehicles` relation names tasks.","example":["v2","v3"],"minItems":1,"uniqueKey":"problem.vehicles.items.[INDEX].compatible_with.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Vehicles this one may serve a `compatible_vehicles` relation's tasks\ntogether with, by id. Absent: any vehicle. A list is a veto, so a\none-sided list still binds both vehicles: two vehicles may share a\nrelation only if neither's list excludes the other. A vehicle always\npairs with itself and all its shifts count as one vehicle; to pair a\nvehicle with no other, list only its own id. An empty list is rejected\nwith HTTP 400 (it would read as \"everyone\" in a client that drops empty\narrays), and so is an id that names no vehicle. Inert unless a\n`compatible_vehicles` relation names tasks.","example":["v2","v3"],"minItems":1,"uniqueKey":"problem.vehicles.items.[INDEX].compatible_with.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].compatible_with","typeLabel":"string[] | null"},"costs":{"oneOf":[{"type":"null","description":"This vehicle's costs. Each field set here replaces the same field of\n`objective.costs` for this vehicle; fields not set keep the fleet\nvalue. A shift's own `costs` replace these per field in turn.","uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.0","typeLabel":"null"},{"type":"object","description":"This vehicle's costs. Each field set here replaces the same field of\n`objective.costs` for this vehicle; fields not set keep the fleet\nvalue. A shift's own `costs` replace these per field in turn.","example":{"per_route":50,"per_route_hour":35,"per_travel_km":0.2},"properties":{"per_overtime_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour a route finishes past its shift's `to` (possible only with\n`max_overtime_s`), reported in `score.components.overtime`, on top of\n`per_route_hour`. Default `0`: overtime is unpriced.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_overtime_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour a route finishes past its shift's `to` (possible only with\n`max_overtime_s`), reported in `score.components.overtime`, on top of\n`per_route_hour`. Default `0`: overtime is unpriced.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_overtime_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_overtime_hour","typeLabel":"number\u003cdouble> | null"},"per_route":{"oneOf":[{"type":"number","format":"double","description":"Flat charge for each used shift (a route with at least one task),\nreported in `score.components.routes`. Default `0`. The higher it is,\nthe more travel the solver accepts to avoid opening another route. It\ncounts shifts, not vehicles: a vehicle that works five days pays it five\ntimes, so it does not prefer one vehicle on two shifts over two vehicles\non one shift each; use `per_used_vehicle` for that.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Flat charge for each used shift (a route with at least one task),\nreported in `score.components.routes`. Default `0`. The higher it is,\nthe more travel the solver accepts to avoid opening another route. It\ncounts shifts, not vehicles: a vehicle that works five days pays it five\ntimes, so it does not prefer one vehicle on two shifts over two vehicles\non one shift each; use `per_used_vehicle` for that.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route","typeLabel":"number\u003cdouble> | null"},"per_route_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour of each route's wall-clock span (travel, service, waiting\nand breaks), reported in `score.components.time`. Default **35** at objective\nlevel; a vehicle or shift value inherits the fleet value.","example":35,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour of each route's wall-clock span (travel, service, waiting\nand breaks), reported in `score.components.time`. Default **35** at objective\nlevel; a vehicle or shift value inherits the fleet value.","example":35,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_route_hour","typeLabel":"number\u003cdouble> | null"},"per_travel_km":{"oneOf":[{"type":"number","format":"double","description":"Per kilometre driven, reported in `score.components.distance`.\nDefault **0.20** at objective level; a vehicle or shift value inherits the\nfleet value.","example":0.2,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_travel_km.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per kilometre driven, reported in `score.components.distance`.\nDefault **0.20** at objective level; a vehicle or shift value inherits the\nfleet value.","example":0.2,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_travel_km.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_travel_km","typeLabel":"number\u003cdouble> | null"},"per_used_vehicle":{"oneOf":[{"type":"number","format":"double","description":"Flat charge once per vehicle that serves at least one task, however\nmany of its shifts it works. Reported in `score.components.vehicles`.\nAdds to `per_route`: the vehicle's first used shift pays both, later\nshifts only `per_route`. Default `0`. Use it to minimise distinct\nvehicles; use `per_route` to price each working day. Not accepted on\n`shifts[].costs`. When any vehicle has a non-zero rate and any vehicle\nhas several shifts, the problem solves without decomposition.","example":400,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_used_vehicle.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Flat charge once per vehicle that serves at least one task, however\nmany of its shifts it works. Reported in `score.components.vehicles`.\nAdds to `per_route`: the vehicle's first used shift pays both, later\nshifts only `per_route`. Default `0`. Use it to minimise distinct\nvehicles; use `per_route` to price each working day. Not accepted on\n`shifts[].costs`. When any vehicle has a non-zero rate and any vehicle\nhas several shifts, the problem solves without decomposition.","example":400,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_used_vehicle.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_used_vehicle","typeLabel":"number\u003cdouble> | null"},"per_wait_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour spent waiting for a time window to open, reported in\n`score.components.waiting`, on top of `per_route_hour` (the span\nincludes the wait). Idle before a windowed break's window opens is\nreported in `wait_s` but not charged here. Default `0`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_wait_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour spent waiting for a time window to open, reported in\n`score.components.waiting`, on top of `per_route_hour` (the span\nincludes the wait). Idle before a windowed break's window opens is\nreported in `wait_s` but not charged here. Default `0`.","example":0,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_wait_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1.per_wait_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].costs.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].costs","typeLabel":"null | object"},"limits":{"oneOf":[{"type":"null","description":"Hard operating limits.","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.0","typeLabel":"null"},{"type":"object","description":"Hard operating limits.","example":{"max_distance_m":200000,"max_route_duration_s":32400},"properties":{"max_distance_m":{"oneOf":[{"type":"integer","format":"int64","description":"Hard maximum distance in metres. `0` to `2147483647`; a value\noutside that range is rejected with HTTP 400 `out_of_range`.","example":200000,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_distance_m.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard maximum distance in metres. `0` to `2147483647`; a value\noutside that range is rejected with HTTP 400 `out_of_range`.","example":200000,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_distance_m.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_distance_m","typeLabel":"integer\u003cint64> | null"},"max_leg_travel_s":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap in seconds on any single travel leg of this vehicle's routes:\nthe `travel_s` reported on each stop, start-to-first-task and\nlast-task-to-`end` included. Travel only: setup, service and wait do\nnot count, and `speed_factor` applies first. A leg made free by\n`free_start_travel`/`free_end_travel`, or absent on an open start or\nend, is exempt. Absent = no cap. Must be > 0: `0` would make every\nleg too long rather than mean \"no cap\", so it is rejected with HTTP\n400 `out_of_range`, as is a value that does not fit in 32 bits. A\nbreach is reported as `max_leg_travel`.","example":3600,"maximum":2147483647,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_leg_travel_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap in seconds on any single travel leg of this vehicle's routes:\nthe `travel_s` reported on each stop, start-to-first-task and\nlast-task-to-`end` included. Travel only: setup, service and wait do\nnot count, and `speed_factor` applies first. A leg made free by\n`free_start_travel`/`free_end_travel`, or absent on an open start or\nend, is exempt. Absent = no cap. Must be > 0: `0` would make every\nleg too long rather than mean \"no cap\", so it is rejected with HTTP\n400 `out_of_range`, as is a value that does not fit in 32 bits. A\nbreach is reported as `max_leg_travel`.","example":3600,"maximum":2147483647,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_leg_travel_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_leg_travel_s","typeLabel":"integer\u003cint64> | null"},"max_route_duration_s":{"oneOf":[{"type":"integer","format":"int64","description":"Hard maximum route duration in seconds: the whole-route span —\ntravel, service, and wait all count, depot load and unload included.\nThe same quantity as the response's `routes[].time.span_s`. `0` to\n`2147483647`; a value outside that range is rejected with HTTP 400\n`out_of_range`.","example":32400,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_route_duration_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard maximum route duration in seconds: the whole-route span —\ntravel, service, and wait all count, depot load and unload included.\nThe same quantity as the response's `routes[].time.span_s`. `0` to\n`2147483647`; a value outside that range is rejected with HTTP 400\n`out_of_range`.","example":32400,"maximum":2147483647,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_route_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_route_duration_s","typeLabel":"integer\u003cint64> | null"},"max_stops":{"oneOf":[{"type":"integer","format":"int32","description":"Maximum stops served per shift; a job counts as one stop.\nStart, end, break and reload stops in `routes[].stops` do not count; a\nshipment counts as two stops.","example":50,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_stops.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Maximum stops served per shift; a job counts as one stop.\nStart, end, break and reload stops in `routes[].stops` do not count; a\nshipment counts as two stops.","example":50,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.max_stops","typeLabel":"integer\u003cint32> | null"},"periods":{"type":"array","items":{"oneOf":[{"type":"object","description":"A cap on a vehicle's totals across every shift that starts in one period.\nSet exactly one of `every`, or `from` and `to`; and at least one maximum.","required":["every"],"example":{"every":"week","max_route_duration_s":144000,"max_stops":40},"properties":{"every":{"oneOf":[{"type":"null","description":"A recurring period: every `day`, or every `week` (weeks start Monday).","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.every.oneOf.0","typeLabel":"null"},{"type":"string","description":"A recurring period: every `day`, or every `week` (weeks start Monday).","enum":["day","week"],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.every.oneOf.1","typeLabel":"enum\u003cstring>"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.every","typeLabel":"null | enum\u003cstring>"},"from":{"oneOf":[{"type":"string","format":"date-time","description":"Start of one explicit period (RFC 3339, UTC offset required), with `to`. The window must\nhold at least one of the vehicle's shift starts; a period inside one\nshift is not supported.","example":"2026-10-05T00:00:00+02:00","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.from.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Start of one explicit period (RFC 3339, UTC offset required), with `to`. The window must\nhold at least one of the vehicle's shift starts; a period inside one\nshift is not supported.","example":"2026-10-05T00:00:00+02:00","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.from.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.from","typeLabel":"string\u003cdate-time> | null"},"max_distance_m":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on the summed distance driven, in metres. Must be `>= 0`.","example":900000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_distance_m.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on the summed distance driven, in metres. Must be `>= 0`.","example":900000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_distance_m.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_distance_m","typeLabel":"integer\u003cint64> | null"},"max_route_duration_s":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on the summed route span of the period's shifts, measured as a\nshift's `max_route_duration_s` is, in seconds. An unused shift adds\nnothing. Must be `>= 0`.","example":144000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_route_duration_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on the summed route span of the period's shifts, measured as a\nshift's `max_route_duration_s` is, in seconds. An unused shift adds\nnothing. Must be `>= 0`.","example":144000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_route_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_route_duration_s","typeLabel":"integer\u003cint64> | null"},"max_stops":{"oneOf":[{"type":"integer","format":"int32","description":"Hard cap on served stops across the period's shifts; a job counts as\none stop. Start, end, break and reload stops in `routes[].stops` do not\ncount; a shipment counts as two stops.","example":40,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_stops.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Hard cap on served stops across the period's shifts; a job counts as\none stop. Start, end, break and reload stops in `routes[].stops` do not\ncount; a shipment counts as two stops.","example":40,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.max_stops","typeLabel":"integer\u003cint32> | null"},"to":{"oneOf":[{"type":"string","format":"date-time","description":"End of one explicit period (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-12T00:00:00+02:00","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.to.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"End of one explicit period (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-12T00:00:00+02:00","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.to.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0.to","typeLabel":"string\u003cdate-time> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"A cap on a vehicle's totals across every shift that starts in one period.\nSet exactly one of `every`, or `from` and `to`; and at least one maximum.","required":["from","to"],"example":{"every":"week","max_route_duration_s":144000,"max_stops":40},"properties":{"from":{"oneOf":[{"type":"string","format":"date-time","description":"Start of one explicit period (RFC 3339, UTC offset required), with `to`. The window must\nhold at least one of the vehicle's shift starts; a period inside one\nshift is not supported.","example":"2026-10-05T00:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.from.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Start of one explicit period (RFC 3339, UTC offset required), with `to`. The window must\nhold at least one of the vehicle's shift starts; a period inside one\nshift is not supported.","example":"2026-10-05T00:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.from.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.from","typeLabel":"string\u003cdate-time> | null"},"to":{"oneOf":[{"type":"string","format":"date-time","description":"End of one explicit period (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-12T00:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.to.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"End of one explicit period (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-12T00:00:00+02:00","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.to.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.to","typeLabel":"string\u003cdate-time> | null"},"every":{"oneOf":[{"type":"null","description":"A recurring period: every `day`, or every `week` (weeks start Monday).","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.every.oneOf.0","typeLabel":"null"},{"type":"string","description":"A recurring period: every `day`, or every `week` (weeks start Monday).","enum":["day","week"],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.every.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.every","typeLabel":"null | enum\u003cstring>"},"max_distance_m":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on the summed distance driven, in metres. Must be `>= 0`.","example":900000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_distance_m.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on the summed distance driven, in metres. Must be `>= 0`.","example":900000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_distance_m.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_distance_m","typeLabel":"integer\u003cint64> | null"},"max_route_duration_s":{"oneOf":[{"type":"integer","format":"int64","description":"Hard cap on the summed route span of the period's shifts, measured as a\nshift's `max_route_duration_s` is, in seconds. An unused shift adds\nnothing. Must be `>= 0`.","example":144000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_route_duration_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Hard cap on the summed route span of the period's shifts, measured as a\nshift's `max_route_duration_s` is, in seconds. An unused shift adds\nnothing. Must be `>= 0`.","example":144000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_route_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_route_duration_s","typeLabel":"integer\u003cint64> | null"},"max_stops":{"oneOf":[{"type":"integer","format":"int32","description":"Hard cap on served stops across the period's shifts; a job counts as\none stop. Start, end, break and reload stops in `routes[].stops` do not\ncount; a shipment counts as two stops.","example":40,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_stops.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Hard cap on served stops across the period's shifts; a job counts as\none stop. Start, end, break and reload stops in `routes[].stops` do not\ncount; a shipment counts as two stops.","example":40,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1.max_stops","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods.items.[INDEX]","typeLabel":"object"},"description":"Hard caps on this vehicle's totals across all of its shifts in a day,\na week or an explicit window. Each shift counts toward the one\nperiod that contains its `from`, read in that shift's own UTC offset.\nA recurring period with none of the vehicle's shifts is skipped; an\nexplicit window with no shift start is a 400.","uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1.periods","typeLabel":"object[]"}},"additionalProperties":false,"uniqueKey":"problem.vehicles.items.[INDEX].limits.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.vehicles.items.[INDEX].limits","typeLabel":"null | object"},"preferred_tags":{"oneOf":[{"type":"array","items":{"type":"object","description":"A soft tag preference, priced.","required":["tag","violation_cost"],"properties":{"tag":{"type":"string","description":"Preferred tag.","example":"north","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags.oneOf.0.items.[INDEX].tag","typeLabel":"string"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a task without this\ntag is served. Must be finite and `>= 0`, and one vehicle's entries\nmust sum to at most 21474.83647 (a task lacking every tag pays them all).","example":25,"maximum":21474.83647,"minimum":0,"isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags.oneOf.0.items.[INDEX].violation_cost","typeLabel":"number\u003cdouble>"}},"additionalProperties":false,"example":{"tag":"north","violation_cost":25},"uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Soft tag preferences. Serving a task that does not\ncarry a preferred tag incurs that entry's `violation_cost`. Entries\napply independently: a task lacking several preferred tags incurs each\ncost.","uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A soft tag preference, priced.","required":["tag","violation_cost"],"properties":{"tag":{"type":"string","description":"Preferred tag.","example":"north"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a task without this\ntag is served. Must be finite and `>= 0`, and one vehicle's entries\nmust sum to at most 21474.83647 (a task lacking every tag pays them all).","example":25,"maximum":21474.83647,"minimum":0}},"additionalProperties":false,"example":{"tag":"north","violation_cost":25}},"description":"Soft tag preferences. Serving a task that does not\ncarry a preferred tag incurs that entry's `violation_cost`. Entries\napply independently: a task lacking several preferred tags incurs each\ncost.","uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].preferred_tags","typeLabel":"object[] | null"},"profile":{"oneOf":[{"type":"null","description":"Routing profile: `car` (default), `truck` or `bike` — selects the road\nnetwork and speeds behind this vehicle's travel times and distances.\nAny other value is rejected with HTTP 400.","uniqueKey":"problem.vehicles.items.[INDEX].profile.oneOf.0","typeLabel":"null"},{"type":"string","description":"Routing profile: `car` (default), `truck` or `bike` — selects the road\nnetwork and speeds behind this vehicle's travel times and distances.\nAny other value is rejected with HTTP 400.","enum":["car","truck","bike"],"example":"car","uniqueKey":"problem.vehicles.items.[INDEX].profile.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.vehicles.items.[INDEX].profile","typeLabel":"null | enum\u003cstring>"},"service_factor":{"oneOf":[{"type":"number","format":"double","description":"Work-rate multiplier for service time at stops (1.0 = base rate).\n\nSame direction as `speed_factor`: effective service time =\n`service_duration_s / service_factor`, so values > 1.0 model a driver who\nworks FASTER and spends less time at each stop, and \u003c 1.0 one who is\nslower. Use it for crew size, equipment, or experience — how quickly the\nwork gets done, as distinct from how fast the vehicle drives.\n\nApplies to job/stop `service_duration_s` only. Deliberately NOT applied\nto `setup_duration_s` (fixed arrival overhead such as parking),\ndepot handling (`depots[].service_duration_s`,\n`start`/`end.service_duration_s`), waiting time, or break durations.\n\nMust be in `[0.001, 5]`. Default 1.0. A shift's own `service_factor`\nreplaces it for that shift; a task's `service_factors[].factor` for\nthis vehicle multiplies whichever applies: effective service time =\n`service_duration_s / (shift_or_vehicle_factor * task_factor)`.\n\nV2's `durationModifier` went the other way (it MULTIPLIED duration,\n`0.8` = 20% faster); the V2 compatibility layer inverts it and sends it\nas the task's `service_factors[].factor = 1 / durationModifier`.","default":1,"maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].service_factor.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Work-rate multiplier for service time at stops (1.0 = base rate).\n\nSame direction as `speed_factor`: effective service time =\n`service_duration_s / service_factor`, so values > 1.0 model a driver who\nworks FASTER and spends less time at each stop, and \u003c 1.0 one who is\nslower. Use it for crew size, equipment, or experience — how quickly the\nwork gets done, as distinct from how fast the vehicle drives.\n\nApplies to job/stop `service_duration_s` only. Deliberately NOT applied\nto `setup_duration_s` (fixed arrival overhead such as parking),\ndepot handling (`depots[].service_duration_s`,\n`start`/`end.service_duration_s`), waiting time, or break durations.\n\nMust be in `[0.001, 5]`. Default 1.0. A shift's own `service_factor`\nreplaces it for that shift; a task's `service_factors[].factor` for\nthis vehicle multiplies whichever applies: effective service time =\n`service_duration_s / (shift_or_vehicle_factor * task_factor)`.\n\nV2's `durationModifier` went the other way (it MULTIPLIED duration,\n`0.8` = 20% faster); the V2 compatibility layer inverts it and sends it\nas the task's `service_factors[].factor = 1 / durationModifier`.","default":1,"maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].service_factor.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].service_factor","typeLabel":"number\u003cdouble> | null"},"skills":{"oneOf":[{"type":"array","items":{"type":"object","description":"A capability a vehicle or shift provides, at a proficiency level:\n`{ \"name\": \"gas\", \"level\": 3 }`. Always an object; a bare string is\nrejected at parse.","required":["name"],"properties":{"name":{"type":"string","description":"Skill name.","example":"gas","isRequired":true,"uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0.items.[INDEX].name","typeLabel":"string"},"level":{"oneOf":[{"type":"integer","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0.items.[INDEX].level.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1,"uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0.items.[INDEX].level.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0.items.[INDEX].level","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"level":3,"name":"gas"},"uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Capabilities the vehicle provides. A job's `required_skills` must all appear\nhere at a level of at least the job's `min_level`. Each entry is an\nobject `{ \"name\": ..., \"level\": N }` (`level` optional, default 1);\na bare string is rejected. A skill may appear once per list. Omitting\nthe field is the same as `[]`: the vehicle can only serve jobs that\nrequire no skills.","uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A capability a vehicle or shift provides, at a proficiency level:\n`{ \"name\": \"gas\", \"level\": 3 }`. Always an object; a bare string is\nrejected at parse.","required":["name"],"properties":{"level":{"oneOf":[{"type":"integer","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1},{"type":"null","format":"int32","description":"Proficiency level, `>= 1`; absent = 1. Satisfies every job\nrequirement of this skill whose `min_level` is at most this value.","example":3,"minimum":1}]},"name":{"type":"string","description":"Skill name.","example":"gas"}},"additionalProperties":false,"example":{"level":3,"name":"gas"}},"description":"Capabilities the vehicle provides. A job's `required_skills` must all appear\nhere at a level of at least the job's `min_level`. Each entry is an\nobject `{ \"name\": ..., \"level\": N }` (`level` optional, default 1);\na bare string is rejected. A skill may appear once per list. Omitting\nthe field is the same as `[]`: the vehicle can only serve jobs that\nrequire no skills.","uniqueKey":"problem.vehicles.items.[INDEX].skills.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].skills","typeLabel":"object[] | null"},"speed_factor":{"oneOf":[{"type":"number","format":"double","description":"Travel-speed multiplier (1.0 = base speed). Effective travel time =\n`base travel time / speed_factor`, so values > 1.0 model a faster\nvehicle and \u003c 1.0 a slower one. Must be in `[0.001, 5]`. Default 1.0.\n\nCovers driving only. Its companion `service_factor` scales the\nwork done at stops; the two are independent and share this direction and\nrange.","default":1,"maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].speed_factor.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Travel-speed multiplier (1.0 = base speed). Effective travel time =\n`base travel time / speed_factor`, so values > 1.0 model a faster\nvehicle and \u003c 1.0 a slower one. Must be in `[0.001, 5]`. Default 1.0.\n\nCovers driving only. Its companion `service_factor` scales the\nwork done at stops; the two are independent and share this direction and\nrange.","default":1,"maximum":5,"minimum":0.001,"uniqueKey":"problem.vehicles.items.[INDEX].speed_factor.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].speed_factor","typeLabel":"number\u003cdouble> | null"},"workload_weight":{"oneOf":[{"type":"number","format":"double","description":"Share of the work this vehicle carries under `objective.workload_share`,\nrelative to the other vehicles. Default `1`; `0.5` carries half as much;\n`0` leaves the vehicle out of the balancing. `0` to `1000000`\n(HTTP 400 `out_of_range` outside that). Ignored when\n`objective.workload_share` is not set.","example":0.5,"maximum":1000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].workload_weight.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Share of the work this vehicle carries under `objective.workload_share`,\nrelative to the other vehicles. Default `1`; `0.5` carries half as much;\n`0` leaves the vehicle out of the balancing. `0` to `1000000`\n(HTTP 400 `out_of_range` outside that). Ignored when\n`objective.workload_share` is not set.","example":0.5,"maximum":1000000,"minimum":0,"uniqueKey":"problem.vehicles.items.[INDEX].workload_weight.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.vehicles.items.[INDEX].workload_weight","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"example":{"capacity":{"volume":20,"weight":500},"id":"v1","profile":"car","shifts":[{"end":{"location":[3.7174,51.0543]},"from":"2026-07-01T08:00:00+02:00","id":"mon","start":{"location":[3.7174,51.0543]},"to":"2026-07-01T17:00:00+02:00"}],"skills":[{"name":"fridge"}]},"uniqueKey":"problem.vehicles.items.[INDEX]","typeLabel":"object"},"description":"Available vehicles: 1 to 2,000 (HTTP 400 otherwise).","maxItems":2000,"minItems":1,"isRequired":true,"uniqueKey":"problem.vehicles","typeLabel":"object[]"},"depots":{"type":"array","items":{"type":"object","description":"A depot: a place a shift starts from, ends at, or reloads at mid-shift,\nreferenced by `id` from `shifts[].start`, `shifts[].end` and\n`shifts[].reloads`. Each depot keeps its own handling time and reload cost.","required":["id","location"],"properties":{"id":{"type":"string","description":"Depot id: 1 to 128 characters, unique across `depots[]`.","example":"gent","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.depots.items.[INDEX].id","typeLabel":"string"},"location":{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.depots.items.[INDEX].location.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"Where the depot is.","examples":[[3.725,51.05]],"maxItems":2,"minItems":2,"isRequired":true,"uniqueKey":"problem.depots.items.[INDEX].location","typeLabel":"number\u003cdouble>[]"},"per_reload":{"oneOf":[{"type":"number","format":"double","description":"Money charged once per reload visit, in the objective's currency.\nDefault 0; at most `1e9`. A shift that only starts or ends here is not\ncharged.\n\nSet this when a reload has a real per-reload price the travel terms\ncannot see — typically the driver labour for the unload itself\n(`service_duration_s` × the hourly rate). Without it, a reload that\nconsumes only *slack* is free in the objective: it adds no route\nduration, so the solver will happily insert one to displace time that\n`objective.costs.per_wait_hour` would otherwise charge as idle, parking\nthe vehicle at a depot for no capacity benefit.","example":38.66,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.depots.items.[INDEX].per_reload.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Money charged once per reload visit, in the objective's currency.\nDefault 0; at most `1e9`. A shift that only starts or ends here is not\ncharged.\n\nSet this when a reload has a real per-reload price the travel terms\ncannot see — typically the driver labour for the unload itself\n(`service_duration_s` × the hourly rate). Without it, a reload that\nconsumes only *slack* is free in the objective: it adds no route\nduration, so the solver will happily insert one to displace time that\n`objective.costs.per_wait_hour` would otherwise charge as idle, parking\nthe vehicle at a depot for no capacity benefit.","example":38.66,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.depots.items.[INDEX].per_reload.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.depots.items.[INDEX].per_reload","typeLabel":"number\u003cdouble> | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Handling time in seconds per visit: the load before a shift that starts\nhere, the unload after a shift that ends here, and each reload. A shift\nend's own `service_duration_s` overrides it for that end. Default 0.\nThe unload after a shift must finish by that shift's `to` (or\n`to + max_overtime_s`). Not scaled by `service_factor`: this is\ndepot-side handling, not the driver's on-site work rate.","example":900,"minimum":0,"uniqueKey":"problem.depots.items.[INDEX].service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Handling time in seconds per visit: the load before a shift that starts\nhere, the unload after a shift that ends here, and each reload. A shift\nend's own `service_duration_s` overrides it for that end. Default 0.\nThe unload after a shift must finish by that shift's `to` (or\n`to + max_overtime_s`). Not scaled by `service_factor`: this is\ndepot-side handling, not the driver's on-site work rate.","example":900,"minimum":0,"uniqueKey":"problem.depots.items.[INDEX].service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.depots.items.[INDEX].service_duration_s","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"id":"gent","location":[3.7174,51.0543],"service_duration_s":900},"uniqueKey":"problem.depots.items.[INDEX]","typeLabel":"object"},"description":"Depots that shifts start from, end at, or reload at, by id.","uniqueKey":"problem.depots","typeLabel":"object[]"},"jobs":{"type":"array","items":{"type":"object","description":"A single-stop visit: one location served once (the `jobs[]` entry type).\nFor a pickup bound to a delivery on the same vehicle, use `shipments[]`.","required":["id"],"properties":{"id":{"type":"string","description":"Job id: 1 to 128 characters, unique across `jobs` + `shipments`.","example":"job-1","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].id","typeLabel":"string"},"assignment_costs":{"oneOf":[{"type":"array","items":{"type":"object","description":"Absolute price of serving one task on one vehicle.","required":["vehicle","cost"],"properties":{"cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when this vehicle serves\nthe task. Must be finite and `>= 0`. A vehicle not listed costs `0`.","example":12.5,"maximum":21474.83647,"minimum":0,"isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX].cost","typeLabel":"number\u003cdouble>"},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle. An id that matches\nno vehicle, or a vehicle listed twice in one task's\n`assignment_costs`, is rejected with HTTP 400.","example":"v1","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"}},"additionalProperties":false,"example":{"cost":12.5,"vehicle":"v1"},"uniqueKey":"problem.jobs.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Absolute price of serving this task on a given vehicle, in the\nobjective's currency. Charged once, when that vehicle (on any of its\nshifts) serves the task; unlisted vehicles cost nothing. Unlike\n`preferences`, which charges the vehicles that did NOT get the task,\nthis prices the vehicle that did, so a task rated badly everywhere is\nthe first one dropped when capacity runs out. It lives in the cost tier,\nbelow `priority`, and adds to `preferences`, `drop_cost` and travel.\nNot applied by decomposition: a problem that sets it solves monolithically.","uniqueKey":"problem.jobs.items.[INDEX].assignment_costs.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Absolute price of serving one task on one vehicle.","required":["vehicle","cost"],"properties":{"cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when this vehicle serves\nthe task. Must be finite and `>= 0`. A vehicle not listed costs `0`.","example":12.5,"maximum":21474.83647,"minimum":0},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle. An id that matches\nno vehicle, or a vehicle listed twice in one task's\n`assignment_costs`, is rejected with HTTP 400.","example":"v1"}},"additionalProperties":false,"example":{"cost":12.5,"vehicle":"v1"}},"description":"Absolute price of serving this task on a given vehicle, in the\nobjective's currency. Charged once, when that vehicle (on any of its\nshifts) serves the task; unlisted vehicles cost nothing. Unlike\n`preferences`, which charges the vehicles that did NOT get the task,\nthis prices the vehicle that did, so a task rated badly everywhere is\nthe first one dropped when capacity runs out. It lives in the cost tier,\nbelow `priority`, and adds to `preferences`, `drop_cost` and travel.\nNot applied by decomposition: a problem that sets it solves monolithically.","uniqueKey":"problem.jobs.items.[INDEX].assignment_costs.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].assignment_costs","typeLabel":"object[] | null"},"break_interruptible":{"oneOf":[{"type":"boolean","description":"Whether a break may pause this job's service. With `true`, a `fixed`\nbreak, a `windowed` break or a duty-`triggered` break that falls\ninside the service pauses it: the work resumes when the break ends,\nthe job departs the break's length later, and the stop reports the\npaused seconds in `break_s`. A drive-`triggered` break never pauses a\njob (it counts driving time only). Default `false`: the whole service\nmoves after the break, or the break is taken before the job starts.","example":true,"uniqueKey":"problem.jobs.items.[INDEX].break_interruptible.oneOf.0","typeLabel":"boolean"},{"type":"null","description":"Whether a break may pause this job's service. With `true`, a `fixed`\nbreak, a `windowed` break or a duty-`triggered` break that falls\ninside the service pauses it: the work resumes when the break ends,\nthe job departs the break's length later, and the stop reports the\npaused seconds in `break_s`. A drive-`triggered` break never pauses a\njob (it counts driving time only). Default `false`: the whole service\nmoves after the break, or the break is taken before the job starts.","example":true,"uniqueKey":"problem.jobs.items.[INDEX].break_interruptible.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].break_interruptible","typeLabel":"boolean | null"},"delivery_load":{"oneOf":[{"type":"null","description":"Quantity delivered at this visit: comes off the vehicle here, having\nbeen loaded at a depot. Direction is carried by the field itself, never\nby sign — `delivery_load` values are non-negative magnitudes, like `pickup_load`.\n\nUnlike a shipment, nothing is picked up for it at another stop: the\ngoods are assumed already aboard from a depot, so the vehicle departs\nits trip carrying the sum of the trip's `delivery_load` quantities.\n\nAbsent or empty means no delivery at this visit.","uniqueKey":"problem.jobs.items.[INDEX].delivery_load.oneOf.0","typeLabel":"null"},{"type":"object","description":"Quantity delivered at this visit: comes off the vehicle here, having\nbeen loaded at a depot. Direction is carried by the field itself, never\nby sign — `delivery_load` values are non-negative magnitudes, like `pickup_load`.\n\nUnlike a shipment, nothing is picked up for it at another stop: the\ngoods are assumed already aboard from a depot, so the vehicle departs\nits trip carrying the sum of the trip's `delivery_load` quantities.\n\nAbsent or empty means no delivery at this visit.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].delivery_load.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.jobs.items.[INDEX].delivery_load.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.jobs.items.[INDEX].delivery_load","typeLabel":"null | object"},"drop_cost":{"oneOf":[{"type":"number","format":"double","description":"Drop **price** — what leaving this task unserved costs you, in the same\ncurrency as `objective.costs`, and the only way to make a task\ndroppable. Tasks without a `drop_cost` must be served.\n\nThis is money, not a priority: it enters the same cost the solver\nminimises, so the task is served only while serving it costs less than\ndropping it. Drop costs the plan chose to pay are reported in\n`score.components.drop_costs` and summed into `score.cost`.\n\nOn a shipment the drop cost applies to the pair, charged once.\n\nMust be finite, `>= 0` and at most `1e9`; combined with `priority` it\nis rejected with HTTP 400 (`conflicting_fields`). Also rejected with\nHTTP 400 (`not_supported`) while a positive `objective.per_delay_workday` is set,\nsince a droppable task could be dropped to avoid its delay charge.","example":25,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].drop_cost.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Drop **price** — what leaving this task unserved costs you, in the same\ncurrency as `objective.costs`, and the only way to make a task\ndroppable. Tasks without a `drop_cost` must be served.\n\nThis is money, not a priority: it enters the same cost the solver\nminimises, so the task is served only while serving it costs less than\ndropping it. Drop costs the plan chose to pay are reported in\n`score.components.drop_costs` and summed into `score.cost`.\n\nOn a shipment the drop cost applies to the pair, charged once.\n\nMust be finite, `>= 0` and at most `1e9`; combined with `priority` it\nis rejected with HTTP 400 (`conflicting_fields`). Also rejected with\nHTTP 400 (`not_supported`) while a positive `objective.per_delay_workday` is set,\nsince a droppable task could be dropped to avoid its delay charge.","example":25,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].drop_cost.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].drop_cost","typeLabel":"number\u003cdouble> | null"},"eligible_vehicles":{"oneOf":[{"type":"null","description":"Hard vehicle allow/exclude. A request may use at most 256 distinct\npermitted-vehicle sets (after resolving `allowed`/`excluded`) across\nall jobs and shipments (HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.0","typeLabel":"null"},{"type":"object","description":"Hard vehicle allow/exclude. A request may use at most 256 distinct\npermitted-vehicle sets (after resolving `allowed`/`excluded`) across\nall jobs and shipments (HTTP 400 `limit_exceeded` beyond that).","example":{"allowed":["v1","v2"]},"properties":{"allowed":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Hard whitelist of vehicle ids. Omit = all vehicles allowed. An empty\nlist, or an id that names no vehicle, is rejected with HTTP 400.","minItems":1,"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Hard whitelist of vehicle ids. Omit = all vehicles allowed. An empty\nlist, or an id that names no vehicle, is rejected with HTTP 400.","minItems":1,"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.allowed","typeLabel":"string[] | null"},"excluded":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Hard blacklist of vehicle ids. Mutually exclusive with `allowed`. An\nid that names no vehicle is rejected with HTTP 400.","uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Hard blacklist of vehicle ids. Mutually exclusive with `allowed`. An\nid that names no vehicle is rejected with HTTP 400.","uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1.excluded","typeLabel":"string[] | null"}},"additionalProperties":false,"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.jobs.items.[INDEX].eligible_vehicles","typeLabel":"null | object"},"location":{"oneOf":[{"type":"null","description":"Where this visit happens. Omit for a \"virtual\" (location-less) job:\nit still has service duration, time windows, load, and skills, but\nrequires no travel — the vehicle's position doesn't change when it\nserves one. Virtual and located jobs may be mixed freely in the same\nrequest and route. A virtual job's stop in the solution response\nreports the resolved location of its nearest real (located)\nneighbor in the route — the predecessor when there is one, otherwise\nthe successor — so it is `null` only on a route that has no located\nstop at all (an all-virtual route on an open-start/open-end shift).\nA shipment's legs still require a `location`.","uniqueKey":"problem.jobs.items.[INDEX].location.oneOf.0","typeLabel":"null"},{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.jobs.items.[INDEX].location.oneOf.1.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"Where this visit happens. Omit for a \"virtual\" (location-less) job:\nit still has service duration, time windows, load, and skills, but\nrequires no travel — the vehicle's position doesn't change when it\nserves one. Virtual and located jobs may be mixed freely in the same\nrequest and route. A virtual job's stop in the solution response\nreports the resolved location of its nearest real (located)\nneighbor in the route — the predecessor when there is one, otherwise\nthe successor — so it is `null` only on a route that has no located\nstop at all (an all-virtual route on an open-start/open-end shift).\nA shipment's legs still require a `location`.","maxItems":2,"minItems":2,"example":[3.725,51.05],"uniqueKey":"problem.jobs.items.[INDEX].location.oneOf.1","typeLabel":"number\u003cdouble>[]"}],"uniqueKey":"problem.jobs.items.[INDEX].location","typeLabel":"null | number\u003cdouble>[]"},"pickup_load":{"oneOf":[{"type":"null","description":"Quantity picked up at this visit: goes onto the vehicle here and stays\naboard until the route ends or reloads. Non-negative magnitudes per\nnamed dimension. A swap that collects one quantity and drops off\nanother at the same address is one job with both `pickup_load` and\n`delivery_load`.","uniqueKey":"problem.jobs.items.[INDEX].pickup_load.oneOf.0","typeLabel":"null"},{"type":"object","description":"Quantity picked up at this visit: goes onto the vehicle here and stays\naboard until the route ends or reloads. Non-negative magnitudes per\nnamed dimension. A swap that collects one quantity and drops off\nanother at the same address is one job with both `pickup_load` and\n`delivery_load`.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].pickup_load.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.jobs.items.[INDEX].pickup_load.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.jobs.items.[INDEX].pickup_load","typeLabel":"null | object"},"preferences":{"oneOf":[{"type":"array","items":{"type":"object","description":"A soft vehicle affinity preference, priced.","required":["vehicle","violation_cost"],"properties":{"vehicle":{"type":"string","description":"Preferred vehicle id. An id that names no vehicle, or a vehicle listed\ntwice in one task's `preferences`, is rejected with HTTP 400.","example":"v1","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].preferences.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a different vehicle\nserves the job. Must be finite and `>= 0`.","example":50,"maximum":21474.83647,"minimum":0,"isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].preferences.oneOf.0.items.[INDEX].violation_cost","typeLabel":"number\u003cdouble>"}},"additionalProperties":false,"example":{"vehicle":"v1","violation_cost":50},"uniqueKey":"problem.jobs.items.[INDEX].preferences.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Soft vehicle affinity preferences, priced. Each entry is independent:\na job listing several preferred vehicles it doesn't get pays each\none's `violation_cost` (compounding, the same rule as a vehicle's\n`preferred_tags`).","uniqueKey":"problem.jobs.items.[INDEX].preferences.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A soft vehicle affinity preference, priced.","required":["vehicle","violation_cost"],"properties":{"vehicle":{"type":"string","description":"Preferred vehicle id. An id that names no vehicle, or a vehicle listed\ntwice in one task's `preferences`, is rejected with HTTP 400.","example":"v1"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a different vehicle\nserves the job. Must be finite and `>= 0`.","example":50,"maximum":21474.83647,"minimum":0}},"additionalProperties":false,"example":{"vehicle":"v1","violation_cost":50}},"description":"Soft vehicle affinity preferences, priced. Each entry is independent:\na job listing several preferred vehicles it doesn't get pays each\none's `violation_cost` (compounding, the same rule as a vehicle's\n`preferred_tags`).","uniqueKey":"problem.jobs.items.[INDEX].preferences.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].preferences","typeLabel":"object[] | null"},"priority":{"oneOf":[{"type":"integer","format":"int32","description":"Importance of a must-serve task when not all of them fit: the solver\nmaximises the summed `priority` of served tasks before any cost. `>= 1`,\ndefault `1` (maximise the count). A rank, not money — it never makes a\ntask droppable; use `drop_cost` for that. Both set is a 400.","example":3,"minimum":1,"uniqueKey":"problem.jobs.items.[INDEX].priority.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Importance of a must-serve task when not all of them fit: the solver\nmaximises the summed `priority` of served tasks before any cost. `>= 1`,\ndefault `1` (maximise the count). A rank, not money — it never makes a\ntask droppable; use `drop_cost` for that. Both set is a 400.","example":3,"minimum":1,"uniqueKey":"problem.jobs.items.[INDEX].priority.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].priority","typeLabel":"integer\u003cint32> | null"},"required_skills":{"oneOf":[{"type":"array","items":{"type":"object","description":"A hard skill requirement — the assigned vehicle must provide it.","required":["name"],"properties":{"name":{"type":"string","description":"Skill name the assigned vehicle must provide.","example":"fridge","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0.items.[INDEX].name","typeLabel":"string"},"min_level":{"oneOf":[{"type":"integer","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1,"uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1,"uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"name":"fridge"},"uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Hard skill requirements — the assigned vehicle must provide every one,\nat or above each requirement's `min_level`. A request may use at most\n256 distinct `(name, min_level)` pairs across all jobs and shipments\n(HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A hard skill requirement — the assigned vehicle must provide it.","required":["name"],"properties":{"min_level":{"oneOf":[{"type":"integer","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1},{"type":"null","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1}]},"name":{"type":"string","description":"Skill name the assigned vehicle must provide.","example":"fridge"}},"additionalProperties":false,"example":{"name":"fridge"}},"description":"Hard skill requirements — the assigned vehicle must provide every one,\nat or above each requirement's `min_level`. A request may use at most\n256 distinct `(name, min_level)` pairs across all jobs and shipments\n(HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.jobs.items.[INDEX].required_skills.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].required_skills","typeLabel":"object[] | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].service_duration_s","typeLabel":"integer\u003cint32> | null"},"service_factors":{"oneOf":[{"type":"array","items":{"type":"object","description":"Per-vehicle work-rate override for one task's `service_duration_s`.","required":["vehicle","factor"],"properties":{"factor":{"type":"number","format":"double","description":"Work-rate factor of `vehicle` on this task. Service time is DIVIDED by\nit: above `1` the vehicle works faster here, below `1` slower; `1.0` is a\nno-op. It multiplies the vehicle's own rate (the shift's\n`service_factor` if set, else the vehicle's): effective service time =\n`service_duration_s / (shift_or_vehicle_factor * factor)`. Same\ndirection and `[0.001, 5]` range as `vehicles[].service_factor`. V2's\n`proficiency.durationModifier` multiplied duration instead; the V2\ncompatibility layer sends its inverse (`1 / durationModifier`) here.","example":1.25,"maximum":5,"minimum":0.001,"isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].service_factors.oneOf.0.items.[INDEX].factor","typeLabel":"number\u003cdouble>"},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle.","example":"v1","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].service_factors.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"}},"additionalProperties":false,"example":{"factor":1.25,"vehicle":"v1"},"uniqueKey":"problem.jobs.items.[INDEX].service_factors.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Per-vehicle work-rate factors for this task's `service_duration_s`,\nwhich is DIVIDED by the factor (above `1` = faster). Each multiplies\nthe serving vehicle's rate (the shift's `service_factor` if set, else\nthe vehicle's): effective service time = `service_duration_s /\n(shift_or_vehicle_factor * factor)`. On a shipment the factor scales\nboth legs. A vehicle not listed works at its own rate.","uniqueKey":"problem.jobs.items.[INDEX].service_factors.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Per-vehicle work-rate override for one task's `service_duration_s`.","required":["vehicle","factor"],"properties":{"factor":{"type":"number","format":"double","description":"Work-rate factor of `vehicle` on this task. Service time is DIVIDED by\nit: above `1` the vehicle works faster here, below `1` slower; `1.0` is a\nno-op. It multiplies the vehicle's own rate (the shift's\n`service_factor` if set, else the vehicle's): effective service time =\n`service_duration_s / (shift_or_vehicle_factor * factor)`. Same\ndirection and `[0.001, 5]` range as `vehicles[].service_factor`. V2's\n`proficiency.durationModifier` multiplied duration instead; the V2\ncompatibility layer sends its inverse (`1 / durationModifier`) here.","example":1.25,"maximum":5,"minimum":0.001},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle.","example":"v1"}},"additionalProperties":false,"example":{"factor":1.25,"vehicle":"v1"}},"description":"Per-vehicle work-rate factors for this task's `service_duration_s`,\nwhich is DIVIDED by the factor (above `1` = faster). Each multiplies\nthe serving vehicle's rate (the shift's `service_factor` if set, else\nthe vehicle's): effective service time = `service_duration_s /\n(shift_or_vehicle_factor * factor)`. On a shipment the factor scales\nboth legs. A vehicle not listed works at its own rate.","uniqueKey":"problem.jobs.items.[INDEX].service_factors.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].service_factors","typeLabel":"object[] | null"},"setup_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].setup_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].setup_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].setup_duration_s","typeLabel":"integer\u003cint32> | null"},"tags":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.jobs.items.[INDEX].tags.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Free-form task labels (zones/territories, relation labels).\nUsed for `tag`/relation resolution and, when a shift scopes itself via\n`serves_tags` (hard ANY-overlap) or a vehicle prices them via\n`preferred_tags` (soft), for tag matching. ANY-overlap — contrast with\n`required_skills`, which requires ALL. Not capability matching on its own.\nA request may carry at most 256 distinct tags across all jobs and\nshipments (HTTP 400 `limit_exceeded` beyond that); vehicle-side tag\nlists do not count.","uniqueKey":"problem.jobs.items.[INDEX].tags.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Free-form task labels (zones/territories, relation labels).\nUsed for `tag`/relation resolution and, when a shift scopes itself via\n`serves_tags` (hard ANY-overlap) or a vehicle prices them via\n`preferred_tags` (soft), for tag matching. ANY-overlap — contrast with\n`required_skills`, which requires ALL. Not capability matching on its own.\nA request may carry at most 256 distinct tags across all jobs and\nshipments (HTTP 400 `limit_exceeded` beyond that); vehicle-side tag\nlists do not count.","uniqueKey":"problem.jobs.items.[INDEX].tags.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].tags","typeLabel":"string[] | null"},"target":{"oneOf":[{"type":"null","description":"Soft target for this task, measured at its arrival (default) or\ndeparture. On a shipment it is measured on the **delivery** leg.","uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.0","typeLabel":"null"},{"type":"object","description":"Soft target for this task, measured at its arrival (default) or\ndeparture. On a shipment it is measured on the **delivery** leg.","required":["at","per_late_hour"],"example":{"at":"2026-07-01T10:00:00+02:00","on":"arrival","per_late_hour":60},"properties":{"at":{"type":"string","format":"date-time","description":"Target instant (RFC 3339, UTC offset required) the `on` instant is measured against.","example":"2026-07-01T10:00:00+02:00","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1.at","typeLabel":"string\u003cdate-time>"},"per_late_hour":{"type":"number","format":"double","description":"Cost, in the objective's currency, per hour of `on` beyond `at`\n(linear, prorated per second). Must be `> 0`; independent of\n`objective.per_late_hour` (which prices *time-window* lateness,\nnot a target point).","example":60,"maximum":21474.83647,"minimum":0.00001,"isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1.per_late_hour","typeLabel":"number\u003cdouble>"},"on":{"oneOf":[{"type":"null","description":"Which instant of the task is compared to `at`: `arrival` (default) or\n`departure`, the stop fields of the same names.","default":"arrival","uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1.on.oneOf.0","typeLabel":"null"},{"type":"string","description":"Which instant of the task is compared to `at`: `arrival` (default) or\n`departure`, the stop fields of the same names.","default":"arrival","enum":["arrival","departure"],"uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1.on.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1.on","typeLabel":"null | enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.jobs.items.[INDEX].target.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.jobs.items.[INDEX].target","typeLabel":"null | object"},"time_windows":{"oneOf":[{"type":"array","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].from","typeLabel":"string\u003cdate-time>"},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00","isRequired":true,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].to","typeLabel":"string\u003cdate-time>"},"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].choice_cost","typeLabel":"number\u003cdouble> | null"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX].per_late_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"},"uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Time windows for this visit.","uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0}]},"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006}]},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}},"description":"Time windows for this visit.","uniqueKey":"problem.jobs.items.[INDEX].time_windows.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.jobs.items.[INDEX].time_windows","typeLabel":"object[] | null"}},"additionalProperties":false,"example":{"id":"job-1","location":[3.725,51.05],"pickup_load":{"weight":20},"required_skills":[{"name":"fridge"}],"service_duration_s":300,"time_windows":[{"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}]},"uniqueKey":"problem.jobs.items.[INDEX]","typeLabel":"object"},"description":"Single-stop visits to serve. At most 10,000 tasks per request, `jobs`\nand `shipments` combined (HTTP 400 `limit_exceeded` beyond that).","maxItems":10000,"uniqueKey":"problem.jobs","typeLabel":"object[]"},"objective":{"oneOf":[{"type":"null","description":"Objective configuration.","uniqueKey":"problem.objective.oneOf.0","typeLabel":"null"},{"type":"object","description":"Objective configuration.","example":{"costs":{"per_route_hour":35,"per_travel_km":0.2},"currency":"EUR"},"properties":{"costs":{"oneOf":[{"type":"null","description":"Fleet cost rates: the default for every vehicle and shift that does\nnot set its own. See the `Costs` schema.","uniqueKey":"problem.objective.oneOf.1.costs.oneOf.0","typeLabel":"null"},{"type":"object","description":"Fleet cost rates: the default for every vehicle and shift that does\nnot set its own. See the `Costs` schema.","example":{"per_route":50,"per_route_hour":35,"per_travel_km":0.2},"properties":{"per_overtime_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour a route finishes past its shift's `to` (possible only with\n`max_overtime_s`), reported in `score.components.overtime`, on top of\n`per_route_hour`. Default `0`: overtime is unpriced.","example":0,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_overtime_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour a route finishes past its shift's `to` (possible only with\n`max_overtime_s`), reported in `score.components.overtime`, on top of\n`per_route_hour`. Default `0`: overtime is unpriced.","example":0,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_overtime_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_overtime_hour","typeLabel":"number\u003cdouble> | null"},"per_route":{"oneOf":[{"type":"number","format":"double","description":"Flat charge for each used shift (a route with at least one task),\nreported in `score.components.routes`. Default `0`. The higher it is,\nthe more travel the solver accepts to avoid opening another route. It\ncounts shifts, not vehicles: a vehicle that works five days pays it five\ntimes, so it does not prefer one vehicle on two shifts over two vehicles\non one shift each; use `per_used_vehicle` for that.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Flat charge for each used shift (a route with at least one task),\nreported in `score.components.routes`. Default `0`. The higher it is,\nthe more travel the solver accepts to avoid opening another route. It\ncounts shifts, not vehicles: a vehicle that works five days pays it five\ntimes, so it does not prefer one vehicle on two shifts over two vehicles\non one shift each; use `per_used_vehicle` for that.","example":50,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route","typeLabel":"number\u003cdouble> | null"},"per_route_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour of each route's wall-clock span (travel, service, waiting\nand breaks), reported in `score.components.time`. Default **35** at objective\nlevel; a vehicle or shift value inherits the fleet value.","example":35,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour of each route's wall-clock span (travel, service, waiting\nand breaks), reported in `score.components.time`. Default **35** at objective\nlevel; a vehicle or shift value inherits the fleet value.","example":35,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_route_hour","typeLabel":"number\u003cdouble> | null"},"per_travel_km":{"oneOf":[{"type":"number","format":"double","description":"Per kilometre driven, reported in `score.components.distance`.\nDefault **0.20** at objective level; a vehicle or shift value inherits the\nfleet value.","example":0.2,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_travel_km.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per kilometre driven, reported in `score.components.distance`.\nDefault **0.20** at objective level; a vehicle or shift value inherits the\nfleet value.","example":0.2,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_travel_km.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_travel_km","typeLabel":"number\u003cdouble> | null"},"per_used_vehicle":{"oneOf":[{"type":"number","format":"double","description":"Flat charge once per vehicle that serves at least one task, however\nmany of its shifts it works. Reported in `score.components.vehicles`.\nAdds to `per_route`: the vehicle's first used shift pays both, later\nshifts only `per_route`. Default `0`. Use it to minimise distinct\nvehicles; use `per_route` to price each working day. Not accepted on\n`shifts[].costs`. When any vehicle has a non-zero rate and any vehicle\nhas several shifts, the problem solves without decomposition.","example":400,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_used_vehicle.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Flat charge once per vehicle that serves at least one task, however\nmany of its shifts it works. Reported in `score.components.vehicles`.\nAdds to `per_route`: the vehicle's first used shift pays both, later\nshifts only `per_route`. Default `0`. Use it to minimise distinct\nvehicles; use `per_route` to price each working day. Not accepted on\n`shifts[].costs`. When any vehicle has a non-zero rate and any vehicle\nhas several shifts, the problem solves without decomposition.","example":400,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_used_vehicle.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_used_vehicle","typeLabel":"number\u003cdouble> | null"},"per_wait_hour":{"oneOf":[{"type":"number","format":"double","description":"Per hour spent waiting for a time window to open, reported in\n`score.components.waiting`, on top of `per_route_hour` (the span\nincludes the wait). Idle before a windowed break's window opens is\nreported in `wait_s` but not charged here. Default `0`.","example":0,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_wait_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Per hour spent waiting for a time window to open, reported in\n`score.components.waiting`, on top of `per_route_hour` (the span\nincludes the wait). Idle before a windowed break's window opens is\nreported in `wait_s` but not charged here. Default `0`.","example":0,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_wait_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1.per_wait_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"problem.objective.oneOf.1.costs.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.objective.oneOf.1.costs","typeLabel":"null | object"},"currency":{"oneOf":[{"type":"string","description":"Currency label (ISO 4217, e.g. `EUR`) for every amount in the request\nand in `score`. Informational: echoed as `score.currency`, it never\nconverts anything.","example":"EUR","uniqueKey":"problem.objective.oneOf.1.currency.oneOf.0","typeLabel":"string"},{"type":"null","description":"Currency label (ISO 4217, e.g. `EUR`) for every amount in the request\nand in `score`. Informational: echoed as `score.currency`, it never\nconverts anything.","example":"EUR","uniqueKey":"problem.objective.oneOf.1.currency.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.currency","typeLabel":"string | null"},"grouping":{"oneOf":[{"type":"null","description":"Job-proximity cluster cohesion. See the `Grouping` schema.","uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.0","typeLabel":"null"},{"type":"object","description":"Job-proximity cluster cohesion. See the `Grouping` schema.","required":["per_entry"],"example":{"distance_metric":"straight_line","per_entry":0.5,"radius_m":180},"properties":{"per_entry":{"type":"number","format":"double","description":"Cost added to the objective on every entry into a group from a job\noutside it (a job that is not within `radius_m` of the entered one),\nthe first entry included, in the objective's currency. Entry from the\nshift's start or from a reload is free. At most 1000 currency units: a\nlarger value is rejected with HTTP 400. Higher keeps clusters together\nmore aggressively at the expense of total travel.","example":0.5,"maximum":1000,"minimum":0,"isRequired":true,"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.per_entry","typeLabel":"number\u003cdouble>"},"distance_metric":{"oneOf":[{"type":"null","description":"How neighbour distance is measured. Default `\"straight_line\"`.","default":"straight_line","uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.distance_metric.oneOf.0","typeLabel":"null"},{"type":"string","description":"How neighbour distance is measured. Default `\"straight_line\"`.","default":"straight_line","enum":["straight_line","road"],"example":"straight_line","uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.distance_metric.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.distance_metric","typeLabel":"null | enum\u003cstring>"},"radius_m":{"oneOf":[{"type":"integer","format":"int32","description":"Radius defining a group, in metres. Default `180`. Must be `> 0`.","default":180,"example":180,"minimum":1,"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.radius_m.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Radius defining a group, in metres. Default `180`. Must be `> 0`.","default":180,"example":180,"minimum":1,"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.radius_m.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1.radius_m","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"uniqueKey":"problem.objective.oneOf.1.grouping.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.objective.oneOf.1.grouping","typeLabel":"null | object"},"per_delay_workday":{"oneOf":[{"type":"number","format":"double","description":"ASAP scheduling: money charged for each served task per workday its\nshift lies after the earliest workday in the request, in the request's\ncurrency. A workday is a distinct calendar date, in the shift's own UTC\noffset, on which at least one shift starts; shifts on one date share a\nrank, and a date with no shift adds none. Unserved tasks pay nothing;\nthe charge never outranks `priority` and cannot be combined with\n`drop_cost`. Absent or `0` = off; a single-date request is charged\nnothing. A problem that sets it, even on one date, solves without\ndecomposition, like `assignment_costs`. Reported as `score.components.delay`. A positive\nrate below `0.00001` is rejected, as is a rate whose total over the\nlater workdays exceeds `21474.83647` (`out_of_range`).","example":5,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.per_delay_workday.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"ASAP scheduling: money charged for each served task per workday its\nshift lies after the earliest workday in the request, in the request's\ncurrency. A workday is a distinct calendar date, in the shift's own UTC\noffset, on which at least one shift starts; shifts on one date share a\nrank, and a date with no shift adds none. Unserved tasks pay nothing;\nthe charge never outranks `priority` and cannot be combined with\n`drop_cost`. Absent or `0` = off; a single-date request is charged\nnothing. A problem that sets it, even on one date, solves without\ndecomposition, like `assignment_costs`. Reported as `score.components.delay`. A positive\nrate below `0.00001` is rejected, as is a rate whose total over the\nlater workdays exceeds `21474.83647` (`out_of_range`).","example":5,"minimum":0,"uniqueKey":"problem.objective.oneOf.1.per_delay_workday.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.per_delay_workday","typeLabel":"number\u003cdouble> | null"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Cost per hour of lateness: the default rate for every task window\nthat does not carry its own `time_windows[].per_late_hour`. Omit for\nhard windows. An explicit `0.0` is rejected as ambiguous (free\nlateness and hard windows read opposite ways, and lateness is never\nfree). There is no earliness rate. It prices task windows only: a\nshift's `to` (plus `max_overtime_s` when set) stays a hard limit.\nSetting it `> 0` alongside a nonzero `time_windows[].choice_cost` anywhere in\nthe request is rejected with HTTP 400.","example":60,"minimum":0.0006,"uniqueKey":"problem.objective.oneOf.1.per_late_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Cost per hour of lateness: the default rate for every task window\nthat does not carry its own `time_windows[].per_late_hour`. Omit for\nhard windows. An explicit `0.0` is rejected as ambiguous (free\nlateness and hard windows read opposite ways, and lateness is never\nfree). There is no earliness rate. It prices task windows only: a\nshift's `to` (plus `max_overtime_s` when set) stays a hard limit.\nSetting it `> 0` alongside a nonzero `time_windows[].choice_cost` anywhere in\nthe request is rejected with HTTP 400.","example":60,"minimum":0.0006,"uniqueKey":"problem.objective.oneOf.1.per_late_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.per_late_hour","typeLabel":"number\u003cdouble> | null"},"workload_share":{"oneOf":[{"type":"null","description":"Spreads work across vehicles. See the `WorkloadShare` schema.","uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.0","typeLabel":"null"},{"type":"object","description":"Spreads work across vehicles. See the `WorkloadShare` schema.","required":["per_imbalance_hour"],"properties":{"per_imbalance_hour":{"type":"number","format":"double","description":"Money per hour a vehicle's service time is outside the band, in the\nrequest's currency. Greater than 0 and at least 0.036 (the internal\nresolution); omit `workload_share` to switch the term off.","example":35,"exclusiveMinimum":0,"isRequired":true,"uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.1.per_imbalance_hour","typeLabel":"number\u003cdouble>"},"tolerance":{"oneOf":[{"type":"number","format":"double","description":"Half-width of the band as a fraction of the vehicle's share, `0` up to\nbut not including `1`. Default `0.1`: a vehicle within 10% of its share\nis not charged. The charge grows from the band edge.","example":0.1,"minimum":0,"exclusiveMaximum":1,"uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.1.tolerance.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Half-width of the band as a fraction of the vehicle's share, `0` up to\nbut not including `1`. Default `0.1`: a vehicle within 10% of its share\nis not charged. The charge grows from the band edge.","example":0.1,"minimum":0,"exclusiveMaximum":1,"uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.1.tolerance.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.1.tolerance","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"problem.objective.oneOf.1.workload_share.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.objective.oneOf.1.workload_share","typeLabel":"null | object"}},"additionalProperties":false,"uniqueKey":"problem.objective.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.objective","typeLabel":"null | object"},"quotas":{"type":"array","items":{"type":"object","description":"A hard cap on how many stops of `tasks` the `vehicles` serve together\nin a window. A stop counts when its service starts in `[from, to)`\n(`arrival + wait_s` in the response when no windowed break is taken on\narrival there); without a window every stop counts.\nStops count as `max_stops` counts them: a job one, a shipment two. An\nover-cap job is left unassigned. Unlike `limits.periods[]`, which counts a\nshift by its start, a quota has no `every` recurrence and caps only stop\ncounts.","required":["id","vehicles","tasks","max_stops"],"properties":{"id":{"type":"string","description":"Quota id: 1 to 128 characters, unique among `quotas`; named in the\n`/evaluate` `quota` violation.","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.quotas.items.[INDEX].id","typeLabel":"string"},"max_stops":{"type":"integer","format":"int32","description":"The cap on counted stops; a job counts as one stop.\nStart, end, break and reload stops in `routes[].stops` do not count; a\nshipment counts as two stops.","minimum":0,"isRequired":true,"uniqueKey":"problem.quotas.items.[INDEX].max_stops","typeLabel":"integer\u003cint32>"},"tasks":{"type":"array","items":{"type":"string","uniqueKey":"problem.quotas.items.[INDEX].tasks.items.[INDEX]","typeLabel":"string"},"description":"Job or shipment ids whose stops count, each at most once. At least\none; an id that names no job or shipment is rejected with HTTP 400.","minItems":1,"isRequired":true,"uniqueKey":"problem.quotas.items.[INDEX].tasks","typeLabel":"string[]"},"vehicles":{"type":"array","items":{"type":"string","uniqueKey":"problem.quotas.items.[INDEX].vehicles.items.[INDEX]","typeLabel":"string"},"description":"Vehicle ids that share the cap, each at most once. At least one; an id\nthat names no vehicle is rejected with HTTP 400.","minItems":1,"isRequired":true,"uniqueKey":"problem.quotas.items.[INDEX].vehicles","typeLabel":"string[]"},"from":{"oneOf":[{"type":"string","format":"date-time","description":"Window start (RFC 3339, UTC offset required), with `to`. The window\nmust overlap a shift of one of `vehicles` (counting its\n`max_overtime_s`), else the request is rejected with HTTP 400.","example":"2026-10-05T00:00:00+02:00","uniqueKey":"problem.quotas.items.[INDEX].from.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Window start (RFC 3339, UTC offset required), with `to`. The window\nmust overlap a shift of one of `vehicles` (counting its\n`max_overtime_s`), else the request is rejected with HTTP 400.","example":"2026-10-05T00:00:00+02:00","uniqueKey":"problem.quotas.items.[INDEX].from.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.quotas.items.[INDEX].from","typeLabel":"string\u003cdate-time> | null"},"to":{"oneOf":[{"type":"string","format":"date-time","description":"Window end (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-06T00:00:00+02:00","uniqueKey":"problem.quotas.items.[INDEX].to.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Window end (RFC 3339, UTC offset required, exclusive), with `from`.","example":"2026-10-06T00:00:00+02:00","uniqueKey":"problem.quotas.items.[INDEX].to.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.quotas.items.[INDEX].to","typeLabel":"string\u003cdate-time> | null"}},"additionalProperties":false,"example":{"id":"pool-install","max_stops":2,"tasks":["j1","j2","j3"],"vehicles":["c0","c1"]},"uniqueKey":"problem.quotas.items.[INDEX]","typeLabel":"object"},"description":"Stop caps shared by a set of vehicles. At most 65,535.","maxItems":65535,"uniqueKey":"problem.quotas","typeLabel":"object[]"},"relations":{"oneOf":[{"type":"array","items":{"oneOf":[{"type":"object","title":"Sequence","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.0.stops.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids (`pickup.id` / `delivery.id`, by\ndefault `\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`), in the\norder they must be served. A shipment's own id is\nrejected with HTTP 400 `not_supported`.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.0.stops","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `sequence`.","enum":["sequence"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.0.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.0","typeLabel":"Sequence · object"},{"type":"object","title":"Consecutive","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.1.stops.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids, in the order they must be served\nback to back. At least 2. A stop has one successor and one predecessor\nacross all `consecutive` relations, so `[a, b]` and `[b, c]` may\noverlap but `[a, b]` and `[a, c]` may not. A shipment's own id is rejected with HTTP\n400 `not_supported`.","minItems":2,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.1.stops","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `consecutive`.","enum":["consecutive"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.1.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.1","typeLabel":"Consecutive · object"},{"type":"object","title":"Tag order","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["tags","type"],"example":{"type":"sequence"},"properties":{"tags":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.2.tags.items.[INDEX]","typeLabel":"string"},"description":"Tag labels in precedence order. Requires at least 2 entries.","minItems":2,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.2.tags","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `tag_order`.","enum":["tag_order"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.2.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.2","typeLabel":"Tag order · object"},{"type":"object","title":"Same vehicle","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.stops.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.stops","typeLabel":"string[] | null"},"type":{"type":"string","description":"Discriminator: always `same_vehicle`.","enum":["same_vehicle"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.type","typeLabel":"enum\u003cstring>"},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.tag.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3.tag","typeLabel":"string | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.3","typeLabel":"Same vehicle · object"},{"type":"object","title":"Same vehicle","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.tag.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.tag","typeLabel":"string | null"},"type":{"type":"string","description":"Discriminator: always `same_vehicle`.","enum":["same_vehicle"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.type","typeLabel":"enum\u003cstring>"},"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4.stops","typeLabel":"string[] | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.4","typeLabel":"Same vehicle · object"},{"type":"object","title":"Same day","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.stops.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.stops","typeLabel":"string[] | null"},"type":{"type":"string","description":"Discriminator: always `same_day`.","enum":["same_day"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.type","typeLabel":"enum\u003cstring>"},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.tag.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5.tag","typeLabel":"string | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.5","typeLabel":"Same day · object"},{"type":"object","title":"Same day","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.tag.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.tag","typeLabel":"string | null"},"type":{"type":"string","description":"Discriminator: always `same_day`.","enum":["same_day"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.type","typeLabel":"enum\u003cstring>"},"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6.stops","typeLabel":"string[] | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.6","typeLabel":"Same day · object"},{"type":"object","title":"Same route","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400.","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.stops.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.stops","typeLabel":"string[] | null"},"type":{"type":"string","description":"Discriminator: always `same_route`.","enum":["same_route"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.type","typeLabel":"enum\u003cstring>"},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.tag.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7.tag","typeLabel":"string | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.7","typeLabel":"Same route · object"},{"type":"object","title":"Same route","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.tag.oneOf.0","typeLabel":"string"},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`).","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.tag.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.tag","typeLabel":"string | null"},"type":{"type":"string","description":"Discriminator: always `same_route`.","enum":["same_route"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.type","typeLabel":"enum\u003cstring>"},"stops":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.stops.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.stops.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400.","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.stops.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8.stops","typeLabel":"string[] | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.8","typeLabel":"Same route · object"},{"type":"object","title":"Synchronized","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["max_spread_s","stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"max_spread_s":{"type":"integer","format":"int64","description":"Maximum spread between the synchronized instants in seconds\n(`0` = exact simultaneity). Required. A negative value, or one that\ndoes not fit in 32 bits, is rejected with HTTP 400 `out_of_range`.","maximum":2147483647,"minimum":0,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.max_spread_s","typeLabel":"integer\u003cint64>"},"stops":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.stops.items.[INDEX]","typeLabel":"string"},"description":"Participating job ids, at most 8 (HTTP 400 `limit_exceeded`\nbeyond that). A shipment-leg stop id is rejected with HTTP 400;\na shipment's own id with HTTP 400 `not_supported`.","maxItems":8,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.stops","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `synchronized`.","enum":["synchronized"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.type","typeLabel":"enum\u003cstring>"},"on":{"oneOf":[{"type":"null","description":"Which instant is synchronized: `service_start` (default) or\n`departure` (the service end), the stop fields of the same names.","default":"service_start","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.on.oneOf.0","typeLabel":"null"},{"type":"string","description":"Which instant is synchronized: `service_start` (default) or\n`departure` (the service end), the stop fields of the same names.","default":"service_start","enum":["service_start","departure"],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.on.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9.on","typeLabel":"null | enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.9","typeLabel":"Synchronized · object"},{"type":"object","title":"Time lag","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["from","to","type"],"example":{"type":"sequence"},"properties":{"from":{"type":"object","description":"The reference end.","required":["stop"],"properties":{"stop":{"type":"string","description":"The stop: a job id. A shipment's own id or a shipment-leg stop id is\nrejected with HTTP 400.","example":"job-1","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.from.stop","typeLabel":"string"},"on":{"oneOf":[{"type":"null","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.from.on.oneOf.0","typeLabel":"null"},{"type":"string","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","enum":["service_start","departure"],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.from.on.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.from.on","typeLabel":"null | enum\u003cstring>"}},"additionalProperties":false,"example":{"on":"departure","stop":"job-1"},"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.from","typeLabel":"object"},"to":{"type":"object","description":"The bounded end.","required":["stop"],"properties":{"stop":{"type":"string","description":"The stop: a job id. A shipment's own id or a shipment-leg stop id is\nrejected with HTTP 400.","example":"job-1","isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.to.stop","typeLabel":"string"},"on":{"oneOf":[{"type":"null","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.to.on.oneOf.0","typeLabel":"null"},{"type":"string","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","enum":["service_start","departure"],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.to.on.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.to.on","typeLabel":"null | enum\u003cstring>"}},"additionalProperties":false,"example":{"on":"departure","stop":"job-1"},"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.to","typeLabel":"object"},"type":{"type":"string","description":"Discriminator: always `time_lag`.","enum":["time_lag"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.type","typeLabel":"enum\u003cstring>"},"max_s":{"oneOf":[{"type":"integer","format":"int64","description":"Upper bound on `t(to) − t(from)` in seconds. Absent = unbounded.\nMust fit in 32 bits and be `>= min_s` (HTTP 400 otherwise).","maximum":2147483647,"minimum":-2147483648,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.max_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Upper bound on `t(to) − t(from)` in seconds. Absent = unbounded.\nMust fit in 32 bits and be `>= min_s` (HTTP 400 otherwise).","maximum":2147483647,"minimum":-2147483648,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.max_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.max_s","typeLabel":"integer\u003cint64> | null"},"min_s":{"oneOf":[{"type":"integer","format":"int64","description":"Lower bound on `t(to) − t(from)` in seconds. Default `0`. Must fit\nin 32 bits.","default":0,"maximum":2147483647,"minimum":-2147483648,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.min_s.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"Lower bound on `t(to) − t(from)` in seconds. Default `0`. Must fit\nin 32 bits.","default":0,"maximum":2147483647,"minimum":-2147483648,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.min_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10.min_s","typeLabel":"integer\u003cint64> | null"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.10","typeLabel":"Time lag · object"},{"type":"object","title":"Compatible vehicles","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.11.stops.items.[INDEX]","typeLabel":"string"},"description":"Job ids, 2 to 16. A shipment's own id or a shipment-leg stop id\nis rejected with HTTP 400.","example":["job-1","job-2"],"maxItems":16,"minItems":2,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.11.stops","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `compatible_vehicles`.","enum":["compatible_vehicles"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.11.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.11","typeLabel":"Compatible vehicles · object"},{"type":"object","title":"All or none","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string","uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.12.stops.items.[INDEX]","typeLabel":"string"},"description":"Job ids, at least two. A shipment's own id or a shipment-leg stop id\nis rejected with HTTP 400.","example":["job-1","job-2"],"minItems":2,"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.12.stops","typeLabel":"string[]"},"type":{"type":"string","description":"Discriminator: always `all_or_none`.","enum":["all_or_none"],"isRequired":true,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.12.type","typeLabel":"enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.relations.oneOf.0.items.[INDEX].oneOf.12","typeLabel":"All or none · object"}],"uniqueKey":"problem.relations.oneOf.0.items.[INDEX]","typeLabel":"Sequence · object · Consecutive · object · Tag order · object · Same vehicle · object · Same vehicle · object · Same day · object · Same day · object · Same route · object · Same route · object · Synchronized · object · Time lag · object · Compatible vehicles · object · All or none · object"},"description":"Ordering, co-assignment and synchronization constraints.","uniqueKey":"problem.relations.oneOf.0","typeLabel":"Sequence · object · Consecutive · object · Tag order · object · Same vehicle · object · Same vehicle · object · Same day · object · Same day · object · Same route · object · Same route · object · Synchronized · object · Time lag · object · Compatible vehicles · object · All or none · object[]"},{"type":"null","items":{"oneOf":[{"type":"object","title":"Sequence","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids (`pickup.id` / `delivery.id`, by\ndefault `\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`), in the\norder they must be served. A shipment's own id is\nrejected with HTTP 400 `not_supported`."},"type":{"type":"string","description":"Discriminator: always `sequence`.","enum":["sequence"]}},"additionalProperties":false},{"type":"object","title":"Consecutive","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids, in the order they must be served\nback to back. At least 2. A stop has one successor and one predecessor\nacross all `consecutive` relations, so `[a, b]` and `[b, c]` may\noverlap but `[a, b]` and `[a, c]` may not. A shipment's own id is rejected with HTTP\n400 `not_supported`.","minItems":2},"type":{"type":"string","description":"Discriminator: always `consecutive`.","enum":["consecutive"]}},"additionalProperties":false},{"type":"object","title":"Tag order","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["tags","type"],"example":{"type":"sequence"},"properties":{"tags":{"type":"array","items":{"type":"string"},"description":"Tag labels in precedence order. Requires at least 2 entries.","minItems":2},"type":{"type":"string","description":"Discriminator: always `tag_order`.","enum":["tag_order"]}},"additionalProperties":false},{"type":"object","title":"Same vehicle","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_vehicle`.","enum":["same_vehicle"]}},"additionalProperties":false},{"type":"object","title":"Same vehicle","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_vehicle`.","enum":["same_vehicle"]}},"additionalProperties":false},{"type":"object","title":"Same day","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_day`.","enum":["same_day"]}},"additionalProperties":false},{"type":"object","title":"Same day","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with\nHTTP 400 `not_supported`."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_day`.","enum":["same_day"]}},"additionalProperties":false},{"type":"object","title":"Same route","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","stops"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_route`.","enum":["same_route"]}},"additionalProperties":false},{"type":"object","title":"Same route","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["type","tag"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"oneOf":[{"type":"array","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400."},{"type":"null","items":{"type":"string"},"description":"Job ids or shipment-leg stop ids in the relation (mutually\nexclusive with `tag`). A shipment's own id is rejected with HTTP\n400."}]},"tag":{"oneOf":[{"type":"string","description":"Tag selecting the relation members (mutually exclusive with `stops`)."},{"type":"null","description":"Tag selecting the relation members (mutually exclusive with `stops`)."}]},"type":{"type":"string","description":"Discriminator: always `same_route`.","enum":["same_route"]}},"additionalProperties":false},{"type":"object","title":"Synchronized","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["max_spread_s","stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"max_spread_s":{"type":"integer","format":"int64","description":"Maximum spread between the synchronized instants in seconds\n(`0` = exact simultaneity). Required. A negative value, or one that\ndoes not fit in 32 bits, is rejected with HTTP 400 `out_of_range`.","maximum":2147483647,"minimum":0},"on":{"oneOf":[{"type":"null","description":"Which instant is synchronized: `service_start` (default) or\n`departure` (the service end), the stop fields of the same names.","default":"service_start"},{"type":"string","description":"Which instant is synchronized: `service_start` (default) or\n`departure` (the service end), the stop fields of the same names.","default":"service_start","enum":["service_start","departure"]}]},"stops":{"type":"array","items":{"type":"string"},"description":"Participating job ids, at most 8 (HTTP 400 `limit_exceeded`\nbeyond that). A shipment-leg stop id is rejected with HTTP 400;\na shipment's own id with HTTP 400 `not_supported`.","maxItems":8},"type":{"type":"string","description":"Discriminator: always `synchronized`.","enum":["synchronized"]}},"additionalProperties":false},{"type":"object","title":"Time lag","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["from","to","type"],"example":{"type":"sequence"},"properties":{"from":{"type":"object","description":"The reference end.","required":["stop"],"properties":{"on":{"oneOf":[{"type":"null","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start"},{"type":"string","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","enum":["service_start","departure"]}]},"stop":{"type":"string","description":"The stop: a job id. A shipment's own id or a shipment-leg stop id is\nrejected with HTTP 400.","example":"job-1"}},"additionalProperties":false,"example":{"on":"departure","stop":"job-1"}},"max_s":{"oneOf":[{"type":"integer","format":"int64","description":"Upper bound on `t(to) − t(from)` in seconds. Absent = unbounded.\nMust fit in 32 bits and be `>= min_s` (HTTP 400 otherwise).","maximum":2147483647,"minimum":-2147483648},{"type":"null","format":"int64","description":"Upper bound on `t(to) − t(from)` in seconds. Absent = unbounded.\nMust fit in 32 bits and be `>= min_s` (HTTP 400 otherwise).","maximum":2147483647,"minimum":-2147483648}]},"min_s":{"oneOf":[{"type":"integer","format":"int64","description":"Lower bound on `t(to) − t(from)` in seconds. Default `0`. Must fit\nin 32 bits.","default":0,"maximum":2147483647,"minimum":-2147483648},{"type":"null","format":"int64","description":"Lower bound on `t(to) − t(from)` in seconds. Default `0`. Must fit\nin 32 bits.","default":0,"maximum":2147483647,"minimum":-2147483648}]},"to":{"type":"object","description":"The bounded end.","required":["stop"],"properties":{"on":{"oneOf":[{"type":"null","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start"},{"type":"string","description":"Which instant of the job the bound is measured at: `service_start`\n(default) or `departure`, the stop fields of the same names.","default":"service_start","enum":["service_start","departure"]}]},"stop":{"type":"string","description":"The stop: a job id. A shipment's own id or a shipment-leg stop id is\nrejected with HTTP 400.","example":"job-1"}},"additionalProperties":false,"example":{"on":"departure","stop":"job-1"}},"type":{"type":"string","description":"Discriminator: always `time_lag`.","enum":["time_lag"]}},"additionalProperties":false},{"type":"object","title":"Compatible vehicles","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string"},"description":"Job ids, 2 to 16. A shipment's own id or a shipment-leg stop id\nis rejected with HTTP 400.","example":["job-1","job-2"],"maxItems":16,"minItems":2},"type":{"type":"string","description":"Discriminator: always `compatible_vehicles`.","enum":["compatible_vehicles"]}},"additionalProperties":false},{"type":"object","title":"All or none","description":"A hard constraint between tasks, selected by `type`: `sequence`,\n`tag_order`, `same_vehicle`, `same_day`, `same_route`, `synchronized`,\n`time_lag`, `compatible_vehicles` or `all_or_none`.\nEach type carries only its own fields; any other `type` is rejected with\nHTTP 400.\n\nMembers are named by `stops` (job ids, or shipment-leg stop ids where\nthe type accepts them, see below). `same_vehicle`, `same_day` and\n`same_route` take **either** `stops` **or** a `tag`, not both. Every\nrelation is hard.\n\nA shipment takes part through its legs: `sequence`, `same_vehicle`,\n`same_day` and `same_route` accept a leg's stop id (`pickup.id` /\n`delivery.id`, by default `\"{shipment}:pickup\"` / `\":delivery\"`) and bind\nthat leg like a job. A leg coupled to other tasks by a `synchronized` or\n`time_lag` relation (directly, or through a `sequence` with a member that\nis) is rejected with HTTP 400, as is a `sequence` putting a delivery before\nits pickup. A shipment's own id in `stops`, or a shipment carrying the\n`tag` of a `same_vehicle` or `same_day` relation, is rejected with HTTP 400\n`not_supported`: relations never silently skip a member. `same_route`,\n`time_lag`, `compatible_vehicles`, `all_or_none` and `tag_order` reject a\nshipment with HTTP 400 as well.","required":["stops","type"],"example":{"stops":["job-1","job-2"],"type":"sequence"},"properties":{"stops":{"type":"array","items":{"type":"string"},"description":"Job ids, at least two. A shipment's own id or a shipment-leg stop id\nis rejected with HTTP 400.","example":["job-1","job-2"],"minItems":2},"type":{"type":"string","description":"Discriminator: always `all_or_none`.","enum":["all_or_none"]}},"additionalProperties":false}]},"description":"Ordering, co-assignment and synchronization constraints.","uniqueKey":"problem.relations.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.relations","typeLabel":"Sequence · object · Consecutive · object · Tag order · object · Same vehicle · object · Same vehicle · object · Same day · object · Same day · object · Same route · object · Same route · object · Synchronized · object · Time lag · object · Compatible vehicles · object · All or none · object[] | null"},"shipments":{"type":"array","items":{"type":"object","description":"A bound pickup→delivery shipment (the `shipments[]` entry type).\n\nTwo stops served by one vehicle, pickup strictly before delivery, with\n`load` carried on the vehicle between the two legs.\n\n`drop_cost` and vehicle eligibility (`eligible_vehicles`, allow\n**and** exclude, any length) are fully supported and applied to both legs — a\nshipment's pickup and delivery share one droppability/eligibility decision,\nsince one vehicle must serve both.","required":["id","pickup","delivery"],"properties":{"delivery":{"type":"object","description":"Delivery leg (load off).","required":["location"],"properties":{"location":{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.shipments.items.[INDEX].delivery.location.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"Where this stop happens.","examples":[[3.725,51.05]],"maxItems":2,"minItems":2,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].delivery.location","typeLabel":"number\u003cdouble>[]"},"id":{"oneOf":[{"type":"string","description":"Stop id: 1 to 128 characters when set. Defaults to\n`\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`. The effective id\n(custom or default) must be unique across all job, shipment, and stop\nids — a collision is rejected with HTTP 400.","example":"ship-1:pickup","maxLength":128,"minLength":1,"uniqueKey":"problem.shipments.items.[INDEX].delivery.id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Stop id: 1 to 128 characters when set. Defaults to\n`\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`. The effective id\n(custom or default) must be unique across all job, shipment, and stop\nids — a collision is rejected with HTTP 400.","example":"ship-1:pickup","maxLength":128,"minLength":1,"uniqueKey":"problem.shipments.items.[INDEX].delivery.id.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.id","typeLabel":"string | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.service_duration_s","typeLabel":"integer\u003cint32> | null"},"setup_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.setup_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.setup_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.setup_duration_s","typeLabel":"integer\u003cint32> | null"},"time_windows":{"oneOf":[{"type":"array","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].from","typeLabel":"string\u003cdate-time>"},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].to","typeLabel":"string\u003cdate-time>"},"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].choice_cost","typeLabel":"number\u003cdouble> | null"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX].per_late_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"},"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Time windows for this stop.","uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0}]},"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006}]},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}},"description":"Time windows for this stop.","uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].delivery.time_windows","typeLabel":"object[] | null"}},"additionalProperties":false,"example":{"id":"ship-1:pickup","location":[3.725,51.05],"service_duration_s":300,"setup_duration_s":60,"time_windows":[{"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}]},"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].delivery","typeLabel":"object"},"id":{"type":"string","description":"Shipment id: 1 to 128 characters, unique across `jobs` + `shipments`.","example":"ship-1","maxLength":128,"minLength":1,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].id","typeLabel":"string"},"pickup":{"type":"object","description":"Pickup leg (load on).","required":["location"],"properties":{"location":{"type":"array","items":{"type":"number","format":"double","uniqueKey":"problem.shipments.items.[INDEX].pickup.location.items.[INDEX]","typeLabel":"number\u003cdouble>"},"description":"Where this stop happens.","examples":[[3.725,51.05]],"maxItems":2,"minItems":2,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].pickup.location","typeLabel":"number\u003cdouble>[]"},"id":{"oneOf":[{"type":"string","description":"Stop id: 1 to 128 characters when set. Defaults to\n`\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`. The effective id\n(custom or default) must be unique across all job, shipment, and stop\nids — a collision is rejected with HTTP 400.","example":"ship-1:pickup","maxLength":128,"minLength":1,"uniqueKey":"problem.shipments.items.[INDEX].pickup.id.oneOf.0","typeLabel":"string"},{"type":"null","description":"Stop id: 1 to 128 characters when set. Defaults to\n`\"{shipment}:pickup\"` / `\"{shipment}:delivery\"`. The effective id\n(custom or default) must be unique across all job, shipment, and stop\nids — a collision is rejected with HTTP 400.","example":"ship-1:pickup","maxLength":128,"minLength":1,"uniqueKey":"problem.shipments.items.[INDEX].pickup.id.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.id","typeLabel":"string | null"},"service_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.service_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"On-site service time paid per job (seconds).\n\nThis is the nominal figure. The serving vehicle's `service_factor`\nscales it — the time actually scheduled is\n`service_duration_s / service_factor` — so the solution's\n`stops[].service_s` may differ from what you sent here. Default `0`;\na negative value is rejected with HTTP 400.","example":300,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.service_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.service_duration_s","typeLabel":"integer\u003cint32> | null"},"setup_duration_s":{"oneOf":[{"type":"integer","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.setup_duration_s.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Setup time paid once on arrival at a new location (seconds),\ndistinct from `service_duration_s`. Skipped when the immediate real\npredecessor in the route already sits at this location — co-located\nstops share one setup.\n\nNot scaled by the vehicle's `service_factor`: setup is fixed arrival\noverhead (parking, walking to the door), not the work itself.\nDefault `0`; a negative value is rejected with HTTP 400.","example":60,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.setup_duration_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.setup_duration_s","typeLabel":"integer\u003cint32> | null"},"time_windows":{"oneOf":[{"type":"array","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].from","typeLabel":"string\u003cdate-time>"},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].to","typeLabel":"string\u003cdate-time>"},"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].choice_cost.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].choice_cost","typeLabel":"number\u003cdouble> | null"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006,"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].per_late_hour.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX].per_late_hour","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"},"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Time windows for this stop.","uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A time window. Hard unless it (or `objective.per_late_hour`, for\nevery window) prices lateness.","required":["from","to"],"properties":{"choice_cost":{"oneOf":[{"type":"number","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0},{"type":"null","format":"double","description":"Optional flat cost, in the objective's currency, added when this\njob/stop is served within THIS window rather than a free/cheaper\nalternative window on the same task. Absent = 0 (no charge). Every\nwindow in the list remains individually hard — a job must still land\nin *some* window — this only grades preference among the hard\nalternatives; it does not soften time-window feasibility. Must be\nfinite and `>= 0`, and requires at least 2 windows on the task. Once\nany window on the task carries a *nonzero* cost, that task's windows\nmust also be pairwise non-overlapping, and windows that only touch\ncount as overlapping (a task whose costs are all\n`0`/absent has its overlapping windows merged).\n\n**Cannot be combined with `objective.per_late_hour > 0`** — a\nnonzero `choice_cost` anywhere in the request alongside priced lateness\nis rejected with HTTP 400 (the two read opposite ways about which\nwindow was paid for). Choose one: priced alternative windows, or priced\nlateness.","maximum":21474.83647,"minimum":0}]},"from":{"type":"string","format":"date-time","description":"Earliest allowed start of service (RFC 3339 instant, UTC offset\nrequired). A vehicle that arrives earlier waits.","example":"2026-07-01T09:00:00+02:00"},"per_late_hour":{"oneOf":[{"type":"number","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006},{"type":"null","format":"double","description":"Makes this window soft on its late side: arriving after `to` is\nallowed and priced at this rate, in the objective's currency per hour\nlate, in place of `objective.per_late_hour` (and whether or not\nthat is set, so hard and soft windows can share one request). Must be\n`> 0`; omit it for a hard window. Only on a\ntask with exactly one window. Arriving early still waits for `from`.","example":60,"minimum":0.0006}]},"to":{"type":"string","format":"date-time","description":"Latest allowed start of service (RFC 3339 instant, UTC offset\nrequired), measured from arrival plus any windowed break taken first\n(#1750 D1). Hard unless `per_late_hour` prices lateness.","example":"2026-07-01T12:00:00+02:00"}},"additionalProperties":false,"example":{"choice_cost":15,"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}},"description":"Time windows for this stop.","uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].pickup.time_windows","typeLabel":"object[] | null"}},"additionalProperties":false,"example":{"id":"ship-1:pickup","location":[3.725,51.05],"service_duration_s":300,"setup_duration_s":60,"time_windows":[{"from":"2026-07-01T09:00:00+02:00","to":"2026-07-01T12:00:00+02:00"}]},"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].pickup","typeLabel":"object"},"assignment_costs":{"oneOf":[{"type":"array","items":{"type":"object","description":"Absolute price of serving one task on one vehicle.","required":["vehicle","cost"],"properties":{"cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when this vehicle serves\nthe task. Must be finite and `>= 0`. A vehicle not listed costs `0`.","example":12.5,"maximum":21474.83647,"minimum":0,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX].cost","typeLabel":"number\u003cdouble>"},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle. An id that matches\nno vehicle, or a vehicle listed twice in one task's\n`assignment_costs`, is rejected with HTTP 400.","example":"v1","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"}},"additionalProperties":false,"example":{"cost":12.5,"vehicle":"v1"},"uniqueKey":"problem.shipments.items.[INDEX].assignment_costs.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Absolute price of serving this task on a given vehicle, in the\nobjective's currency. Charged once, when that vehicle (on any of its\nshifts) serves the task; unlisted vehicles cost nothing. Unlike\n`preferences`, which charges the vehicles that did NOT get the task,\nthis prices the vehicle that did, so a task rated badly everywhere is\nthe first one dropped when capacity runs out. It lives in the cost tier,\nbelow `priority`, and adds to `preferences`, `drop_cost` and travel.\nNot applied by decomposition: a problem that sets it solves monolithically.","uniqueKey":"problem.shipments.items.[INDEX].assignment_costs.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Absolute price of serving one task on one vehicle.","required":["vehicle","cost"],"properties":{"cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when this vehicle serves\nthe task. Must be finite and `>= 0`. A vehicle not listed costs `0`.","example":12.5,"maximum":21474.83647,"minimum":0},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle. An id that matches\nno vehicle, or a vehicle listed twice in one task's\n`assignment_costs`, is rejected with HTTP 400.","example":"v1"}},"additionalProperties":false,"example":{"cost":12.5,"vehicle":"v1"}},"description":"Absolute price of serving this task on a given vehicle, in the\nobjective's currency. Charged once, when that vehicle (on any of its\nshifts) serves the task; unlisted vehicles cost nothing. Unlike\n`preferences`, which charges the vehicles that did NOT get the task,\nthis prices the vehicle that did, so a task rated badly everywhere is\nthe first one dropped when capacity runs out. It lives in the cost tier,\nbelow `priority`, and adds to `preferences`, `drop_cost` and travel.\nNot applied by decomposition: a problem that sets it solves monolithically.","uniqueKey":"problem.shipments.items.[INDEX].assignment_costs.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].assignment_costs","typeLabel":"object[] | null"},"drop_cost":{"oneOf":[{"type":"number","format":"double","description":"Drop **price** — what leaving this task unserved costs you, in the same\ncurrency as `objective.costs`, and the only way to make a task\ndroppable. Tasks without a `drop_cost` must be served.\n\nThis is money, not a priority: it enters the same cost the solver\nminimises, so the task is served only while serving it costs less than\ndropping it. Drop costs the plan chose to pay are reported in\n`score.components.drop_costs` and summed into `score.cost`.\n\nOn a shipment the drop cost applies to the pair, charged once.\n\nMust be finite, `>= 0` and at most `1e9`; combined with `priority` it\nis rejected with HTTP 400 (`conflicting_fields`). Also rejected with\nHTTP 400 (`not_supported`) while a positive `objective.per_delay_workday` is set,\nsince a droppable task could be dropped to avoid its delay charge.","example":25,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].drop_cost.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Drop **price** — what leaving this task unserved costs you, in the same\ncurrency as `objective.costs`, and the only way to make a task\ndroppable. Tasks without a `drop_cost` must be served.\n\nThis is money, not a priority: it enters the same cost the solver\nminimises, so the task is served only while serving it costs less than\ndropping it. Drop costs the plan chose to pay are reported in\n`score.components.drop_costs` and summed into `score.cost`.\n\nOn a shipment the drop cost applies to the pair, charged once.\n\nMust be finite, `>= 0` and at most `1e9`; combined with `priority` it\nis rejected with HTTP 400 (`conflicting_fields`). Also rejected with\nHTTP 400 (`not_supported`) while a positive `objective.per_delay_workday` is set,\nsince a droppable task could be dropped to avoid its delay charge.","example":25,"maximum":1000000000,"minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].drop_cost.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].drop_cost","typeLabel":"number\u003cdouble> | null"},"eligible_vehicles":{"oneOf":[{"type":"null","description":"Hard vehicle allow/exclude. A request may use at most 256 distinct\npermitted-vehicle sets (after resolving `allowed`/`excluded`) across\nall jobs and shipments (HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.0","typeLabel":"null"},{"type":"object","description":"Hard vehicle allow/exclude. A request may use at most 256 distinct\npermitted-vehicle sets (after resolving `allowed`/`excluded`) across\nall jobs and shipments (HTTP 400 `limit_exceeded` beyond that).","example":{"allowed":["v1","v2"]},"properties":{"allowed":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Hard whitelist of vehicle ids. Omit = all vehicles allowed. An empty\nlist, or an id that names no vehicle, is rejected with HTTP 400.","minItems":1,"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Hard whitelist of vehicle ids. Omit = all vehicles allowed. An empty\nlist, or an id that names no vehicle, is rejected with HTTP 400.","minItems":1,"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.allowed.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.allowed","typeLabel":"string[] | null"},"excluded":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Hard blacklist of vehicle ids. Mutually exclusive with `allowed`. An\nid that names no vehicle is rejected with HTTP 400.","uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Hard blacklist of vehicle ids. Mutually exclusive with `allowed`. An\nid that names no vehicle is rejected with HTTP 400.","uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.excluded.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1.excluded","typeLabel":"string[] | null"}},"additionalProperties":false,"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.shipments.items.[INDEX].eligible_vehicles","typeLabel":"null | object"},"load":{"oneOf":[{"type":"null","description":"Load carried from the pickup to the delivery: picked up at one leg and\nthe same quantity dropped off at the other. Non-negative magnitudes\nper named dimension.","uniqueKey":"problem.shipments.items.[INDEX].load.oneOf.0","typeLabel":"null"},{"type":"object","description":"Load carried from the pickup to the delivery: picked up at one leg and\nthe same quantity dropped off at the other. Non-negative magnitudes\nper named dimension.","example":{"volume":2,"weight":20},"additionalProperties":{"type":"integer","format":"int32","minimum":0,"uniqueKey":"problem.shipments.items.[INDEX].load.oneOf.1.additionalProperties","typeLabel":"integer\u003cint32>"},"uniqueKey":"problem.shipments.items.[INDEX].load.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.shipments.items.[INDEX].load","typeLabel":"null | object"},"preferences":{"oneOf":[{"type":"array","items":{"type":"object","description":"A soft vehicle affinity preference, priced.","required":["vehicle","violation_cost"],"properties":{"vehicle":{"type":"string","description":"Preferred vehicle id. An id that names no vehicle, or a vehicle listed\ntwice in one task's `preferences`, is rejected with HTTP 400.","example":"v1","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].preferences.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a different vehicle\nserves the job. Must be finite and `>= 0`.","example":50,"maximum":21474.83647,"minimum":0,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].preferences.oneOf.0.items.[INDEX].violation_cost","typeLabel":"number\u003cdouble>"}},"additionalProperties":false,"example":{"vehicle":"v1","violation_cost":50},"uniqueKey":"problem.shipments.items.[INDEX].preferences.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Soft vehicle affinity preferences, priced. Each entry is independent:\na job listing several preferred vehicles it doesn't get pays each\none's `violation_cost` (compounding, the same rule as a vehicle's\n`preferred_tags`).","uniqueKey":"problem.shipments.items.[INDEX].preferences.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A soft vehicle affinity preference, priced.","required":["vehicle","violation_cost"],"properties":{"vehicle":{"type":"string","description":"Preferred vehicle id. An id that names no vehicle, or a vehicle listed\ntwice in one task's `preferences`, is rejected with HTTP 400.","example":"v1"},"violation_cost":{"type":"number","format":"double","description":"Cost, in the objective's currency, incurred when a different vehicle\nserves the job. Must be finite and `>= 0`.","example":50,"maximum":21474.83647,"minimum":0}},"additionalProperties":false,"example":{"vehicle":"v1","violation_cost":50}},"description":"Soft vehicle affinity preferences, priced. Each entry is independent:\na job listing several preferred vehicles it doesn't get pays each\none's `violation_cost` (compounding, the same rule as a vehicle's\n`preferred_tags`).","uniqueKey":"problem.shipments.items.[INDEX].preferences.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].preferences","typeLabel":"object[] | null"},"priority":{"oneOf":[{"type":"integer","format":"int32","description":"Importance of a must-serve task when not all of them fit: the solver\nmaximises the summed `priority` of served tasks before any cost. `>= 1`,\ndefault `1` (maximise the count). A rank, not money — it never makes a\ntask droppable; use `drop_cost` for that. Both set is a 400.","example":3,"minimum":1,"uniqueKey":"problem.shipments.items.[INDEX].priority.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Importance of a must-serve task when not all of them fit: the solver\nmaximises the summed `priority` of served tasks before any cost. `>= 1`,\ndefault `1` (maximise the count). A rank, not money — it never makes a\ntask droppable; use `drop_cost` for that. Both set is a 400.","example":3,"minimum":1,"uniqueKey":"problem.shipments.items.[INDEX].priority.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].priority","typeLabel":"integer\u003cint32> | null"},"required_skills":{"oneOf":[{"type":"array","items":{"type":"object","description":"A hard skill requirement — the assigned vehicle must provide it.","required":["name"],"properties":{"name":{"type":"string","description":"Skill name the assigned vehicle must provide.","example":"fridge","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0.items.[INDEX].name","typeLabel":"string"},"min_level":{"oneOf":[{"type":"integer","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1,"uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1,"uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0.items.[INDEX].min_level","typeLabel":"integer\u003cint32> | null"}},"additionalProperties":false,"example":{"name":"fridge"},"uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Hard skill requirements — the assigned vehicle must provide every one,\nat or above each requirement's `min_level`. A request may use at most\n256 distinct `(name, min_level)` pairs across all jobs and shipments\n(HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"A hard skill requirement — the assigned vehicle must provide it.","required":["name"],"properties":{"min_level":{"oneOf":[{"type":"integer","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1},{"type":"null","format":"int32","description":"Minimum level the serving vehicle must hold for this skill (`>= 1`).\nAbsent = 1. A vehicle skill with no `level` holds level 1.","example":2,"minimum":1}]},"name":{"type":"string","description":"Skill name the assigned vehicle must provide.","example":"fridge"}},"additionalProperties":false,"example":{"name":"fridge"}},"description":"Hard skill requirements — the assigned vehicle must provide every one,\nat or above each requirement's `min_level`. A request may use at most\n256 distinct `(name, min_level)` pairs across all jobs and shipments\n(HTTP 400 `limit_exceeded` beyond that).","uniqueKey":"problem.shipments.items.[INDEX].required_skills.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].required_skills","typeLabel":"object[] | null"},"service_factors":{"oneOf":[{"type":"array","items":{"type":"object","description":"Per-vehicle work-rate override for one task's `service_duration_s`.","required":["vehicle","factor"],"properties":{"factor":{"type":"number","format":"double","description":"Work-rate factor of `vehicle` on this task. Service time is DIVIDED by\nit: above `1` the vehicle works faster here, below `1` slower; `1.0` is a\nno-op. It multiplies the vehicle's own rate (the shift's\n`service_factor` if set, else the vehicle's): effective service time =\n`service_duration_s / (shift_or_vehicle_factor * factor)`. Same\ndirection and `[0.001, 5]` range as `vehicles[].service_factor`. V2's\n`proficiency.durationModifier` multiplied duration instead; the V2\ncompatibility layer sends its inverse (`1 / durationModifier`) here.","example":1.25,"maximum":5,"minimum":0.001,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].service_factors.oneOf.0.items.[INDEX].factor","typeLabel":"number\u003cdouble>"},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle.","example":"v1","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].service_factors.oneOf.0.items.[INDEX].vehicle","typeLabel":"string"}},"additionalProperties":false,"example":{"factor":1.25,"vehicle":"v1"},"uniqueKey":"problem.shipments.items.[INDEX].service_factors.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Per-vehicle work-rate factors for this task's `service_duration_s`,\nwhich is DIVIDED by the factor (above `1` = faster). Each multiplies\nthe serving vehicle's rate (the shift's `service_factor` if set, else\nthe vehicle's): effective service time = `service_duration_s /\n(shift_or_vehicle_factor * factor)`. On a shipment the factor scales\nboth legs. A vehicle not listed works at its own rate.","uniqueKey":"problem.shipments.items.[INDEX].service_factors.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Per-vehicle work-rate override for one task's `service_duration_s`.","required":["vehicle","factor"],"properties":{"factor":{"type":"number","format":"double","description":"Work-rate factor of `vehicle` on this task. Service time is DIVIDED by\nit: above `1` the vehicle works faster here, below `1` slower; `1.0` is a\nno-op. It multiplies the vehicle's own rate (the shift's\n`service_factor` if set, else the vehicle's): effective service time =\n`service_duration_s / (shift_or_vehicle_factor * factor)`. Same\ndirection and `[0.001, 5]` range as `vehicles[].service_factor`. V2's\n`proficiency.durationModifier` multiplied duration instead; the V2\ncompatibility layer sends its inverse (`1 / durationModifier`) here.","example":1.25,"maximum":5,"minimum":0.001},"vehicle":{"type":"string","description":"Vehicle id; applies to every shift of that vehicle.","example":"v1"}},"additionalProperties":false,"example":{"factor":1.25,"vehicle":"v1"}},"description":"Per-vehicle work-rate factors for this task's `service_duration_s`,\nwhich is DIVIDED by the factor (above `1` = faster). Each multiplies\nthe serving vehicle's rate (the shift's `service_factor` if set, else\nthe vehicle's): effective service time = `service_duration_s /\n(shift_or_vehicle_factor * factor)`. On a shipment the factor scales\nboth legs. A vehicle not listed works at its own rate.","uniqueKey":"problem.shipments.items.[INDEX].service_factors.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].service_factors","typeLabel":"object[] | null"},"tags":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"problem.shipments.items.[INDEX].tags.oneOf.0.items.[INDEX]","typeLabel":"string"},"description":"Free-form task labels (zones/territories, relation labels).\nUsed for `tag`/relation resolution and, when a shift scopes itself via\n`serves_tags` (hard ANY-overlap) or a vehicle prices them via\n`preferred_tags` (soft), for tag matching. ANY-overlap — contrast with\n`required_skills`, which requires ALL. Not capability matching on its own.\nA request may carry at most 256 distinct tags across all jobs and\nshipments (HTTP 400 `limit_exceeded` beyond that); vehicle-side tag\nlists do not count.","uniqueKey":"problem.shipments.items.[INDEX].tags.oneOf.0","typeLabel":"string[]"},{"type":"null","items":{"type":"string"},"description":"Free-form task labels (zones/territories, relation labels).\nUsed for `tag`/relation resolution and, when a shift scopes itself via\n`serves_tags` (hard ANY-overlap) or a vehicle prices them via\n`preferred_tags` (soft), for tag matching. ANY-overlap — contrast with\n`required_skills`, which requires ALL. Not capability matching on its own.\nA request may carry at most 256 distinct tags across all jobs and\nshipments (HTTP 400 `limit_exceeded` beyond that); vehicle-side tag\nlists do not count.","uniqueKey":"problem.shipments.items.[INDEX].tags.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.shipments.items.[INDEX].tags","typeLabel":"string[] | null"},"target":{"oneOf":[{"type":"null","description":"Soft target for this task, measured at its arrival (default) or\ndeparture. On a shipment it is measured on the **delivery** leg.","uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.0","typeLabel":"null"},{"type":"object","description":"Soft target for this task, measured at its arrival (default) or\ndeparture. On a shipment it is measured on the **delivery** leg.","required":["at","per_late_hour"],"example":{"at":"2026-07-01T10:00:00+02:00","on":"arrival","per_late_hour":60},"properties":{"at":{"type":"string","format":"date-time","description":"Target instant (RFC 3339, UTC offset required) the `on` instant is measured against.","example":"2026-07-01T10:00:00+02:00","isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1.at","typeLabel":"string\u003cdate-time>"},"per_late_hour":{"type":"number","format":"double","description":"Cost, in the objective's currency, per hour of `on` beyond `at`\n(linear, prorated per second). Must be `> 0`; independent of\n`objective.per_late_hour` (which prices *time-window* lateness,\nnot a target point).","example":60,"maximum":21474.83647,"minimum":0.00001,"isRequired":true,"uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1.per_late_hour","typeLabel":"number\u003cdouble>"},"on":{"oneOf":[{"type":"null","description":"Which instant of the task is compared to `at`: `arrival` (default) or\n`departure`, the stop fields of the same names.","default":"arrival","uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1.on.oneOf.0","typeLabel":"null"},{"type":"string","description":"Which instant of the task is compared to `at`: `arrival` (default) or\n`departure`, the stop fields of the same names.","default":"arrival","enum":["arrival","departure"],"uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1.on.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1.on","typeLabel":"null | enum\u003cstring>"}},"additionalProperties":false,"uniqueKey":"problem.shipments.items.[INDEX].target.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.shipments.items.[INDEX].target","typeLabel":"null | object"}},"additionalProperties":false,"example":{"delivery":{"location":[3.71,51.06],"service_duration_s":300},"id":"ship-1","load":{"weight":20},"pickup":{"location":[3.725,51.05],"service_duration_s":300}},"uniqueKey":"problem.shipments.items.[INDEX]","typeLabel":"object"},"description":"Bound pickup→delivery shipments to serve. Counts toward the same\n10,000-task cap as `jobs`.","maxItems":10000,"uniqueKey":"problem.shipments","typeLabel":"object[]"},"travel":{"oneOf":[{"type":"null","description":"Where travel times and distances come from.","uniqueKey":"problem.travel.oneOf.0","typeLabel":"null"},{"type":"object","description":"Where travel times and distances come from.","example":{"departure_time":"2026-07-01T08:00:00+02:00","engine":"tomtom"},"properties":{"departure_time":{"oneOf":[{"type":"string","format":"date-time","description":"Departure time for the traffic lookup (RFC 3339 instant, any offset).\nOmitted → free-flow times, or traffic at solve time with `engine:\ntomtom`. An explicit departure time bypasses the server-side matrix\ncache.","example":"2026-07-01T08:00:00+02:00","uniqueKey":"problem.travel.oneOf.1.departure_time.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","description":"Departure time for the traffic lookup (RFC 3339 instant, any offset).\nOmitted → free-flow times, or traffic at solve time with `engine:\ntomtom`. An explicit departure time bypasses the server-side matrix\ncache.","example":"2026-07-01T08:00:00+02:00","uniqueKey":"problem.travel.oneOf.1.departure_time.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.travel.oneOf.1.departure_time","typeLabel":"string\u003cdate-time> | null"},"engine":{"oneOf":[{"type":"null","description":"Data behind travel times and distances. Omitted → `osm`, or `tomtom`\nwhen `departure_time` is set.","uniqueKey":"problem.travel.oneOf.1.engine.oneOf.0","typeLabel":"null"},{"type":"string","description":"Data behind travel times and distances. Omitted → `osm`, or `tomtom`\nwhen `departure_time` is set.","enum":["tomtom","osm","tomtom_real_time","straight_line"],"example":"osm","uniqueKey":"problem.travel.oneOf.1.engine.oneOf.1","typeLabel":"enum\u003cstring>"}],"uniqueKey":"problem.travel.oneOf.1.engine","typeLabel":"null | enum\u003cstring>"},"speed_kmh":{"oneOf":[{"type":"number","format":"double","description":"Travel speed for `engine: \"straight_line\"`, in km/h: each leg takes its\ngreat-circle distance at this speed, rounded to the whole second. `1` to\n`1000`, default `50`; `vehicles[].speed_factor` still scales it per\nvehicle. Any other engine rejects it (HTTP 400 `conflicting_fields`).","default":50,"example":50,"maximum":1000,"minimum":1,"uniqueKey":"problem.travel.oneOf.1.speed_kmh.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Travel speed for `engine: \"straight_line\"`, in km/h: each leg takes its\ngreat-circle distance at this speed, rounded to the whole second. `1` to\n`1000`, default `50`; `vehicles[].speed_factor` still scales it per\nvehicle. Any other engine rejects it (HTTP 400 `conflicting_fields`).","default":50,"example":50,"maximum":1000,"minimum":1,"uniqueKey":"problem.travel.oneOf.1.speed_kmh.oneOf.1","typeLabel":"null"}],"uniqueKey":"problem.travel.oneOf.1.speed_kmh","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"problem.travel.oneOf.1","typeLabel":"object"}],"uniqueKey":"problem.travel","typeLabel":"null | object"}},"additionalProperties":false,"example":{"depots":[{"id":"gent","location":[3.7174,51.0543]}],"jobs":[{"id":"job-1","location":[3.725,51.05],"pickup_load":{"weight":20},"service_duration_s":300}],"vehicles":[{"capacity":{"weight":500},"id":"v1","shifts":[{"end":{"depot":"gent"},"from":"2026-07-01T08:00:00+02:00","id":"mon","start":{"depot":"gent"},"to":"2026-07-01T17:00:00+02:00"}]}]},"isRequired":true,"uniqueKey":"problem","typeLabel":"object"},"options":{"oneOf":[{"type":"null","description":"Suggest options. Absent: the defaults.","uniqueKey":"options.oneOf.0","typeLabel":"null"},{"type":"object","description":"Suggest options. Absent: the defaults.","example":{"max_insertions":5,"time_limit_s":2},"properties":{"max_insertions":{"oneOf":[{"type":"integer","format":"int32","description":"Max ranked `insertions` in each `suggestions[]` entry, `1` to `10`;\ndefault 5. It caps the insertions per entry, not the number of\nentries: every task outside `plan` still gets its entry. Values outside\nthe range are a 400, never clamped. It also sets the search's beam\nwidth, `max(8, 4 × max_insertions)`: for a unit of several stops, which\nis never searched exhaustively, each stop after the unit's first keeps\nat most that many partial placements. A single-stop task has every\nfeasible position considered unless `time_limit_s` runs out first.","default":5,"example":5,"maximum":10,"minimum":1,"uniqueKey":"options.oneOf.1.max_insertions.oneOf.0","typeLabel":"integer\u003cint32>"},{"type":"null","format":"int32","description":"Max ranked `insertions` in each `suggestions[]` entry, `1` to `10`;\ndefault 5. It caps the insertions per entry, not the number of\nentries: every task outside `plan` still gets its entry. Values outside\nthe range are a 400, never clamped. It also sets the search's beam\nwidth, `max(8, 4 × max_insertions)`: for a unit of several stops, which\nis never searched exhaustively, each stop after the unit's first keeps\nat most that many partial placements. A single-stop task has every\nfeasible position considered unless `time_limit_s` runs out first.","default":5,"example":5,"maximum":10,"minimum":1,"uniqueKey":"options.oneOf.1.max_insertions.oneOf.1","typeLabel":"null"}],"uniqueKey":"options.oneOf.1.max_insertions","typeLabel":"integer\u003cint32> | null"},"time_limit_s":{"oneOf":[{"type":"number","format":"double","description":"Search budget in seconds, fractions allowed (default 1; minimum 0.1 —\nsmaller values are raised to it; maximum 60). The clock\nstarts when the search starts, after the matrix fetch and any wait for a\nsolver slot. Units are searched in problem order (jobs, then\nshipments), each with an equal share of the time left when it starts; a\nunit that finishes early leaves its slack to the ones after it.","default":1,"example":2.5,"maximum":60,"minimum":0,"uniqueKey":"options.oneOf.1.time_limit_s.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","description":"Search budget in seconds, fractions allowed (default 1; minimum 0.1 —\nsmaller values are raised to it; maximum 60). The clock\nstarts when the search starts, after the matrix fetch and any wait for a\nsolver slot. Units are searched in problem order (jobs, then\nshipments), each with an equal share of the time left when it starts; a\nunit that finishes early leaves its slack to the ones after it.","default":1,"example":2.5,"maximum":60,"minimum":0,"uniqueKey":"options.oneOf.1.time_limit_s.oneOf.1","typeLabel":"null"}],"uniqueKey":"options.oneOf.1.time_limit_s","typeLabel":"number\u003cdouble> | null"}},"additionalProperties":false,"uniqueKey":"options.oneOf.1","typeLabel":"object"}],"uniqueKey":"options","typeLabel":"null | object"}},"additionalProperties":false,"example":{"options":{"max_insertions":5},"plan":{"routes":[{"shift":"mon","stops":[{"id":"job-1","type":"job"}],"vehicle":"v1"}]},"problem":{"jobs":[{"id":"job-1","location":[3.725,51.05],"pickup_load":{"weight":10},"service_duration_s":300},{"id":"job-2","location":[3.71,51.06],"pickup_load":{"weight":10},"service_duration_s":300}],"vehicles":[{"capacity":{"weight":500},"id":"v1","shifts":[{"end":{"location":[3.7174,51.0543]},"from":"2026-07-01T08:00:00+02:00","id":"mon","start":{"location":[3.7174,51.0543]},"to":"2026-07-01T17:00:00+02:00"}]}]}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"options":{"max_insertions":5},"plan":{"routes":[{"shift":"mon","stops":[{"id":"job-1","type":"job"}],"vehicle":"v1"}]},"problem":{"jobs":[{"id":"job-1","location":[3.725,51.05],"pickup_load":{"weight":10},"service_duration_s":300},{"id":"job-2","location":[3.71,51.06],"pickup_load":{"weight":10},"service_duration_s":300}],"vehicles":[{"capacity":{"weight":500},"id":"v1","shifts":[{"end":{"location":[3.7174,51.0543]},"from":"2026-07-01T08:00:00+02:00","id":"mon","start":{"location":[3.7174,51.0543]},"to":"2026-07-01T17:00:00+02:00"}]}]}}}},"exampleType":"generated"}},"required":true,"exampleType":"generated"},"responses":{"19aab307-5994-4839-bffb-6106d915b694":{"description":"The request passed every check made before travel times are fetched. `warnings` may contain warnings; none are produced today.","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"The 200 body of `POST /v3/routing/validate/{solve,evaluate,suggest}`: the\nrequest passed every check a real call runs before the matrix fetch.","required":["valid","warnings"],"properties":{"valid":{"type":"boolean","description":"Always `true`: an invalid request gets a 400 instead.","isRequired":true,"uniqueKey":"valid","typeLabel":"boolean"},"warnings":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"warnings.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"warnings.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"warnings.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"warnings.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"warnings.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"warnings.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"warnings.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"warnings.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"warnings.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"warnings.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"warnings.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"warnings.items.[INDEX]","typeLabel":"object"},"description":"May contain warnings about the request; none are produced today.","isRequired":true,"uniqueKey":"warnings","typeLabel":"object[]"}},"example":{"valid":true,"warnings":[]},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"valid":true,"warnings":[]}}},"exampleType":"generated"}},"exampleType":"generated"},"d7710125-24ed-4033-bfed-f6631a996cfd":{"description":"The request is invalid. `errors[]` lists what to fix, each entry with a `code` and, when the problem is in the body, a JSON `pointer` to it.","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"Error body of every `/v3/routing/*` endpoint.\n\n`status` is the HTTP status as text, `code` says what kind of failure it\nis, `request_id` identifies the request, and `errors` holds one item per\nproblem found in the request. Branch on `code`, and on `errors[].code` for\n400s; the messages are for people.","required":["status","code","message"],"properties":{"code":{"type":"string","description":"What kind of failure this is. One value per HTTP status class.","x-extensible-enum":["invalid_request","feature_not_enabled","payload_too_large","unsupported_media_type","internal","travel_provider_error","overloaded"],"isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable summary. With exactly one item it is that item's\nmessage; with several, `\"{n} problems in request\"` (at most 100 items\nare listed, and the message says when the list is cut).","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"status":{"type":"string","description":"The HTTP status as text, e.g. `\"BAD_REQUEST\"` or\n`\"SERVICE_UNAVAILABLE\"`.","example":"BAD_REQUEST","isRequired":true,"uniqueKey":"status","typeLabel":"string"},"errors":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"errors.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"description":"One entry per problem found in the request. Empty for non-input errors.","uniqueKey":"errors","typeLabel":"object[]"},"request_id":{"oneOf":[{"type":"string","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"request_id","typeLabel":"string | null"}},"example":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"}}},"exampleType":"generated"}},"exampleType":"generated"},"1a341c44-e67d-414d-a550-aa059286dc6d":{"description":"Missing or invalid API key. Returned by the API gateway before the request reaches the solver, so it does not use the `ErrorBody` shape and can have an empty body. Branch on the HTTP status.","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"2b7215a4-b32b-432c-8e5e-f72d9b754303":{"description":"The request uses a feature this account does not have (`tomtom_real_time`)","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"Error body of every `/v3/routing/*` endpoint.\n\n`status` is the HTTP status as text, `code` says what kind of failure it\nis, `request_id` identifies the request, and `errors` holds one item per\nproblem found in the request. Branch on `code`, and on `errors[].code` for\n400s; the messages are for people.","required":["status","code","message"],"properties":{"code":{"type":"string","description":"What kind of failure this is. One value per HTTP status class.","x-extensible-enum":["invalid_request","feature_not_enabled","payload_too_large","unsupported_media_type","internal","travel_provider_error","overloaded"],"isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable summary. With exactly one item it is that item's\nmessage; with several, `\"{n} problems in request\"` (at most 100 items\nare listed, and the message says when the list is cut).","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"status":{"type":"string","description":"The HTTP status as text, e.g. `\"BAD_REQUEST\"` or\n`\"SERVICE_UNAVAILABLE\"`.","example":"BAD_REQUEST","isRequired":true,"uniqueKey":"status","typeLabel":"string"},"errors":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"errors.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"description":"One entry per problem found in the request. Empty for non-input errors.","uniqueKey":"errors","typeLabel":"object[]"},"request_id":{"oneOf":[{"type":"string","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"request_id","typeLabel":"string | null"}},"example":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"},"uniqueKey":"","typeLabel":"object"},"example":{"code":"feature_not_enabled","message":"travel.engine: 'tomtom_real_time' is not enabled for this account; use engine 'tomtom'","request_id":"req_7f3a2c90d1e4b5a6","status":"FORBIDDEN"},"examples":{"Example":{"title":"Example","value":{"code":"feature_not_enabled","message":"travel.engine: 'tomtom_real_time' is not enabled for this account; use engine 'tomtom'","request_id":"req_7f3a2c90d1e4b5a6","status":"FORBIDDEN"}}},"exampleType":"examples"}},"exampleType":"examples"},"aa52ea89-715c-4bcd-8a3a-4fca06fad029":{"description":"Request body larger than 10 MiB (10,485,760 bytes), counted after gzip decompression","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"Error body of every `/v3/routing/*` endpoint.\n\n`status` is the HTTP status as text, `code` says what kind of failure it\nis, `request_id` identifies the request, and `errors` holds one item per\nproblem found in the request. Branch on `code`, and on `errors[].code` for\n400s; the messages are for people.","required":["status","code","message"],"properties":{"code":{"type":"string","description":"What kind of failure this is. One value per HTTP status class.","x-extensible-enum":["invalid_request","feature_not_enabled","payload_too_large","unsupported_media_type","internal","travel_provider_error","overloaded"],"isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable summary. With exactly one item it is that item's\nmessage; with several, `\"{n} problems in request\"` (at most 100 items\nare listed, and the message says when the list is cut).","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"status":{"type":"string","description":"The HTTP status as text, e.g. `\"BAD_REQUEST\"` or\n`\"SERVICE_UNAVAILABLE\"`.","example":"BAD_REQUEST","isRequired":true,"uniqueKey":"status","typeLabel":"string"},"errors":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"errors.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"description":"One entry per problem found in the request. Empty for non-input errors.","uniqueKey":"errors","typeLabel":"object[]"},"request_id":{"oneOf":[{"type":"string","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"request_id","typeLabel":"string | null"}},"example":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"},"uniqueKey":"","typeLabel":"object"},"example":{"code":"payload_too_large","message":"Request body exceeds 10485760 bytes","request_id":"req_7f3a2c90d1e4b5a6","status":"PAYLOAD_TOO_LARGE"},"examples":{"Example":{"title":"Example","value":{"code":"payload_too_large","message":"Request body exceeds 10485760 bytes","request_id":"req_7f3a2c90d1e4b5a6","status":"PAYLOAD_TOO_LARGE"}}},"exampleType":"examples"}},"exampleType":"examples"},"928345e2-0309-4fdf-8241-511d7b7d0d27":{"description":"Request `Content-Type` is missing or not JSON (`application/json` or `application/*+json`), or the body has a `Content-Encoding` other than `gzip` (the message says which)","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"Error body of every `/v3/routing/*` endpoint.\n\n`status` is the HTTP status as text, `code` says what kind of failure it\nis, `request_id` identifies the request, and `errors` holds one item per\nproblem found in the request. Branch on `code`, and on `errors[].code` for\n400s; the messages are for people.","required":["status","code","message"],"properties":{"code":{"type":"string","description":"What kind of failure this is. One value per HTTP status class.","x-extensible-enum":["invalid_request","feature_not_enabled","payload_too_large","unsupported_media_type","internal","travel_provider_error","overloaded"],"isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable summary. With exactly one item it is that item's\nmessage; with several, `\"{n} problems in request\"` (at most 100 items\nare listed, and the message says when the list is cut).","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"status":{"type":"string","description":"The HTTP status as text, e.g. `\"BAD_REQUEST\"` or\n`\"SERVICE_UNAVAILABLE\"`.","example":"BAD_REQUEST","isRequired":true,"uniqueKey":"status","typeLabel":"string"},"errors":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"errors.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"description":"One entry per problem found in the request. Empty for non-input errors.","uniqueKey":"errors","typeLabel":"object[]"},"request_id":{"oneOf":[{"type":"string","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"request_id","typeLabel":"string | null"}},"example":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"},"uniqueKey":"","typeLabel":"object"},"example":{"code":"unsupported_media_type","message":"Expected request with `Content-Type: application/json`","request_id":"req_7f3a2c90d1e4b5a6","status":"UNSUPPORTED_MEDIA_TYPE"},"examples":{"Example":{"title":"Example","value":{"code":"unsupported_media_type","message":"Expected request with `Content-Type: application/json`","request_id":"req_7f3a2c90d1e4b5a6","status":"UNSUPPORTED_MEDIA_TYPE"}}},"exampleType":"examples"}},"exampleType":"examples"},"319b651a-3d91-4499-b8b1-85e399ed3ca9":{"description":"Rate limited. Returned by the API gateway before the request reaches the solver, so it does not use the `ErrorBody` shape. Back off and retry.","content":{"_mintlify/placeholder":{"schema":{"type":"object","description":""}}}},"524bb7f4-078c-4bfe-8cad-2f9140f462a8":{"description":"Server-side error (`code: internal`).","headers":{"x-request-id":{"schema":{"type":"string"},"description":"The request's `X-Request-Id`, echoed, or a generated `req_…` id."}},"content":{"application/json":{"schema":{"type":"object","description":"Error body of every `/v3/routing/*` endpoint.\n\n`status` is the HTTP status as text, `code` says what kind of failure it\nis, `request_id` identifies the request, and `errors` holds one item per\nproblem found in the request. Branch on `code`, and on `errors[].code` for\n400s; the messages are for people.","required":["status","code","message"],"properties":{"code":{"type":"string","description":"What kind of failure this is. One value per HTTP status class.","x-extensible-enum":["invalid_request","feature_not_enabled","payload_too_large","unsupported_media_type","internal","travel_provider_error","overloaded"],"isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable summary. With exactly one item it is that item's\nmessage; with several, `\"{n} problems in request\"` (at most 100 items\nare listed, and the message says when the list is cut).","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"status":{"type":"string","description":"The HTTP status as text, e.g. `\"BAD_REQUEST\"` or\n`\"SERVICE_UNAVAILABLE\"`.","example":"BAD_REQUEST","isRequired":true,"uniqueKey":"status","typeLabel":"string"},"errors":{"type":"array","items":{"type":"object","description":"One problem in a request.","required":["code","message"],"properties":{"code":{"type":"string","description":"What is wrong.","x-extensible-enum":["invalid_json","invalid_type","unknown_field","missing_field","invalid_value","not_supported","out_of_range","duplicate_id","unknown_reference","conflicting_fields","limit_exceeded"],"isRequired":true,"uniqueKey":"errors.items.[INDEX].code","typeLabel":"string"},"message":{"type":"string","description":"Human-readable description.","isRequired":true,"uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"actual":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the count this request has.","minimum":0,"uniqueKey":"errors.items.[INDEX].actual.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].actual","typeLabel":"integer\u003cint64> | null"},"limit":{"oneOf":[{"type":"integer","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.0","typeLabel":"integer\u003cint64>"},{"type":"null","format":"int64","description":"`limit_exceeded` only: the published cap.","minimum":0,"uniqueKey":"errors.items.[INDEX].limit.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].limit","typeLabel":"integer\u003cint64> | null"},"pointer":{"oneOf":[{"type":"string","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.0","typeLabel":"string"},{"type":"null","description":"RFC 6901 JSON Pointer into the request body, when the problem has a\nlocation. It is relative to the root of the body, so a field of the\nproblem reads `/problem/...` (e.g.\n`\"/problem/vehicles/0/shifts/0/from\"`).","uniqueKey":"errors.items.[INDEX].pointer.oneOf.1","typeLabel":"null"}],"uniqueKey":"errors.items.[INDEX].pointer","typeLabel":"string | null"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"description":"One entry per problem found in the request. Empty for non-input errors.","uniqueKey":"errors","typeLabel":"object[]"},"request_id":{"oneOf":[{"type":"string","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.0","typeLabel":"string"},{"type":"null","description":"The `X-Request-Id` of the request (echoed, or generated when absent).","uniqueKey":"request_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"request_id","typeLabel":"string | null"}},"example":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"code":"invalid_request","errors":[{"code":"out_of_range","message":"depot 'gent': service_duration_s must be >= 0, got -60","pointer":"/problem/depots/0/service_duration_s"}],"message":"depot 'gent': service_duration_s must be >= 0, got -60","request_id":"req_7f3a2c90d1e4b5a6","status":"BAD_REQUEST"}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"9ccad23f-2998-47f5-b1b2-2885a0d8c12b":{"apiKey":{"type":"apiKey","in":"header","name":"Authorization","scopes":[],"schemeName":"apiKey"}}},"servers":{"201228c4-350a-441d-b6ae-257ddac506eb":{"url":"https://api.solvice.io","description":"Production — Solvice API gateway"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"Authorization","scopes":[],"schemeName":"apiKey"},"schema":{"title":"Authorization","type":"string","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"apiKey","name":"Authorization"}],"title":"apiKey"}]},"originalFileLocation":"api-reference/vrp-v3.json"},"subdomain":"solvice-68592f22","siteName":"Solvice Docs","title":"Validate suggest - Solvice Docs","navMaps":{"firstHrefInVersion":{"v3":{"href":"/api-reference/vrp/v3/validate-suggest","matchLevel":0},"v2":{"href":"/guides/platform/platform","matchLevel":4}},"firstHrefInLanguage":{}},"lastModified":"2026-10-29T08:47:33.261Z","originalFileLocation":"api-reference/vrp/v3/validate-suggest.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Check a suggest request without running it\">\u003cmeta data-mint-head name=\"keywords\" content=\"Route Optimization, Route API, Optimization API, Workforce Scheduling, Solvice\">\u003cmeta data-mint-head name=\"application-name\" content=\"Solvice Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"index, follow\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Validate suggest - Solvice Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"Check a suggest request without running it\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Solvice Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://solvice-68592f22.mintlify.app/link to your default meta tag image\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Validate suggest - Solvice Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Check a suggest request without running it\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://solvice-68592f22.mintlify.app/link to your default meta tag image\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/solvice-68592f22/wZOj_k-mDHXJa5jh/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Solvice Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0f62fe\">\u003cmeta data-mint-head name=\"charset\" content=\"UTF-8\">\u003cmeta data-mint-head name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\u003cmeta data-mint-head name=\"author\" content=\"Christophe Van Huele\">\u003cmeta data-mint-head name=\"googlebot\" content=\"index, follow\">\u003cmeta data-mint-head name=\"google\" content=\"notranslate\">\u003cmeta data-mint-head name=\"google-site-verification\" content=\"verification_token\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/vrp/v3/validate-suggest.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.solvice.io/#organization\",\"name\":\"Solvice Docs\",\"url\":\"https://docs.solvice.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/solvice-68592f22/1KJ_2AIotizI1Bng/logo/light.svg?fit=max\u0026auto=format\u0026n=1KJ_2AIotizI1Bng\u0026q=85\u0026s=e93560fee320491613107060a1afc094\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.solvice.io#website\",\"name\":\"Solvice Docs\",\"url\":\"https://docs.solvice.io\",\"publisher\":{\"@id\":\"https://docs.solvice.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest#webpage\",\"url\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest\",\"name\":\"Validate suggest\",\"description\":\"Check a suggest request without running it\",\"dateModified\":\"2026-10-29T08:47:33.261Z\",\"isPartOf\":{\"@id\":\"https://docs.solvice.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Routing API\",\"item\":\"https://docs.solvice.io/api-reference/vrp/v3/introduction\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Validate\",\"item\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-solve\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Validate suggest\",\"item\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest#apireference\",\"headline\":\"Validate suggest\",\"name\":\"Validate suggest\",\"description\":\"Check a suggest request without running it\",\"url\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest\",\"mainEntityOfPage\":{\"@id\":\"https://docs.solvice.io/api-reference/vrp/v3/validate-suggest#webpage\"},\"image\":\"https://docs.solvice.io/link%20to%20your%20default%20meta%20tag%20image\",\"dateModified\":\"2026-10-29T08:47:33.261Z\",\"publisher\":{\"@id\":\"https://docs.solvice.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.solvice.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Solvice Docs\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Solvice Docs","nav":{"global":{"anchors":[{"anchor":"Dashboard","icon":"book-open-cover","href":"https://platform.solvice.io"},{"anchor":"Website","icon":"planet-ringed","href":"https://www.solvice.io"},{"anchor":"Blog","icon":"newspaper","href":"https://www.solvice.io/blog/news"}]},"versions":[{"version":"v3","tabs":[{"tab":"Guides","pages":[{"title":"Guides","href":"/guides/platform/platform"}]},{"tab":"API Reference","groups":[{"group":"Routing API","pages":[{"title":"Introduction","href":"/api-reference/vrp/v3/introduction"},{"title":"OpenAPI specification","href":"/api-reference/vrp/v3/openapi"},{"group":"Endpoints","pages":[{"title":"Solve","openapi":"vrp-v3 POST /v3/routing/solve","href":"/api-reference/vrp/v3/solve"},{"title":"Evaluate","openapi":"vrp-v3 POST /v3/routing/evaluate","href":"/api-reference/vrp/v3/evaluate"},{"title":"Suggest","openapi":"vrp-v3 POST /v3/routing/suggest","href":"/api-reference/vrp/v3/suggest"}]},{"group":"Validate","pages":[{"title":"Validate solve","openapi":"vrp-v3 POST /v3/routing/validate/solve","href":"/api-reference/vrp/v3/validate-solve"},{"title":"Validate evaluate","openapi":"vrp-v3 POST /v3/routing/validate/evaluate","description":"Check a evaluate request without running it","href":"/api-reference/vrp/v3/validate-evaluate"},{"title":"Validate suggest","openapi":"vrp-v3 POST /v3/routing/validate/suggest","href":"/api-reference/vrp/v3/validate-suggest"}]},{"group":"Async runs","pages":[{"title":"Submit a run","openapi":"vrp-v3-runs POST /v3/routing/runs","description":"Submit a routing problem to solve in the background","href":"/api-reference/vrp/v3/runs-submit"},{"title":"Run status","openapi":"vrp-v3-runs GET /v3/routing/runs/{id}","href":"/api-reference/vrp/v3/runs-status"},{"title":"Run result","openapi":"vrp-v3-runs GET /v3/routing/runs/{id}/result","href":"/api-reference/vrp/v3/runs-result"},{"title":"Cancel a run","openapi":"vrp-v3-runs POST /v3/routing/runs/{id}/cancel","href":"/api-reference/vrp/v3/runs-cancel"}]}]}]},{"tab":"Changelog","pages":[{"title":"Changelog","href":"/changelog/vrp-v3"}]}]},{"version":"v2","default":true,"pages":[{"title":"v2","href":"/guides/platform/platform"}]}]},"title":"Validate suggest - Solvice Docs","buildId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","deploymentId":"dpl_2xiSHD9XEvLsPGPcfoMtkLTB3dy9","dynamics":["c2aa737661","b0f84f53ff","a9bb46feb3","2b790eda92"],"chunks":["OpenApiReferenceProvider-DmVyH30O.js","utils-BHQqGGOd.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-CD-E4BIt.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Bp5Lq9Ds.js","snippetPresets-C4xAVCFP.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","Page-CBCH2P7b.js","ApiExamples-CgXVLxUC.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-BF8I5oUf.js","shallow-Byd0lWnC.js","getApiPlaygroundDisplay-BGOZG1OK.js","CodeSnippet-CpvQL0CY.js","CodeSnippets-B8wkBKXa.js","getPastedJson-Ry3scI3Y.js","icon-D7a9HcdD.js","MethodPill-CJ8pmHhz.js","DuplicateIcon-rh1HJF0t.js","createIcon-DvGznqYs.js","DynamicMarkdown-Cc6AuSHS.js","SectionHeading-B4A0S-ep.js","axios-vUo_bRtp.js","Markdown-Cc16CX65.js","clsx-Cs6nMGht.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-zbf22OZA.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-C_fs-y5n.js"]}