DevelopersAPI reference

Quotes API

REST endpoints for quotes in ServFlo: 13 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 quotesGET /organizations/{organizationId}/quotesread
Create a draft quotePOST /organizations/{organizationId}/quoteswrite
Get a quote with options, lines and totalsGET /organizations/{organizationId}/quotes/{quoteId}read
Update a quotePATCH /organizations/{organizationId}/quotes/{quoteId}write
Delete a quoteDELETE /organizations/{organizationId}/quotes/{quoteId}sensitive
Mark a quote as sentPOST /organizations/{organizationId}/quotes/{quoteId}/sendsensitive
Approve on the customer's behalfPOST /organizations/{organizationId}/quotes/{quoteId}/approvesensitive
Archive a quotePOST /organizations/{organizationId}/quotes/{quoteId}/archivewrite
Duplicate a quote as a new draftPOST /organizations/{organizationId}/quotes/{quoteId}/duplicatewrite
Remove or re-apply member pricingPOST /organizations/{organizationId}/quotes/{quoteId}/member-pricingwrite
Replace the customer linkPOST /organizations/{organizationId}/quotes/{quoteId}/linksensitive
Convert an approved quote to a jobPOST /organizations/{organizationId}/quotes/{quoteId}/jobwrite
Convert an approved quote to an invoicePOST /organizations/{organizationId}/quotes/{quoteId}/invoicewrite

List quotes

GET /organizations/{organizationId}/quotes

Quotes (Q-n) newest first, filtered by text, status, customer or request; paged with a total. totalCents is the approved total, else the lowest option's total. Sent quotes past validUntil read as EXPIRED. Read-only.

Permission: quotes.read (Owner, Admin, Dispatcher, Technician (quotes they sold), Member); risk read (OAuth scope servflo.read).

Permissionquotes.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolquotes_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 DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED.
customerIdquerystringNo
requestIdquerystringNo
businessUnitIdquerystringNoOnly this business unit (GET /business-units), or "none" for records without one. Up to 100 characters.
todayquerystringNoA calendar date in the business's own calendar, YYYY-MM-DD.
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/quotes" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

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

Create a draft quote

POST /organizations/{organizationId}/quotes

Creates a DRAFT quote (Q-n) for a customer with options and lines. Tax is 0 for tax-exempt customers, else taxRate, else the property's rate. Without options, one empty option is made. Nothing is sent: POST /quotes/{quoteId}/send marks it sent and the customer opens /q/{token}.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

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

Request body

FieldTypeRequiredDescription
customerIdstringYes
customFieldsobjectNoQuote custom field values (GET /custom-fields?entity=QUOTE); those marked visibleToCustomer print on the quote. Required ones are checked when the quote is created here.
propertyIdstring or nullNo
requestIdstring or nullNo
titlestring or nullNoUp to 500 characters.
messagestring or nullNo
validUntilempty string or string or nullNo
taxRatenumberNo-1000–1000.
depositPercentnumber or nullNo0–100.
depositCentsinteger or nullNo0–100000000.
internalNotesstring or nullNo
optionsarray of objectNoUp to 10 items.
options[].namestring or nullNoUp to 200 characters.
options[].descriptionstring or nullNoUp to 5000 characters.
options[].imageUrlstring or nullNoIn-home presenter: a picture of this option; else its first pricebook item's image. Up to 2000 characters.
options[].highlightsarray of stringNoIn-home presenter: feature bullets compared side by side across options. Up to 12 items.
options[].warrantystring or nullNoIn-home presenter: the warranty shown with this option. Up to 500 characters.
options[].recommendedbooleanNoIn-home presenter: mark as the recommended option.
options[].linesarray of objectYesUp to 200 items.
options[].lines[].descriptionstringYes
options[].lines[].quantitynumberYes-1000000–1000000.
options[].lines[].unitPriceCentsintegerYesMoney in integer cents; negative for a discount or credit line. -100000000–100000000.
options[].lines[].optionalbooleanNo
options[].lines[].defaultSelectedbooleanNo
options[].lines[].serviceTypeIdstring or nullNo
options[].lines[].materialIdstring or nullNo
options[].lines[].kindenum or nullNoFor member pricing: SERVICE (labour, the default) or MATERIAL get the member discount for their kind; MEMBERSHIP (a plan fee) is never discounted. Discount lines are added by the server. One of SERVICE, MATERIAL, MEMBERSHIP.
options[].lines[].pricebookItemIdstring or nullNoThe pricebook item the line was picked from (GET /pricebook/items): the server snapshots its cost; later pricebook edits never change this quote.
options[].lines[].memberPriceAppliedboolean or nullNoThe line is priced at the item's member price (memberPriceCents); the plan's member discount then skips it. Kept only for items that have a member price.
memberPricingbooleanNoMember pricing: a member customer's quote gets the plan's discount lines automatically; false removes them from this quote, true restores them.
soldByTechnicianIdstring or nullNoThe technician who sold it, for commissions (GET /technicians/options). Defaults to the creator's linked technician; set on approval when still empty.
financingDisabledbooleanNoExposes to customers: true hides Affirm and Klarna ("or about $X/mo", pay the deposit over time) on this quote even when the business offers financing.
businessUnitIdstring or nullNoBusiness unit (GET /business-units): its branding shows on the quote. Omitted on create: the request's unit, the first service line's default, then the seller's home unit. Up to 100 characters.

