DevelopersAPI reference

Field app API

REST endpoints for field app in ServFlo: 8 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
Share where I amPOST /organizations/{organizationId}/field/locationwrite
The technician app's offline packetGET /organizations/{organizationId}/field/packetread
Send the office a lead from a jobPOST /organizations/{organizationId}/jobs/{jobId}/leadswrite
The leads I sentGET /organizations/{organizationId}/field/leadsread
The parts I asked forGET /organizations/{organizationId}/field/parts-requestsread
Ask the office for partsPOST /organizations/{organizationId}/field/parts-requestswrite
What my truck needsGET /organizations/{organizationId}/field/restockread
Send the customer the job's pay linkPOST /organizations/{organizationId}/jobs/{jobId}/pay-link/sendsensitive

Share where I am

POST /organizations/{organizationId}/field/location

The technician app sends its recent positions (oldest first or not; up to 100). Kept only while the caller is clocked in or on the way to a visit (sharing: false otherwise, and nothing is kept): the newest becomes their position on the office's map and the customer's tracking link, the rest their trail (two weeks).

Permissiontime.track.own (Owner, Admin, Dispatcher, Technician)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP tooltracking_share (toolset scheduling)

Request body

FieldTypeRequiredDescription
pingsarray of objectYesUp to 100 items.
pings[].latitudenumberYes-90–90.
pings[].longitudenumberYes-180–180.
pings[].accuracyMnumber or nullNo0–100000.
pings[].headingDegnumber or nullNo0–360.
pings[].speedMpsnumber or nullNo0–200.
pings[].atstring (date-time)Yes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/field/location" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pings":[{"latitude":1,"longitude":1,"at":"2026-11-03T15:00:00Z"}]}'

Response

200: the answer's fields
FieldTypeDescription
keptintegerPositions stored.
sharingbooleanWhether the technician shares their position now (on the clock or on the way).

The technician app's offline packet

GET /organizations/{organizationId}/field/packet

Everything the technician app keeps on the phone to work without signal: the caller's My day for today and tomorrow, each of those jobs in full (customer, property and access notes, equipment, checklist, notes, materials, forms with answers, invoices) with its pay-later link token, the pricebook at selling prices when the caller may quote, the shift clock, and the business's switches for quoting and collecting. A technician gets only their own jobs. Read-only; safe to call on every sync.

Permission: jobs.read (Owner, Admin, Dispatcher, Technician (own jobs), Member); risk read (OAuth scope servflo.read).

Permissionjobs.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolfieldApp_packet (toolset scheduling)

Example

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

Response

