Optimization API
A solverSolverThe optimizer that assigns and sequences a set of tasks across a set of resources automatically, weighing skills, travel time and availability. It is a licensed module and produces a proposal, not a change. takes a set of resourcesResourceAn entity that can carry out work - a person, vehicle, tool, or room - that you schedule on the planning board., a window and the work that has to fit in it, and comes back with a plan: which resource does what, when, and in which order. Dispatchers start one from the planning board and review the outcome on the solver runs page; an AI agent can start one through the MCP optimization tools. The optimization endpoints are the third entry point, for integrations that want to trigger a run from a workflow of their own, say every evening for the next day, or when a batch of orders lands from the back office.
Whichever entry point starts it, a run is recorded as a solver runSolver runOne execution of the solver, listed on the solver runs page with its scores, status and the before-and-after of every appointment it touched. A run reaches the board only when a planner applies it., so a run started from the API shows up on the solver runs page like any other.
There are three solvers, each with its own endpoint:
| Endpoint | Solver | Problem it solves |
|---|---|---|
POST /optimization/fieldService | Field service | Routes: assigns and sequences appointmentsAppointmentA task scheduled to a resource for a specific period - the scheduled instance you see on the planning board. across several resources and days to minimize travel timeTravel timeThe time needed to get from one appointment to the next, calculated from their locations. The planning board can show it in front of each appointment and fold it into the schedule. and distance (a vehicle routing problem). |
POST /optimization/professionalServices | Professional services | Assignment: spreads tasksTaskA unit of work that belongs to a job. It appears in the open task list until it is scheduled to a resource. over resources and time by availability and requirements, where travel plays no role. |
POST /optimization/dailyRoute | Daily route | Sequence: reorders one resource's appointments on one day into the shortest routeRouteThe path between a set of stops drawn on the map, with travel time and distance per leg. The route sequence grid lists the same stops as rows. (a traveling salesman problem). |
Licenses and setup
The solvers are optional modules, and each endpoint checks the tenant's license before it does anything:
/optimization/fieldServicerequires the Field Service solver subscription./optimization/professionalServicesrequires the Professional Services solver subscription./optimization/dailyRouterequires the Advanced Map module.
A tenant without the subscription gets HTTP 403 with the title Solver not licensed (or Advanced map not available for the daily route). The field service and professional services solvers also need the solver API key to be configured in Application Setup; without it the call fails with HTTP 500 and the message Solver API key not configured.
Request
The field service and professional services requests share most of their shape:
| Name | Data Type | Default | Required | Description |
|---|---|---|---|---|
| startDate | string (date) | ✔️ | Start of the window the solver may plan into. | |
| endDate | string (date) | ✔️ | End of the window. | |
| resources | string[] | ✔️ | Resource numbers the solver may plan onto. At least one must exist. | |
| items | object[] | The work to hand the solver, see below. | ||
| options.timeZone | string | Time zone the dates are interpreted in. Defaults to the caller's time zone, then to UTC. | ||
| options.termination | string | How long the solver may search, as an ISO 8601 duration. Capped by the server. | ||
| options.saveAndPublish | boolean | false | Also publish the changed appointments to every receiver, see Response. | |
| notificationEmail | string | Where to send the explanation when the problem turns out to be infeasible. | ||
| incrementalMode | boolean | false | Field service only. Keep the existing planning and only add the unplanned work around it. | |
| reassignment | object | Field service only, see below. |
Each entry in items names one piece of work:
| Name | Data Type | Default | Required | Description |
|---|---|---|---|---|
| type | string | ✔️ | APPOINTMENT, TASK or PLANNED_TASK. | |
| jobNo | string | With TASK and PLANNED_TASK: the job of the task. | ||
| taskNo | string | With TASK and PLANNED_TASK: the task. | ||
| appointmentGuid | string (uuid) | With APPOINTMENT: the appointment. |
A TASK is an open taskOpen taskA task that has not been scheduled yet. It waits in the open task list to be placed on the planning board. that still has to be planned; a PLANNED_TASK and an APPOINTMENT are work that is already on the board and may be moved. An item that cannot be found, or that lacks the identifier its type needs, fails the whole request with HTTP 400.
reassignment is for the field service solver and narrows a run to re-planning around one resource, the case where a technician calls in sick and their day has to be handed out:
| Name | Data Type | Default | Required | Description |
|---|---|---|---|---|
| mode | int | 0 keeps every appointment's date and time and only changes who does it; 1 keeps the resource and reshuffles that resource's appointments on the selected day. | ||
| originalResourceId | int | The resource whose work is being reassigned. | ||
| originalDateStart | string (date) | Start of the day or period being reassigned. | ||
| originalDateEnd | string (date) | End of that period. |
The daily route request is smaller, because the scope is one resource on one day:
| Name | Data Type | Default | Required | Description |
|---|---|---|---|---|
| date | string (date) | ✔️ | The day to reorder. | |
| resource | string | ✔️ | The resource number. | |
| options.timeZone | string | As above. | ||
| options.saveAndPublish | boolean | false | As above. |
Response
All three answer synchronously; the call returns when the solver is done, so allow for a request that takes longer than a normal API call. The response has the same shape for each:
| Name | Data Type | Description |
|---|---|---|
| success | boolean | Whether the solver found a plan. |
| errorMessage | string | Why it did not, when success is false. |
| optimizedAppointments | object[] | The proposed appointments, in the shape GET /appointment returns them. |
| totalTravelTime | int | Travel time of the proposed plan in seconds. Field service only. |
| totalDistance | int | Distance of the proposed plan in meters. Field service only. |
A run started from the API always applies its result: the appointments in the response have been written to the board by the time you receive them, the same as the Apply results automatically option of the in-product dialog. There is no review-first mode on the API; use the solver runs page when a dispatcher should confirm a plan before it lands. options.saveAndPublish controls what happens next. Left off, the appointments change on the board and in the response only. Switched on, the changes are also published to every receiver, which is the pipeline that tells the back officeBack officeThe ERP or business system Dime.Scheduler plans for - most often Microsoft Dynamics 365 Business Central. It owns the master data and remains authoritative over what it receives., connected clients and webhookWebhookThe generic connector that POSTs every appointment change as JSON to a URL you choose. It delivers the message and leaves interpretation to the receiving system. subscribers about an edit made on the board. Leave it off when your own system is the one that will read the response and does not need to hear about it twice.
When the hard constraints cannot all be satisfied, the field service and professional services solvers answer with HTTP 400 and send a detailed explanation to notificationEmail rather than returning a partial plan. Invalid input (an unknown resource, a bad time zone, an item that does not exist) is also answered with HTTP 400 and the reason in the problem body.
- API
- See
POST /optimization/fieldService,POST /optimization/professionalServicesandPOST /optimization/dailyRoutein the REST API reference. - Example body for
POST /optimization/fieldService:{"startDate": "2026-03-02T00:00:00","endDate": "2026-03-06T23:59:59","resources": ["LINDA", "JOHN"],"items": [{ "type": "TASK", "jobNo": "SVC001", "taskNo": "1000" },{ "type": "APPOINTMENT", "appointmentGuid": "ad37cfba-f502-4592-883d-4b10433722fe" }],"incrementalMode": true,"options": {"timeZone": "Europe/Brussels","saveAndPublish": false}} - Example body for
POST /optimization/dailyRoute:{"date": "2026-03-02","resource": "LINDA","options": { "timeZone": "Europe/Brussels" }}
Read more
- Solver runs, where dispatchers review and apply what a solver proposed
- MCP optimization tools, the same solvers driven by an AI agent
- Recommendation API, for finding a slot for one appointment rather than re-planning many