DevelopersAPI reference

Requests API

REST endpoints for requests in ServFlo: 11 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
List requestsGET /organizations/{organizationId}/requestsread
Create a requestPOST /organizations/{organizationId}/requestswrite
Get a request with its customer, quotes and jobsGET /organizations/{organizationId}/requests/{requestId}read
Update a requestPATCH /organizations/{organizationId}/requests/{requestId}write
Delete a requestDELETE /organizations/{organizationId}/requests/{requestId}sensitive
Make the request's contact a customerPOST /organizations/{organizationId}/requests/{requestId}/customerwrite
Convert a request to a draft quotePOST /organizations/{organizationId}/requests/{requestId}/quotewrite
Schedule an on-site assessmentPOST /organizations/{organizationId}/requests/{requestId}/assessmentwrite
Confirm an online bookingPOST /organizations/{organizationId}/requests/{requestId}/confirm-bookingwrite
Online booking and portal settingsGET /organizations/{organizationId}/booking-settingsread
Turn online booking, portal job photos or customer sign-in on or offPATCH /organizations/{organizationId}/booking-settingssensitive

List requests

GET /organizations/{organizationId}/requests

Service requests (REQ-n) newest first: from the online booking form, the customer portal or entered by staff. Filter by text, status, source or customer; paged with a total. Read-only.