Example

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

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)

Get a quote with options, lines and totals

GET /organizations/{organizationId}/quotes/{quoteId}

One quote with its options, lines, totals, deposit, approval details and the customer link token (publicToken, for /q/{token}). Read-only.

Permission: quotes.read (Owner, Admin, Dispatcher, Technician (quotes they sold), Member); risk read (OAuth scope servflo.read).

Permissionquotes.read
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolquotes_get (toolset sales, in the default set)

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes
todayquerystringNoA calendar date in the business's own calendar, YYYY-MM-DD.

Example

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

Response

200: 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)
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
customer.addressstring or null
customer.citystring or null
customer.statestring or null
customer.zipstring or null
customer.taxExemptboolean
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
property.taxRatenumber or null
requestobject or null
request.idstring
request.identifierstringREQ-n
request.statusenumNEW → ASSESSMENT_SCHEDULED / QUOTED → CONVERTED (a job was booked), or ARCHIVED. One of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.
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.
invoiceobject or null
invoice.idstring
invoice.identifierstringINV-n
invoice.statusenumDRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED.
invoice.totalCentsinteger
optionsarray of object
options[].idstringQuote option id (for optionId).
options[].quoteIdstring
options[].namestring
options[].descriptionstring or null
options[].sortOrderinteger
options[].imageUrlstring or null
options[].highlightsarray of string
options[].warrantystring or null
options[].recommendedboolean
options[].linesarray of object
options[].lines[].idstringQuote line id (for selectedLineIds).
options[].lines[].optionIdstring
options[].lines[].descriptionstring
options[].lines[].quantitynumber
options[].lines[].unitPriceCentsintegerUnit price, in integer cents.
options[].lines[].optionalbooleanThe customer may leave it out.
options[].lines[].defaultSelectedbooleanAn optional line's default.
options[].lines[].serviceTypeIdstring or null
options[].lines[].materialIdstring or null
options[].lines[].sortOrderinteger
options[].lines[].kindenum or nullSERVICE or MATERIAL (member discount by kind), MEMBER_DISCOUNT (the automatic member pricing line) or MEMBERSHIP (a plan fee). One of SERVICE, MATERIAL, MEMBER_DISCOUNT, MEMBERSHIP.
options[].lines[].pricebookItemIdstring or null
options[].lines[].costCentsinteger or nullOur unit cost in cents (costing.read only).
options[].lines[].memberPriceAppliedboolean
options[].totalsobjectThe option's totals in cents with its default lines.
options[].totals.lineTotalsarray of integer
options[].totals.includedarray of boolean
options[].totals.subtotalCentsinteger
options[].totals.taxCentsinteger
options[].totals.totalCentsinteger
options[].totals.depositCentsinteger
memberPricingobject
memberPricing.appliedbooleanMember discount lines are on the document.
memberPricing.removedbooleanStaff removed the member pricing from this document.
memberPricing.membershipobject or nullThe customer's active membership that would apply; null when not a member.
memberPricing.membership.membershipIdstring
memberPricing.membership.identifierstringMEM-n
memberPricing.membership.planNamestring
memberPricing.membership.serviceDiscountPercentnumber
memberPricing.membership.materialDiscountPercentnumber
memberPricing.membership.priorityboolean
approvalSnapshotanyWhat the customer approved (option, lines, totals), frozen at approval; null before.