200: the answer's fields
FieldTypeDescription
generatedAtstringWhen the packet was built (ISO timestamp).
todaystringThe business's today, YYYY-MM-DD.
timeZonestring
daysanyMy day for today and tomorrow, as GET /my-day returns it: the caller's visits in route order.
jobsarray of objectEvery job on those days, as GET /jobs/{jobId} returns it, with its forms.
jobs[].idstringJob id.
jobs[].organizationIdstring
jobs[].identifierstringJOB-n, unique per organization.
jobs[].customerIdstring
jobs[].propertyIdstring or null
jobs[].assetIdstring or nullThe equipment worked on.
jobs[].technicianIdstring or nullThe lead technician of the next open visit.
jobs[].serviceTypeIdstring or null
jobs[].statusenumSCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED or CANCELLED. A job's status is its next open visit's. One of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
jobs[].priorityenumOne of LOW, NORMAL, HIGH, URGENT.
jobs[].scheduledDatestringThe next open visit's day, YYYY-MM-DD.
jobs[].scheduledTimestring or nullHh: MM
jobs[].durationMinutesinteger
jobs[].priceCentsintegerJob price before tax, in integer cents.
jobs[].addressstring or null
jobs[].notesstring or null
jobs[].completionNotesstring or nullWhat was done.
jobs[].recurrenceIntervalenum or nullOne of WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, YEARLY.
jobs[].recurrenceParentIdstring or null
jobs[].onMyWayAtstring (date-time) or null
jobs[].arrivedAtstring (date-time) or null
jobs[].startedAtstring (date-time) or null
jobs[].completedAtstring (date-time) or null
jobs[].signedBystring or nullWho signed the work off on site.
jobs[].signedAtstring (date-time) or null
jobs[].businessUnitIdstring or null
jobs[].customFieldsanyCustom field values by key (definitions: GET /custom-fields?entity=JOB).
jobs[].weatherSensitiveboolean or nullPlans around the weather: overrides the service type; null follows it.
jobs[].createdAtstring (date-time)
jobs[].updatedAtstring (date-time)
jobs[].customerobject
jobs[].customer.idstringCustomer id.
jobs[].customer.namestring
jobs[].customer.phonestring or null
jobs[].technicianobject or null
jobs[].technician.idstringTechnician id (GET /technicians).
jobs[].technician.namestring
jobs[].technician.colorstringCalendar colour, #rrggbb.
jobs[].serviceTypeobject or null
jobs[].serviceType.idstring
jobs[].serviceType.namestring
jobs[].serviceType.colorstring
jobs[].businessUnitobject or nullThe business unit.
jobs[].businessUnit.idstring
jobs[].businessUnit.namestring
jobs[].assetobject or null
jobs[].asset.idstring
jobs[].asset.namestring
jobs[].asset.serialNumberstring
jobs[].propertyobject or null
jobs[].property.idstringProperty id.
jobs[].property.namestring or null
jobs[].property.addressstring or null
jobs[].property.citystring or null
jobs[].property.taxRatenumber or null
jobs[].property.gateCodestring or null
jobs[].property.accessInstructionsstring or null
jobs[].property.safetyNotesstring or null
jobs[].property.petsOnSiteboolean
jobs[].property.petNotesstring or null
jobs[].property.contactNamestring or null
jobs[].property.contactPhonestring or null
jobs[].property.latitudenumber or null
jobs[].property.longitudenumber or null
jobs[].nextJobIdstring or nullAfter an update: the next occurrence booked when a recurring job completed.
jobs[].notesLogarray of objectInternal notes, newest first.
jobs[].notesLog[].idstringJob note id.
jobs[].notesLog[].jobIdstring
jobs[].notesLog[].contentstring
jobs[].notesLog[].authorUserIdstring or null
jobs[].notesLog[].createdAtstring (date-time)
jobs[].checklistarray of object
jobs[].checklist[].idstringChecklist item id.
jobs[].checklist[].jobIdstring
jobs[].checklist[].labelstring
jobs[].checklist[].checkedboolean
jobs[].checklist[].sortOrderinteger
jobs[].materialsarray of object
jobs[].materials[].idstringMaterial line id.
jobs[].materials[].jobIdstring
jobs[].materials[].materialIdstring or null
jobs[].materials[].pricebookItemIdstring or null
jobs[].materials[].descriptionstring or null
jobs[].materials[].unitstring or null
jobs[].materials[].quantitynumber
jobs[].materials[].unitCostCentsintegerThe unit PRICE billed for this line (the original API's name), in integer cents.
jobs[].materials[].costCentsinteger or nullOur unit cost in cents (costing.read only).
jobs[].materials[].locationIdstring or nullThe stock location it was drawn from.
jobs[].materials[].createdAtstring (date-time)
jobs[].materials[].materialobjectThe original API's material shape; id null for a pricebook-only line.
jobs[].materials[].pricebookItemobject or null
jobs[].materials[].locationobject or null
jobs[].invoicesarray of objectInvoices for the job (INV-n).
jobs[].invoices[].idstring
jobs[].invoices[].identifierstringINV-n
jobs[].invoices[].statusenumDRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED.
jobs[].invoices[].totalCentsinteger
jobs[].quotesarray of objectQuotes the job came from (Q-n).
jobs[].quotes[].idstring
jobs[].quotes[].identifierstringQ-n
jobs[].quotes[].statusenumDRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (job or invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED.
jobs[].requestsarray of object
jobs[].requests[].idstring
jobs[].requests[].identifierstring
jobs[].assessmentRequestsarray of object
jobs[].assessmentRequests[].idstring
jobs[].assessmentRequests[].identifierstring
jobs[].visitsarray of objectThe job's visits in order.
jobs[].visits[].idstringVisit id (for /jobs/{jobId}/visits/{visitId}/…).
jobs[].visits[].jobIdstring
jobs[].visits[].scheduledDatestring or nullYYYY-MM-DD; null = not scheduled yet.
jobs[].visits[].scheduledTimestring or nullHh: MM
jobs[].visits[].durationMinutesinteger
jobs[].visits[].statusenumSCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED or CANCELLED. A job's status is its next open visit's. One of SCHEDULED, CONFIRMED, IN_PROGRESS, COMPLETED, CANCELLED.
jobs[].visits[].notesstring or null
jobs[].visits[].sortOrderinteger
jobs[].visits[].routeOrderinteger or null
jobs[].visits[].onMyWayAtstring (date-time) or null
jobs[].visits[].trackingTokenstring or nullThe customer's tracking link token (/t/{token}), made on On my way.
jobs[].visits[].arrivedAtstring (date-time) or null
jobs[].visits[].startedAtstring (date-time) or null
jobs[].visits[].completedAtstring (date-time) or null
jobs[].visits[].createdAtstring (date-time)
jobs[].visits[].updatedAtstring (date-time)
jobs[].visits[].crewarray of objectTechnicians on the visit, lead first.
jobs[].formsanyThe job's forms with their fields, answers, status and missing required fields (as GET /jobs/{jobId}/forms).
jobs[].photoCountinteger
jobs[].membershipobject or nullThe Member badge: the customer's membership that covers the job.
jobs[].membership.membershipIdstring
jobs[].membership.identifierstringMEM-n
jobs[].membership.planNamestring
jobs[].membership.prioritybooleanThe plan flags its members' work as priority on the board.
jobs[].membership.dueMonthstring or nullYYYY-MM when the job is an included member visit; null for other work for a member.
jobs[].membership.dueDatestring or nullYYYY-MM-DD when the member visit is on a week cadence (every N weeks); null for month-based visits.
jobs[].payTokenstringThe job's pay-later link token (/p/{token}).
jobs[].backgroundanyWhy the technician is going: the request, the quote sold, recent visits, equipment and contacts.
pricebookarray of objectActive pricebook items for quoting offline (empty when the caller cannot quote).
pricebook[].idstringPricebook item id.
pricebook[].kindenumOne of SERVICE, MATERIAL, EQUIPMENT, FEE.
pricebook[].codestring or null
pricebook[].namestring
pricebook[].descriptionstring or null
pricebook[].unitstring
pricebook[].categoryIdstring or null
pricebook[].priceCentsintegerSelling price in cents.
pricebook[].memberPriceCentsinteger or null
pricebook[].taxableboolean
pricebook[].imageIdstring or null
pricebook[].imageUrlstring or nullThe item's photo, valid for a short time.
clockanyThe caller's time clock (as GET /time/clock).
customFieldsanyCustom field definitions for jobs, visits and equipment (all types and each type's, equipmentTypeId); the values travel on each record's customFields.
equipmentTypesanyThe business's equipment types (id, name, icon, customerOwned, built-in columns and labels), for recording new equipment on site.
equipmentLabelsobjectWhat equipment is called here (e.g. Vehicle / Vehicles).
equipmentLabels.singularstring
equipmentLabels.pluralstring
switchesobject
switches.technicianQuotesboolean
switches.technicianPaymentsboolean
featuresobject
features.equipmentboolean
features.expensesboolean
features.timeTrackingbooleanThe clock (clock in, breaks, non-job time) is time tracking; without it only a running shift can be ended.
features.serviceReportsbooleanService reports can be filled in (Grow and Pro, or the add-on); without it they are read-only.
features.inventorybooleanMy truck and parts requests (inventory, Pro); without it the app hides them.
features.phonebooleanThe phone system add-on (numbers and calls).
payLinkBasestringThe pay-later link base URL; append the job's payToken.
accessobject
access.officebooleanSees the whole business (office mode).
access.technicianbooleanThe caller is a technician.
access.permissionsarray of stringThe caller's permissions: which actions the app offers.
signingTermsobjectWhat customers agree to when they sign on the phone.
signingTerms.signOffTermsstring
signingTerms.quoteTermsstring
signingTerms.membershipTermsstring
serviceReportsobjectService reports to fill offline; empty without serviceReports.read.
serviceReports.reportsanyThe service reports on these jobs as GET /service-reports/{reportId} returns them (sections, items with status and notes, findings with photos, settings with statuses and severities, release state), without client links, agreements or extra documents.
serviceReports.libraryanyThe comment library of those reports' templates (tagged to template items by itemIds), for searching and adding findings offline.
serviceReports.extraSectionsanyThe extra-section catalog (Detached garage, Well, Radon …: items, describe fields, comments) to add offline with serviceReports.addExtraSection; empty without reports.
serviceReports.agreementsanyPending and signed pre-service agreements of the jobs with reports: frozen wording (safe HTML) and its textHash, status, signer name and time. Never the drawn signature, IP or link. Sign on site with POST …/agreements/{agreementId}/sign and the textHash shown.
serviceReports.agreementDraftsanyFor a job with reports but no pending or signed agreement: the wording POST …/agreements would freeze now (agreementTemplateId, title, text, textHash), to show and sign offline; prepare it, then sign with that textHash (refused if it changed).
membershipPlansarray of objectPlans a technician can sell on site (empty otherwise).
membershipPlans[].idstringMembership plan id.
membershipPlans[].namestring
membershipPlans[].descriptionstring or null
membershipPlans[].priceCentsinteger
membershipPlans[].billingFrequencyenumOne of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
membershipPlans[].termMonthsinteger or null
membershipPlans[].autoRenewDefaultboolean
membershipPlans[].serviceDiscountPercentnumber
membershipPlans[].materialDiscountPercentnumber
membershipPlans[].priorityboolean
membershipPlans[].includedVisitCountinteger

Send the office a lead from a job

POST /organizations/{organizationId}/jobs/{jobId}/leads

A technician recommends work they saw on one of their jobs (an aging unit, a leak, an upgrade): creates a NEW request (source FIELD) for the job's customer and property, with the job, the technician and how soon (urgency: NOW unsafe or failing, SOON within weeks, LATER plan for it). The office sees it in Requests and quotes it. Technicians: their own jobs (404 otherwise). Returns the request.

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

Parameters

NameInTypeRequiredDescription
jobIdpathstringYes

Request body

FieldTypeRequiredDescription
descriptionstringYesUp to 5000 characters.
urgencyenumYesOne of NOW, SOON, LATER.
serviceTypeIdstring or nullNoFrom GET /service-types, when the technician knows it.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/jobs/{jobId}/leads" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"description":"string","urgency":"NOW"}'

Response

201: the answer's fields
FieldTypeDescription
idstringRequest id.
organizationIdstring
identifierstringREQ-n, unique per organization.
customerIdstring or nullNull while the request is from a new contact.
contactNamestring or null
contactCompanystring or null
contactPhonestring or null
contactEmailstring or null
propertyIdstring or null
addressstring or null
serviceTypeIdstring or null
descriptionstringWhat the customer asked for.
preferredDatestring or nullYYYY-MM-DD
alternateDatestring or nullYYYY-MM-DD
preferredTimeWindowenumOne of ANY, MORNING, AFTERNOON, EVENING.
bookedDatestring or nullOnline booking's slot day, YYYY-MM-DD.
bookedTimestring or nullHh: MM
bookedDurationMinutesinteger or null
bookedTechnicianIdstring or null
sourceenumWhere it came from: MANUAL (staff), ONLINE_BOOKING, PORTAL, FIELD (a technician's lead) or PHONE (taken by the AI receptionist on a call). One of MANUAL, ONLINE_BOOKING, PORTAL, FIELD, PHONE.
leadTechnicianIdstring or nullThe technician who sent a FIELD lead.
sourceJobIdstring or nullThe job a FIELD lead came from.
leadUrgencyenum or nullOne of NOW, SOON, LATER.
statusenumNEW → ASSESSMENT_SCHEDULED / QUOTED → CONVERTED (a job was booked), or ARCHIVED. One of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.
internalNotesstring or null
jobIdstring or nullThe job booked from it.
assessmentJobIdstring or nullThe on-site assessment job.
convertedAtstring (date-time) or null
archivedAtstring (date-time) or null
businessUnitIdstring or null
adCampaignIdstring or nullThe ad campaign that brought it; null when not from an ad.
createdAtstring (date-time)
updatedAtstring (date-time)
customerobject or null
customer.idstring
customer.namestring
propertyobject or null
property.idstringProperty id.
property.namestring or null
property.addressstring or null
property.citystring or null
serviceTypeobject or null
serviceType.idstring
serviceType.namestring
serviceType.colorstring
businessUnitobject or nullThe business unit.
businessUnit.idstring
businessUnit.namestring
bookedTechnicianobject or null
bookedTechnician.idstringTechnician id (GET /technicians).
bookedTechnician.namestring
bookedTechnician.colorstringCalendar colour, #rrggbb.
leadTechnicianobject or null
leadTechnician.idstringTechnician id (GET /technicians).
leadTechnician.namestring
leadTechnician.colorstringCalendar colour, #rrggbb.
sourceJobobject or null
sourceJob.idstring
sourceJob.identifierstring

The leads I sent

GET /organizations/{organizationId}/field/leads

The caller's leads from the field, newest first, with their status (NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED) and the latest quote made from each. Read-only.

Permission: jobs.read (Owner, Admin, Dispatcher, Technician (own jobs), Member); risk read (OAuth scope servflo.read).

Permissionjobs.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolfieldApp_myLeads (toolset scheduling)

Example

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

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
idstringRequest id.
identifierstringREQ-n
descriptionstring
statusenumNEW → ASSESSMENT_SCHEDULED / QUOTED → CONVERTED (a job was booked), or ARCHIVED. One of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.
leadUrgencyenum or nullOne of NOW, SOON, LATER.
createdAtstring (date-time)
customerobject or null
customer.idstring
customer.namestring
sourceJobobject or null
sourceJob.idstring
sourceJob.identifierstring
quotesarray of objectThe latest quote made from it, if any.
quotes[].idstring
quotes[].identifierstring
quotes[].statusenumDRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (job or invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED.

The parts I asked for

GET /organizations/{organizationId}/field/parts-requests

The caller's parts requests, newest first, with status and the office's note. Read-only.

Permission: jobs.read (Owner, Admin, Dispatcher, Technician (own jobs), Member); risk read (OAuth scope servflo.read).

Permissionjobs.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolfieldApp_myPartsRequests (toolset scheduling)

Example

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

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
idstringParts request id.
organizationIdstring
identifierstringPRQ-n, unique per organization.
kindenumFor a job, or to restock the truck. One of JOB, RESTOCK.
statusenumREQUESTED → ORDERED (from a supplier) → READY (waiting for pickup) → DONE (on the truck), or CANCELLED. One of REQUESTED, ORDERED, READY, DONE, CANCELLED.
technicianIdstring or null
requestedByUserIdstring
jobIdstring or null
truckIdstring or nullThe technician's truck (inventory location).
neededBystring or nullYYYY-MM-DD
notestring or null
officeNotestring or nullThe office's answer to the technician.
statusChangedAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)
technicianobject or null
technician.idstringTechnician id (GET /technicians).
technician.namestring
technician.colorstringCalendar colour, #rrggbb.
jobobject or null
job.idstring
job.identifierstringJOB-n
job.customerobject
job.customer.namestring
truckobject or null
truck.idstring
truck.namestring
linesarray of object
lines[].idstring
lines[].itemIdstring or nullThe pricebook item, when it is one.
lines[].descriptionstring
lines[].quantitynumber
lines[].itemobject or null
lines[].item.codestring or null
lines[].item.namestring

Ask the office for parts

POST /organizations/{organizationId}/field/parts-requests

A technician asks for parts for one of their jobs (kind JOB, jobId) or to restock their truck (RESTOCK): lines from the pricebook (itemId) or described in words, with when they're needed. Creates PRQ-n for the office (Inventory → Parts requests); the technician's phone is told when it's on order or ready. Returns it.

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

Request body

FieldTypeRequiredDescription
kindenumYesOne of JOB, RESTOCK.
jobIdstring or nullNo
neededBystring or nullNo
notestring or nullNoUp to 2000 characters.
linesarray of objectYesUp to 100 items.
lines[].itemIdstring or nullNo
lines[].descriptionstringYesUp to 500 characters.
lines[].quantitynumberYesAt most 100000.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/field/parts-requests" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"JOB","lines":[{"description":"string","quantity":1}]}'

Response

201: the answer's fields
FieldTypeDescription
idstringParts request id.
organizationIdstring
identifierstringPRQ-n, unique per organization.
kindenumFor a job, or to restock the truck. One of JOB, RESTOCK.
statusenumREQUESTED → ORDERED (from a supplier) → READY (waiting for pickup) → DONE (on the truck), or CANCELLED. One of REQUESTED, ORDERED, READY, DONE, CANCELLED.
technicianIdstring or null
requestedByUserIdstring
jobIdstring or null
truckIdstring or nullThe technician's truck (inventory location).
neededBystring or nullYYYY-MM-DD
notestring or null
officeNotestring or nullThe office's answer to the technician.
statusChangedAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)
technicianobject or null
technician.idstringTechnician id (GET /technicians).
technician.namestring
technician.colorstringCalendar colour, #rrggbb.
jobobject or null
job.idstring
job.identifierstringJOB-n
job.customerobject
job.customer.namestring
truckobject or null
truck.idstring
truck.namestring
linesarray of object
lines[].idstring
lines[].itemIdstring or nullThe pricebook item, when it is one.
lines[].descriptionstring
lines[].quantitynumber
lines[].itemobject or null
lines[].item.codestring or null
lines[].item.namestring

What my truck needs

GET /organizations/{organizationId}/field/restock

Every item on the caller's truck at or below its reorder point, with the quantity to ask for (the reorder quantity, else back above the point). Read-only.

Permission: jobs.read (Owner, Admin, Dispatcher, Technician (own jobs), Member); risk read (OAuth scope servflo.read).

Permissionjobs.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolfieldApp_restockSuggestion (toolset scheduling)

Example

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

Response

200: the answer's fields
FieldTypeDescription
truckIdstring or nullThe technician's truck; null when they have none.
linesarray of objectItems at or below their reorder point, with the quantity to ask for.
lines[].itemIdstringPricebook item id.
lines[].descriptionstring
lines[].quantitynumber
POST /organizations/{organizationId}/jobs/{jobId}/pay-link/send

Sends to the customer: texts (else emails) the job's customer its pay-later link (/p/{token}), which opens the job's invoice to pay online. The technician app calls it when the phone reconnects after a customer chose to pay later. Consent rules apply (no text without SMS consent; then email). Technicians: their own jobs. Returns the link and how it went out.

Permission: invoices.send (Owner, Admin, Dispatcher, Technician (own jobs' invoices)); risk sensitive (OAuth scope servflo.sensitive).

Permissioninvoices.send
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolfieldApp_sendPayLink (toolset scheduling)
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in ServFlo). See Approvals.

Parameters

NameInTypeRequiredDescription
jobIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/jobs/{jobId}/pay-link/send" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
urlstringThe pay-later link (/p/{token}).
sentbooleanWhether a text or email went out.
channelenum or nullOne of SMS, EMAIL.

On this page