Permissionrequests.read (Owner, Admin, Dispatcher, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolrequests_list (toolset sales, in the default set)

Parameters

NameInTypeRequiredDescription
queryquerystringNoFree-text search over the list's names, numbers and contact details. Up to 200 characters.
statusqueryenumNoOne of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.
sourcequeryenumNoOne of MANUAL, ONLINE_BOOKING, PORTAL, FIELD, PHONE.
customerIdquerystringNo
businessUnitIdquerystringNoOnly this business unit (GET /business-units), or "none" for records without one. Up to 100 characters.
limitqueryintegerNoPage size, 1–200. Default 50.
offsetqueryintegerNoRows to skip; the answer's total counts every match. Default 0.

Example

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

Response

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

Create a request

POST /organizations/{organizationId}/requests

Records a NEW service request (REQ-n). Name an existing customerId (search GET /customers first), or give contactName (and phone/email) for a new contact; no customer is created until POST /requests/{requestId}/customer. Nothing is sent to anyone.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_create (toolset sales, in the default set)

Request body

FieldTypeRequiredDescription
customerIdstring or nullNo
contactNamestring or nullNoUp to 200 characters.
contactCompanystring or nullNoUp to 200 characters.
contactPhonestring or nullNoUp to 50 characters.
contactEmailempty string or string (email) or nullNo
propertyIdstring or nullNo
addressstring or nullNoUp to 500 characters.
serviceTypeIdstring or nullNo
descriptionstringYes
preferredDateempty string or string or nullNo
alternateDateempty string or string or nullNo
preferredTimeWindowenumNoOne of ANY, MORNING, AFTERNOON, EVENING.
sourceenumNoOne of MANUAL, ONLINE_BOOKING, PORTAL, FIELD, PHONE.
internalNotesstring or nullNo
businessUnitIdstring or nullNoBusiness unit (GET /business-units); null = none. Omitted on create: the default (service type, then technician). Up to 100 characters.

Example

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

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

Get a request with its customer, quotes and jobs

GET /organizations/{organizationId}/requests/{requestId}

One request with its customer, property, quotes and jobs. matchingCustomers lists existing customers with the contact's email or phone, when no customer is linked: link one with PATCH (customerId) rather than creating a duplicate. Read-only.

Permissionrequests.read (Owner, Admin, Dispatcher, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolrequests_get (toolset sales, in the default set)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Example

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

Response

200: 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
customer.emailstring or null
customer.phonestring or null
customer.statusenumLEAD until the first job, then ACTIVE; ARCHIVED customers leave the lists. One of LEAD, ACTIVE, INACTIVE, ARCHIVED.
propertyobject or null
property.idstringProperty id.
property.namestring or null
property.addressstring or null
property.citystring or null
property.statestring or null
property.zipstring 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
jobobject or null
job.idstring
job.identifierstringJOB-n
job.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.
job.scheduledDatestring
assessmentJobobject or null
assessmentJob.idstring
assessmentJob.identifierstringJOB-n
assessmentJob.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.
assessmentJob.scheduledDatestring
quotesarray of object
quotes[].idstring
quotes[].identifierstringQ-n
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.
quotes[].titlestring
matchingCustomersarray of objectExisting customers with the contact's email or phone (up to 3) while the request has no customer.
matchingCustomers[].idstring
matchingCustomers[].namestring
matchingCustomers[].emailstring or null
matchingCustomers[].phonestring or null

Update a request

PATCH /organizations/{organizationId}/requests/{requestId}

Changes the fields sent. status: ARCHIVED archives it; NEW reopens an archived request. To quote or book it use POST /requests/{requestId}/quote, /assessment or POST /jobs with requestId.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_update (toolset sales)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Request body

FieldTypeRequiredDescription
customerIdstring or nullNo
contactNamestring or nullNoUp to 200 characters.
contactCompanystring or nullNoUp to 200 characters.
contactPhonestring or nullNoUp to 50 characters.
contactEmailempty string or string (email) or nullNo
propertyIdstring or nullNo
addressstring or nullNoUp to 500 characters.
serviceTypeIdstring or nullNo
descriptionstringNo
preferredDateempty string or string or nullNo
alternateDateempty string or string or nullNo
preferredTimeWindowenumNoOne of ANY, MORNING, AFTERNOON, EVENING.
sourceenumNoOne of MANUAL, ONLINE_BOOKING, PORTAL, FIELD, PHONE.
internalNotesstring or nullNo
businessUnitIdstring or nullNoBusiness unit (GET /business-units); null = none. Omitted on create: the default (service type, then technician). Up to 100 characters.
statusenumNoOne of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customerId":"customer_id","contactName":"string","contactCompany":"string"}'

Response

200: 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

Delete a request

DELETE /organizations/{organizationId}/requests/{requestId}

Destructive: deletes the request. Quotes and jobs made from it stay. Prefer archiving (PATCH status: ARCHIVED).

Permissionrequests.delete (Owner, Admin, Dispatcher)
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolrequests_delete (toolset sales)
ApprovalOver MCP, this tool always waits for your approval in ServFlo. See Approvals.

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Example

curl -X DELETE "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
oktrue

Make the request's contact a customer

POST /organizations/{organizationId}/requests/{requestId}/customer

Creates a LEAD customer (and a property from the address) from the request's contact when the request has none, and links it; returns the request. Check matchingCustomers on GET /requests/{requestId} first to avoid duplicates.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_ensureCustomer (toolset sales)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}/customer" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: 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
customer.emailstring or null
customer.phonestring or null
customer.statusenumLEAD until the first job, then ACTIVE; ARCHIVED customers leave the lists. One of LEAD, ACTIVE, INACTIVE, ARCHIVED.
propertyobject or null
property.idstringProperty id.
property.namestring or null
property.addressstring or null
property.citystring or null
property.statestring or null
property.zipstring 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
jobobject or null
job.idstring
job.identifierstringJOB-n
job.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.
job.scheduledDatestring
assessmentJobobject or null
assessmentJob.idstring
assessmentJob.identifierstringJOB-n
assessmentJob.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.
assessmentJob.scheduledDatestring
quotesarray of object
quotes[].idstring
quotes[].identifierstringQ-n
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.
quotes[].titlestring
matchingCustomersarray of objectExisting customers with the contact's email or phone (up to 3) while the request has no customer.
matchingCustomers[].idstring
matchingCustomers[].namestring
matchingCustomers[].emailstring or null
matchingCustomers[].phonestring or null

Convert a request to a draft quote

POST /organizations/{organizationId}/requests/{requestId}/quote

Creates a DRAFT quote for the request (and the customer, if the request is from a new contact); the request becomes QUOTED. Fill the quote with PATCH /quotes/{quoteId}; nothing is sent.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_convertToQuote (toolset sales, in the default set)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}/quote" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

201: the answer's fields
FieldTypeDescription
idstringQuote id.
organizationIdstring
identifierstringQ-n, unique per organization.
customerIdstring
propertyIdstring or null
requestIdstring or nullThe request it was made from.
titlestring
messagestring or nullShown to the customer.
validUntilstring or nullYYYY-MM-DD; a sent quote expires after it.
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.
taxRatenumberTax rate in percent.
depositPercentnumber or nullDeposit asked, as a percent of the total.
depositCentsinteger or nullDeposit asked, as a fixed amount in cents.
internalNotesstring or null
publicTokenstringThe customer link token: the quote page is /q/{publicToken}.
sentAtstring (date-time) or null
approvedAtstring (date-time) or null
approvedOptionIdstring or null
approvedLineIdsarray of stringThe optional lines the customer kept.
approvedTotalCentsinteger or nullApproved total in cents, with tax.
approvedDepositCentsinteger or nullApproved deposit in cents.
signatureNamestring or null
approvedByStaffbooleanStaff recorded the approval for the customer.
changesRequestedAtstring (date-time) or null
changesRequestedNotestring or null
declinedAtstring (date-time) or null
declineReasonstring or null
jobIdstring or nullThe job it was converted to.
invoiceIdstring or nullThe invoice it was converted to.
convertedAtstring (date-time) or null
memberPricingRemovedboolean
soldByUserIdstring or null
soldByTechnicianIdstring or null
financingDisabledboolean
businessUnitIdstring or null
customFieldsanyCustom field values by key (definitions: GET /custom-fields?entity=QUOTE).
createdAtstring (date-time)
updatedAtstring (date-time)

Schedule an on-site assessment

POST /organizations/{organizationId}/requests/{requestId}/assessment

Books a job (JOB-n) noted as the request's on-site assessment, creating the customer if needed; the request becomes ASSESSMENT_SCHEDULED. Nothing is sent to the customer.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_scheduleAssessment (toolset sales)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Request body

FieldTypeRequiredDescription
scheduledDatestringYesA calendar date in the business's own calendar, YYYY-MM-DD.
scheduledTimestring or nullNoA local time of day, HH:MM (24-hour). Blank means 09:00 on new jobs.
technicianIdstring or nullNo
notesstring or nullNo

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}/assessment" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scheduledDate":"2026-11-03"}'