Update a quote

PATCH /organizations/{organizationId}/quotes/{quoteId}

Changes the fields sent, until the customer decides. options replaces every option and line (send them all). Moving an expired quote's date forward re-opens it.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Request body

FieldTypeRequiredDescription
customerIdstringNo
customFieldsobjectNoQuote custom field values (GET /custom-fields?entity=QUOTE); those marked visibleToCustomer print on the quote. Required ones are checked when the quote is created here.
propertyIdstring or nullNo
requestIdstring or nullNo
titlestring or nullNoUp to 500 characters.
messagestring or nullNo
validUntilempty string or string or nullNo
taxRatenumberNo-1000–1000.
depositPercentnumber or nullNo0–100.
depositCentsinteger or nullNo0–100000000.
internalNotesstring or nullNo
optionsarray of objectNoUp to 10 items.
options[].namestring or nullNoUp to 200 characters.
options[].descriptionstring or nullNoUp to 5000 characters.
options[].imageUrlstring or nullNoIn-home presenter: a picture of this option; else its first pricebook item's image. Up to 2000 characters.
options[].highlightsarray of stringNoIn-home presenter: feature bullets compared side by side across options. Up to 12 items.
options[].warrantystring or nullNoIn-home presenter: the warranty shown with this option. Up to 500 characters.
options[].recommendedbooleanNoIn-home presenter: mark as the recommended option.
options[].linesarray of objectYesUp to 200 items.
options[].lines[].descriptionstringYes
options[].lines[].quantitynumberYes-1000000–1000000.
options[].lines[].unitPriceCentsintegerYesMoney in integer cents; negative for a discount or credit line. -100000000–100000000.
options[].lines[].optionalbooleanNo
options[].lines[].defaultSelectedbooleanNo
options[].lines[].serviceTypeIdstring or nullNo
options[].lines[].materialIdstring or nullNo
options[].lines[].kindenum or nullNoFor member pricing: SERVICE (labour, the default) or MATERIAL get the member discount for their kind; MEMBERSHIP (a plan fee) is never discounted. Discount lines are added by the server. One of SERVICE, MATERIAL, MEMBERSHIP.
options[].lines[].pricebookItemIdstring or nullNoThe pricebook item the line was picked from (GET /pricebook/items): the server snapshots its cost; later pricebook edits never change this quote.
options[].lines[].memberPriceAppliedboolean or nullNoThe line is priced at the item's member price (memberPriceCents); the plan's member discount then skips it. Kept only for items that have a member price.
memberPricingbooleanNoMember pricing: a member customer's quote gets the plan's discount lines automatically; false removes them from this quote, true restores them.
soldByTechnicianIdstring or nullNoThe technician who sold it, for commissions (GET /technicians/options). Defaults to the creator's linked technician; set on approval when still empty.
financingDisabledbooleanNoExposes to customers: true hides Affirm and Klarna ("or about $X/mo", pay the deposit over time) on this quote even when the business offers financing.
businessUnitIdstring or nullNoBusiness unit (GET /business-units): its branding shows on the quote. Omitted on create: the request's unit, the first service line's default, then the seller's home unit. Up to 100 characters.
todaystringNoA calendar date in the business's own calendar, YYYY-MM-DD.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customerId":"customer_id","customFields":{},"propertyId":"property_id"}'

Response

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

Delete a quote

DELETE /organizations/{organizationId}/quotes/{quoteId}

Destructive: deletes the quote with its options and lines; its customer link stops working. Deposits taken on it stay as payments, no longer linked to a quote. Prefer archiving (POST /quotes/{quoteId}/archive).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Example

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

Response

200: the answer's fields
FieldTypeDescription
oktrue

Mark a quote as sent

POST /organizations/{organizationId}/quotes/{quoteId}/send

Sends to the customer: marks the quote SENT (records sentAt), which opens its customer page /q/{token} for approval. Nothing is emailed; share the link from GET /quotes/{quoteId}.

