DevelopersAPI reference

Dispatch API

REST endpoints for dispatch in ServFlo: 6 operations with parameters, request and response fields, permissions and curl examples.

Base URL: https://app.servflo.ai/api. Every call needs Authorization: Bearer sfk_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.

OperationEndpointRisk
The dispatch board for a dayGET /organizations/{organizationId}/dispatchread
Plan a technician's route (nearest-next)GET /organizations/{organizationId}/dispatch/routeread
Save a technician's route orderPOST /organizations/{organizationId}/dispatch/routewrite
Business address and travel speedGET /organizations/{organizationId}/dispatch-settingsread
Change the business address or travel speedPATCH /organizations/{organizationId}/dispatch-settingswrite
Where the technicians areGET /organizations/{organizationId}/dispatch/locationsread

The dispatch board for a day

GET /organizations/{organizationId}/dispatch

Everything the dispatch board draws for days days from date: active technicians (working hours, home base), every visit on those days with status, field times, customer, service, property coordinates and crew; unscheduled (open visits without a date, or without a crew after the shown days) and requests (NEW requests awaiting an assessment, only for roles that may read requests); and the business address and travel speed. A technician gets only their own row (ownRowOnly), with no unscheduled work or requests. Read-only. Move visits with POST /jobs/{jobId}/visits/{visitId}/move.