Response

201: the answer's fields
FieldTypeDescription
idstringJob id.
organizationIdstring
identifierstringJOB-n, unique per organization.
customerIdstring
propertyIdstring or null
assetIdstring or nullThe equipment worked on.
technicianIdstring or nullThe lead technician of the next open visit.
serviceTypeIdstring or null
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.
priorityenumOne of LOW, NORMAL, HIGH, URGENT.
scheduledDatestringThe next open visit's day, YYYY-MM-DD.
scheduledTimestring or nullHh: MM
durationMinutesinteger
priceCentsintegerJob price before tax, in integer cents.
addressstring or null
notesstring or null
completionNotesstring or nullWhat was done.
recurrenceIntervalenum or nullOne of WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, YEARLY.
recurrenceParentIdstring or null
onMyWayAtstring (date-time) or null
arrivedAtstring (date-time) or null
startedAtstring (date-time) or null
completedAtstring (date-time) or null
signedBystring or nullWho signed the work off on site.
signedAtstring (date-time) or null
businessUnitIdstring or null
customFieldsanyCustom field values by key (definitions: GET /custom-fields?entity=JOB).
weatherSensitiveboolean or nullPlans around the weather: overrides the service type; null follows it.
createdAtstring (date-time)
updatedAtstring (date-time)
customerobject
customer.idstringCustomer id.
customer.namestring
customer.phonestring or null
technicianobject or null
technician.idstringTechnician id (GET /technicians).
technician.namestring
technician.colorstringCalendar colour, #rrggbb.
serviceTypeobject or null
serviceType.idstring
serviceType.namestring
serviceType.colorstring
businessUnitobject or nullThe business unit.
businessUnit.idstring
businessUnit.namestring
assetobject or null
asset.idstring
asset.namestring
asset.serialNumberstring
propertyobject or null
property.idstringProperty id.
property.namestring or null
property.addressstring or null
property.citystring or null
property.taxRatenumber or null
nextJobIdstring or nullAfter an update: the next occurrence booked when a recurring job completed.

Confirm an online booking

POST /organizations/{organizationId}/requests/{requestId}/confirm-booking

Turns the time a customer booked online (bookedDate, bookedTime on the request) into a job (JOB-n) at that time, creating the customer from the contact when none is linked (link an existing one first with PATCH /requests/{requestId} customerId to avoid a duplicate). The technician defaults to the one the slot holds; pass technicianId (or null) to change it. The request becomes CONVERTED. Only NEW requests with a booked time. Nothing is sent by this call; automations may react to booking.confirmed.

Permissionrequests.write (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolrequests_confirmBooking (toolset sales)

Parameters

NameInTypeRequiredDescription
requestIdpathstringYes

Request body

FieldTypeRequiredDescription
technicianIdstring or nullNoAssign someone else (or null for nobody).

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/requests/{requestId}/confirm-booking" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"technicianId":"technician_id"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
identifierstringJOB-n
scheduledDatestring
scheduledTimestring or null
technicianIdstring or null

Online booking and portal settings

GET /organizations/{organizationId}/booking-settings

Whether the public booking form (/book/{slug}) takes requests, whether the customer portal shows completed jobs' photos, and whether customers can sign in to their portal (/c/{slug}). Read-only.

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

Example

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

Response

200: the answer's fields
FieldTypeDescription
slugstringThe booking form is at /book/{slug}.
bookingEnabledboolean
portalShowJobPhotosbooleanWhether the customer portal shows the photos of completed jobs (default off).
customerSignInEnabledbooleanWhether customers can sign in to their portal at /c/{slug} with a code sent to their email or phone (default on).

Turn online booking, portal job photos or customer sign-in on or off

PATCH /organizations/{organizationId}/booking-settings

customerSignInEnabled off REVOKES ACCESS: every customer is signed out of their portal at once and /c/{slug} stops offering sign-in (portal links keep working). bookingEnabled off: the public booking form and /api/public/book/{slug} answer 404 and take no requests; on: anyone with the link can send a request. portalShowJobPhotos on EXPOSES the before/after/general photos of completed jobs to customers in their portal (never ISSUE photos or signatures). Send either or both. Needs settings.manage (owners and admins).

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

Request body

FieldTypeRequiredDescription
bookingEnabledbooleanNo
portalShowJobPhotosbooleanNoShow completed jobs' photos to customers in their portal.
customerSignInEnabledbooleanNoLet customers sign in to their portal with a code (on by default). Off signs every customer out at once.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/booking-settings" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"bookingEnabled":true,"portalShowJobPhotos":true,"customerSignInEnabled":true}'

Response

200: the answer's fields
FieldTypeDescription
slugstringThe booking form is at /book/{slug}.
bookingEnabledboolean
portalShowJobPhotosbooleanWhether the customer portal shows the photos of completed jobs (default off).
customerSignInEnabledbooleanWhether customers can sign in to their portal at /c/{slug} with a code sent to their email or phone (default on).

On this page