Permission: quotes.send (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk sensitive (OAuth scope servflo.sensitive).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Request body

FieldTypeRequiredDescription
todaystringNoA calendar date in the business's own calendar, YYYY-MM-DD.

Example

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

Response

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

Approve on the customer's behalf

POST /organizations/{organizationId}/quotes/{quoteId}/approve

Acts for the customer: records the customer's approval (e.g. given by phone) of one option; the quote becomes APPROVED and can be converted to a job or invoice and take deposits. selectedLineIds are the optional lines kept; omitted means their defaults. Stores the terms the customer was shown (terms, else the business's current quote terms) and, when they signed on the device, signatureDataUrl. Get option and line ids from GET /quotes/{quoteId}.

Permission: quotes.approve (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk sensitive (OAuth scope servflo.sensitive).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Request body

FieldTypeRequiredDescription
optionIdstringNo
selectedLineIdsarray of stringNoUp to 200 items.
signatureNamestring or nullNoUp to 200 characters.
termsstring or nullNoThe terms shown to the customer (GET /signing-terms resolved.quoteTerms); omitted: the business's current ones. Up to 5000 characters.
signatureDataUrlstring or nullNoThe customer's signature drawn on the device: a data:image/png;base64 URL.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/approve" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"optionId":"option_id","selectedLineIds":["selectedLine_id"],"signatureName":"string"}'

Response

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

Archive a quote

POST /organizations/{organizationId}/quotes/{quoteId}/archive

Moves the quote to ARCHIVED: out of the open lists, kept for the record. Its customer link stops accepting answers.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

Permissionquotes.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolquotes_archive (toolset sales)

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/archive" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

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

Duplicate a quote as a new draft

POST /organizations/{organizationId}/quotes/{quoteId}/duplicate

Copies the quote's options and lines into a new DRAFT quote (new Q-n, new link) for the same customer. Returns the new quote.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

Permissionquotes.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolquotes_duplicate (toolset sales)

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/duplicate" \
  -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)

Remove or re-apply member pricing

POST /organizations/{organizationId}/quotes/{quoteId}/member-pricing

Member pricing: a member customer's quote gets the plan's discount as separate negative lines per option (services and materials apart, required lines only). applied: false removes them for this quote; applied: true restores them (409 when the customer has no active membership covering the quote's property). Only while the quote can still change (DRAFT, SENT, CHANGES_REQUESTED, EXPIRED; 409 otherwise). Returns the quote with memberPricing.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

Permissionquotes.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolquotes_setMemberPricing (toolset sales)

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Request body

FieldTypeRequiredDescription
appliedbooleanYestrue: apply the member discount; false: remove it.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/member-pricing" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"applied":true}'

Response

200: 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)
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
customer.addressstring or null
customer.citystring or null
customer.statestring or null
customer.zipstring or null
customer.taxExemptboolean
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
property.taxRatenumber or null
requestobject or null
request.idstring
request.identifierstringREQ-n
request.statusenumNEW → ASSESSMENT_SCHEDULED / QUOTED → CONVERTED (a job was booked), or ARCHIVED. One of NEW, ASSESSMENT_SCHEDULED, QUOTED, CONVERTED, ARCHIVED.
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.
invoiceobject or null
invoice.idstring
invoice.identifierstringINV-n
invoice.statusenumDRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED.
invoice.totalCentsinteger
optionsarray of object
options[].idstringQuote option id (for optionId).
options[].quoteIdstring
options[].namestring
options[].descriptionstring or null
options[].sortOrderinteger
options[].imageUrlstring or null
options[].highlightsarray of string
options[].warrantystring or null
options[].recommendedboolean
options[].linesarray of object
options[].lines[].idstringQuote line id (for selectedLineIds).
options[].lines[].optionIdstring
options[].lines[].descriptionstring
options[].lines[].quantitynumber
options[].lines[].unitPriceCentsintegerUnit price, in integer cents.
options[].lines[].optionalbooleanThe customer may leave it out.
options[].lines[].defaultSelectedbooleanAn optional line's default.
options[].lines[].serviceTypeIdstring or null
options[].lines[].materialIdstring or null
options[].lines[].sortOrderinteger
options[].lines[].kindenum or nullSERVICE or MATERIAL (member discount by kind), MEMBER_DISCOUNT (the automatic member pricing line) or MEMBERSHIP (a plan fee). One of SERVICE, MATERIAL, MEMBER_DISCOUNT, MEMBERSHIP.
options[].lines[].pricebookItemIdstring or null
options[].lines[].costCentsinteger or nullOur unit cost in cents (costing.read only).
options[].lines[].memberPriceAppliedboolean
options[].totalsobjectThe option's totals in cents with its default lines.
options[].totals.lineTotalsarray of integer
options[].totals.includedarray of boolean
options[].totals.subtotalCentsinteger
options[].totals.taxCentsinteger
options[].totals.totalCentsinteger
options[].totals.depositCentsinteger
memberPricingobject
memberPricing.appliedbooleanMember discount lines are on the document.
memberPricing.removedbooleanStaff removed the member pricing from this document.
memberPricing.membershipobject or nullThe customer's active membership that would apply; null when not a member.
memberPricing.membership.membershipIdstring
memberPricing.membership.identifierstringMEM-n
memberPricing.membership.planNamestring
memberPricing.membership.serviceDiscountPercentnumber
memberPricing.membership.materialDiscountPercentnumber
memberPricing.membership.priorityboolean
approvalSnapshotanyWhat the customer approved (option, lines, totals), frozen at approval; null before.
POST /organizations/{organizationId}/quotes/{quoteId}/link

REVOKES / EXPOSES: issues a new customer link token; the previous /q/{token} link stops working at once. Returns the quote.

Permission: quotes.send (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk sensitive (OAuth scope servflo.sensitive).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Example

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

Response

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

Convert an approved quote to a job

POST /organizations/{organizationId}/quotes/{quoteId}/job

Books a job (JOB-n) from an APPROVED quote; the quote becomes CONVERTED. Price is the approved total before tax; the approved lines go into the job's notes. Returns the job.

Permission: quotes.write (Owner, Admin, Dispatcher, Technician (quotes they sold)); risk write (OAuth scope servflo.write).

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

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

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

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/job" \
  -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.

Convert an approved quote to an invoice

POST /organizations/{organizationId}/quotes/{quoteId}/invoice

Creates a DRAFT invoice with the approved lines, through the normal invoice rules; deposits paid on the quote move onto it and count as paid. Nothing is sent. Returns the invoice.

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

Permissioninvoices.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolquotes_convertToInvoice (toolset sales)

Parameters

NameInTypeRequiredDescription
quoteIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/invoice" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

201: the answer's fields
FieldTypeDescription
idstringInvoice id.
organizationIdstring
identifierstringINV-n, unique per organization.
customerIdstring
jobIdstring or null
statusenumDRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED.
subtotalCentsintegerLines total before tax, in integer cents.
taxRatenumberTax rate in percent.
taxCentsintegerTax, in integer cents.
totalCentsintegerTotal with tax, in integer cents.
notesstring or null
dueDatestring or nullYYYY-MM-DD
paidDatestring or nullYYYY-MM-DD
amountPaidCentsintegerPaid so far, net of refunds, tips excluded, in integer cents.
membershipIdstring or nullSet on a membership's billing invoice.
memberPricingRemovedboolean
financingDisabledboolean
progressBillingIdstring or null
progressRoleenum or nullIts place in a progress billing. One of PROGRESS, FINAL, RETAINAGE_RELEASE.
progressMilestoneIdstring or null
progressBilledCentsintegerBilled towards the contract on a progress invoice, in integer cents.
retainageCentsintegerRetainage held on a progress invoice, in integer cents.
businessUnitIdstring or null
customFieldsanyCustom field values by key (definitions: GET /custom-fields?entity=INVOICE).
createdAtstring (date-time)
updatedAtstring (date-time)
customerobject
customer.idstring
customer.namestring
businessUnitobject or nullThe business unit.
businessUnit.idstring
businessUnit.namestring
jobobject or null
job.idstring
job.identifierstringJOB-n
job.signedBystring or nullWork accepted by (the job's sign-off).
job.signedAtstring (date-time) or null
balanceDueCentsintegerStill due, in integer cents.
partiallyPaidboolean

On this page