Permissionschedule.read (Owner, Admin, Dispatcher, Technician, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP tooldispatch_board (toolset scheduling)

Parameters

NameInTypeRequiredDescription
datequerystringNoThe first day shown, YYYY-MM-DD. Defaults to today in the organization's timezone.
daysqueryintegerNoHow many days, 1–7. Default 1.
businessUnitIdquerystringNoOnly this business unit's work and the technicians who may work for it (GET /business-units).

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
datesarray of string
organizationobject
organization.addressstring or null
organization.citystring or null
organization.latitudenumber or null
organization.longitudenumber or null
organization.travelSpeedKmhinteger
ownRowOnlybooleanTrue for a technician: only their own row is included.
techniciansarray of object
technicians[].idstring
technicians[].namestring
technicians[].colorstring
technicians[].workStartTimestring
technicians[].workEndTimestring
technicians[].homeAddressstring or null
technicians[].homeLatitudenumber or null
technicians[].homeLongitudenumber or null
technicians[].homeBusinessUnitIdstring or nullTheir home business unit.
visitsarray of object
visits[].idstring
visits[].jobIdstring
visits[].scheduledDatestring or nullYYYY-MM-DD; null = not scheduled yet.
visits[].scheduledTimestring or null
visits[].durationMinutesinteger
visits[].statusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
visits[].notesstring or null
visits[].sortOrderinteger
visits[].routeOrderinteger or nullPosition in the technician's route for the day (Optimize route); null = by time.
visits[].onMyWayAtstring (date-time) or null
visits[].arrivedAtstring (date-time) or null
visits[].startedAtstring (date-time) or null
visits[].completedAtstring (date-time) or null
visits[].createdAtstring (date-time)
visits[].updatedAtstring (date-time)
visits[].crewarray of objectTechnicians on the visit, lead first.
visits[].crew[].technicianIdstring
visits[].crew[].isLeadbooleanThe lead runs the visit; the job's technician is its lead.
visits[].crew[].namestring
visits[].crew[].colorstring
visits[].identifierstring
visits[].jobStatusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
visits[].priorityenumOne of LOW, NORMAL, HIGH, URGENT.
visits[].addressstring or null
visits[].customerobject
visits[].customer.idstring
visits[].customer.namestring
visits[].customer.phonestring or null
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].businessUnitobject or nullThe job's business unit.
visits[].businessUnit.idstring
visits[].businessUnit.namestring
visits[].propertyobject or null
visits[].property.idstring
visits[].property.namestring or null
visits[].property.addressstring or null
visits[].property.citystring or null
visits[].property.latitudenumber or null
visits[].property.longitudenumber or null
visits[].visitCountintegerHow many visits the job has.
visits[].membershipobject or nullSet when the customer is a member: the membership covering this job, with dueMonth when the job is an included member visit.
visits[].membership.membershipIdstring
visits[].membership.identifierstringMEM-n
visits[].membership.planNamestring
visits[].membership.prioritybooleanThe plan flags its members' work as priority on the board.
visits[].membership.dueMonthstring or nullYYYY-MM when the job is an included member visit; null for other work for a member.
visits[].membership.dueDatestring or nullYYYY-MM-DD when the member visit is on a week cadence (every N weeks); null for month-based visits.
visits[].technicianIdstring or nullThe visit's lead technician.
unscheduledarray of object
unscheduled[].idstring
unscheduled[].jobIdstring
unscheduled[].scheduledDatestring or nullYYYY-MM-DD; null = not scheduled yet.
unscheduled[].scheduledTimestring or null
unscheduled[].durationMinutesinteger
unscheduled[].statusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
unscheduled[].notesstring or null
unscheduled[].sortOrderinteger
unscheduled[].routeOrderinteger or nullPosition in the technician's route for the day (Optimize route); null = by time.
unscheduled[].onMyWayAtstring (date-time) or null
unscheduled[].arrivedAtstring (date-time) or null
unscheduled[].startedAtstring (date-time) or null
unscheduled[].completedAtstring (date-time) or null
unscheduled[].createdAtstring (date-time)
unscheduled[].updatedAtstring (date-time)
unscheduled[].crewarray of objectTechnicians on the visit, lead first.
unscheduled[].crew[].technicianIdstring
unscheduled[].crew[].isLeadbooleanThe lead runs the visit; the job's technician is its lead.
unscheduled[].crew[].namestring
unscheduled[].crew[].colorstring
unscheduled[].identifierstring
unscheduled[].jobStatusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
unscheduled[].priorityenumOne of LOW, NORMAL, HIGH, URGENT.
unscheduled[].addressstring or null
unscheduled[].customerobject
unscheduled[].customer.idstring
unscheduled[].customer.namestring
unscheduled[].customer.phonestring or null
unscheduled[].serviceTypeobject or null
unscheduled[].serviceType.idstring
unscheduled[].serviceType.namestring
unscheduled[].serviceType.colorstring
unscheduled[].businessUnitobject or nullThe job's business unit.
unscheduled[].businessUnit.idstring
unscheduled[].businessUnit.namestring
unscheduled[].propertyobject or null
unscheduled[].property.idstring
unscheduled[].property.namestring or null
unscheduled[].property.addressstring or null
unscheduled[].property.citystring or null
unscheduled[].property.latitudenumber or null
unscheduled[].property.longitudenumber or null
unscheduled[].visitCountintegerHow many visits the job has.
unscheduled[].membershipobject or nullSet when the customer is a member: the membership covering this job, with dueMonth when the job is an included member visit.
unscheduled[].membership.membershipIdstring
unscheduled[].membership.identifierstringMEM-n
unscheduled[].membership.planNamestring
unscheduled[].membership.prioritybooleanThe plan flags its members' work as priority on the board.
unscheduled[].membership.dueMonthstring or nullYYYY-MM when the job is an included member visit; null for other work for a member.
unscheduled[].membership.dueDatestring or nullYYYY-MM-DD when the member visit is on a week cadence (every N weeks); null for month-based visits.
unscheduled[].technicianIdstring or nullThe visit's lead technician.
requestsarray of object
requests[].idstring
requests[].identifierstring
requests[].contactNamestring or null
requests[].descriptionstring
requests[].preferredDatestring or null
requests[].preferredTimeWindowstring
requests[].addressstring or null
requests[].createdAtstring (date-time)
requests[].customerobject or null
requests[].customer.idstring
requests[].customer.namestring
requests[].serviceTypeobject or null
requests[].serviceType.idstring
requests[].serviceType.namestring
requests[].serviceType.colorstring
requests[].propertyobject or null
requests[].property.idstring
requests[].property.namestring or null
requests[].property.addressstring or null
requests[].property.citystring or null
requests[].property.latitudenumber or null
requests[].property.longitudenumber or null

Plan a technician's route (nearest-next)

GET /organizations/{organizationId}/dispatch/route

Proposes a driving order for a technician's visits on date without saving anything: nearest-next from their home base (else the business address), with the straight-line km of the current and the proposed order and the start times the proposed order would get (leaving at startTime, default their working-hours start, travelling at the business's average speed). Visits without coordinates go last. Save it with POST /dispatch/route. A technician may plan only their own day. Read-only.

Permissionschedule.read (Owner, Admin, Dispatcher, Technician, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP tooldispatch_planRoute (toolset scheduling)

Parameters

NameInTypeRequiredDescription
technicianIdquerystringYesWhose day (GET /technicians/options).
datequerystringYesA calendar date in the business's own calendar, YYYY-MM-DD.
startTimequerystringNoWhen the day starts; defaults to their working hours.

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch/route?technicianId=technician_id&date=2026-11-03" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
technicianIdstring
datestring
startobject or nullWhere the route starts; null when nothing is geocoded.
start.latitudenumber
start.longitudenumber
startSourceenum or nullOne of HOME, BUSINESS.
speedKmhnumber
startTimestring
stopsarray of object
stops[].visitIdstring
stops[].jobIdstring
stops[].identifierstring
stops[].customerNamestring
stops[].statusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
stops[].scheduledTimestring or null
stops[].durationMinutesinteger
stops[].routeOrderinteger or null
stops[].latitudenumber or null
stops[].longitudenumber or null
currentobject
current.visitIdsarray of string
current.totalKmnumber
optimizedobject
optimized.visitIdsarray of string
optimized.totalKmnumber
optimized.timesarray of object
optimized.times[].idstring
optimized.times[].scheduledTimestring
optimized.times[].travelMinutesinteger
missingCoordinatesintegerVisits without coordinates (placed last).

Save a technician's route order

POST /organizations/{organizationId}/dispatch/route

Saves the driving order of a technician's visits on date (visitIds: all of that day's visits, in order) as routeOrder 1..n, which My day follows. With retime, scheduled and confirmed visits also get sequential start times (durations kept, travel buffers at the business's average speed from GET /dispatch-settings). 409 when the day's visits changed since GET /dispatch/route. Nothing is sent to anyone.

Permissionjobs.assign (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP tooldispatch_applyRoute (toolset scheduling)

Request body

FieldTypeRequiredDescription
technicianIdstringYes
datestringYesA calendar date in the business's own calendar, YYYY-MM-DD.
visitIdsarray of stringYesEvery visit of that day, in driving order. Up to 100 items.
retimebooleanNoAlso re-time the visits sequentially.
startTimestringNoWhen the day starts; defaults to their working hours.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch/route" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"technicianId":"technician_id","date":"2026-11-03","visitIds":["visit_id"]}'

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
idstring
jobIdstring
scheduledDatestring or nullYYYY-MM-DD; null = not scheduled yet.
scheduledTimestring or null
durationMinutesinteger
statusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
notesstring or null
sortOrderinteger
routeOrderinteger or nullPosition in the technician's route for the day (Optimize route); null = by time.
onMyWayAtstring (date-time) or null
arrivedAtstring (date-time) or null
startedAtstring (date-time) or null
completedAtstring (date-time) or null
createdAtstring (date-time)
updatedAtstring (date-time)
crewarray of objectTechnicians on the visit, lead first.
crew[].technicianIdstring
crew[].isLeadbooleanThe lead runs the visit; the job's technician is its lead.
crew[].namestring
crew[].colorstring
identifierstring
jobStatusenumOne of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
priorityenumOne of LOW, NORMAL, HIGH, URGENT.
addressstring or null
customerobject
customer.idstring
customer.namestring
customer.phonestring or null
serviceTypeobject or null
serviceType.idstring
serviceType.namestring
serviceType.colorstring
businessUnitobject or nullThe job's business unit.
businessUnit.idstring
businessUnit.namestring
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
property.latitudenumber or null
property.longitudenumber or null
visitCountintegerHow many visits the job has.
membershipobject or nullSet when the customer is a member: the membership covering this job, with dueMonth when the job is an included member visit.
membership.membershipIdstring
membership.identifierstringMEM-n
membership.planNamestring
membership.prioritybooleanThe plan flags its members' work as priority on the board.
membership.dueMonthstring or nullYYYY-MM when the job is an included member visit; null for other work for a member.
membership.dueDatestring or nullYYYY-MM-DD when the member visit is on a week cadence (every N weeks); null for month-based visits.
technicianIdstring or nullThe visit's lead technician.

Business address and travel speed

GET /organizations/{organizationId}/dispatch-settings

The business address (every technician's route starts here unless they have a home base; the weather forecast point) with its coordinates and how close they are (locationPrecision), and the average travel speed in km/h used for travel buffers when re-timing a route. Read-only.

Permissionsettings.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP tooldispatchSettings_get (toolset settings)

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch-settings" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
addressstring or null
citystring or null
statestring or null
zipstring or null
countrystring or null
latitudenumber or null
longitudenumber or null
locationPrecisionstring or nullHow close the coordinates are: ADDRESS (the address itself), STREET (its street: the map has no house number there), AREA (its town or ZIP), PINNED (sent by hand); null when not on the map or located before this was recorded.
travelSpeedKmhinteger

Change the business address or travel speed

PATCH /organizations/{organizationId}/dispatch-settings

Sets the business address (Settings → Company profile; every route's default start and the weather forecast point) and the average travel speed (5–150 km/h). The address is geocoded after saving unless latitude/longitude are sent with it (then locationPrecision is PINNED); when the exact address is not on the map the street, then the town or ZIP, is used (locationPrecision says which). Any save while the address has no coordinates looks it up again. The configured geocoder may send the address to OpenStreetMap Nominatim. Send only what changes. Nothing is shown to customers.

Permissionsettings.manage (Owner, Admin)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP tooldispatchSettings_update (toolset settings)

Request body

FieldTypeRequiredDescription
addressstring or nullNoUp to 500 characters.
citystring or nullNoUp to 200 characters.
statestring or nullNoUp to 200 characters.
zipstring or nullNoUp to 50 characters.
countrystring or nullNoUp to 200 characters.
latitudenumber or nullNoPin by hand (WGS84). -90–90.
longitudenumber or nullNo-180–180.
travelSpeedKmhintegerNo5–150.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch-settings" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"address":"string","city":"string","state":"string"}'

Response

200: the answer's fields
FieldTypeDescription
addressstring or null
citystring or null
statestring or null
zipstring or null
countrystring or null
latitudenumber or null
longitudenumber or null
locationPrecisionstring or nullHow close the coordinates are: ADDRESS (the address itself), STREET (its street: the map has no house number there), AREA (its town or ZIP), PINNED (sent by hand); null when not on the map or located before this was recorded.
travelSpeedKmhinteger

Where the technicians are

GET /organizations/{organizationId}/dispatch/locations

Each technician's last shared position (only while they were on the clock or on the way), with when and whether it is live (sent in the last 10 minutes). For the dispatch map. Read-only.

Permissionjobs.assign (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP tooltracking_team (toolset scheduling)

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/dispatch/locations" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
technicianIdstring
latitudenumber
longitudenumber
accuracyMnumber or nullAccuracy in metres.
headingDegnumber or null
recordedAtstring (date-time)When the phone took the position.
technicianobject
technician.namestring
technician.colorstring
livebooleanSent in the last 10 minutes.

On this page