DevelopersAPI referenceProjects

Subcontractors API

REST endpoints for subcontractors in ServFlo: 14 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 subcontractorsGET /organizations/{organizationId}/subcontractorsread
Add a subcontractorPOST /organizations/{organizationId}/subcontractorswrite
A subcontractorGET /organizations/{organizationId}/subcontractors/{subcontractorId}read
Change a subcontractorPATCH /organizations/{organizationId}/subcontractors/{subcontractorId}write
Subcontractor papers expired or expiringGET /organizations/{organizationId}/subcontractors/expiring-documentsread
Add a subcontractor contactPOST /organizations/{organizationId}/subcontractors/{subcontractorId}/contactswrite
Change a subcontractor contactPATCH /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}write
Delete a subcontractor contactDELETE /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}sensitive
Add an insurance certificate, license or W-9POST /organizations/{organizationId}/subcontractors/{subcontractorId}/documentswrite
Change a subcontractor documentPATCH /organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}write
Delete a subcontractor documentDELETE /organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}sensitive
Start uploading a document's scanPOST /organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/filewrite
Finish uploading a document's scanPOST /organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/confirmwrite
Attach a document's scan (content in the request)POST /organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/contentwrite

List subcontractors

GET /organizations/{organizationId}/subcontractors

Subcontractors (vendors marked as subs) with trade, contacts, insurance, license and W-9 with expiry state, and a warning when papers are expired or missing. Read-only.

Permissionsubcontractors.read (Owner, Admin, Dispatcher, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolsubcontractors_list (toolset projects)

Parameters

NameInTypeRequiredDescription
searchquerystringNoUp to 200 characters.
tradequerystringNoUp to 100 characters.
includeInactivequerybooleanNo

Example

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

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Add a subcontractor

POST /organizations/{organizationId}/subcontractors

Adds a subcontractor (a vendor marked as a sub) with a trade and main contact. Add papers with POST …/documents.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_create (toolset projects)

Request body

FieldTypeRequiredDescription
namestringYesUp to 200 characters.
tradestring or nullNoElectrical, Plumbing, Drywall… Up to 100 characters.
contactNamestring or nullNoUp to 200 characters.
emailempty string or string (email) or nullNo
phonestring or nullNoUp to 50 characters.
termsstring or nullNoUp to 200 characters.
notesstring or nullNoUp to 5000 characters.

Example

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

Response

201: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

A subcontractor

GET /organizations/{organizationId}/subcontractors/{subcontractorId}

One subcontractor with contacts and papers. Read-only.

Permissionsubcontractors.read (Owner, Admin, Dispatcher, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolsubcontractors_get (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).

Example

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

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Change a subcontractor

PATCH /organizations/{organizationId}/subcontractors/{subcontractorId}

Name, trade, contact, terms, notes, active. subcontractor: true turns an existing vendor into a sub (false: back to a plain vendor).

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_update (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).

Request body

FieldTypeRequiredDescription
namestringNoUp to 200 characters.
tradestring or nullNoElectrical, Plumbing, Drywall… Up to 100 characters.
contactNamestring or nullNoUp to 200 characters.
emailempty string or string (email) or nullNo
phonestring or nullNoUp to 50 characters.
termsstring or nullNoUp to 200 characters.
notesstring or nullNoUp to 5000 characters.
activebooleanNo
subcontractorbooleanNo

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Dana Whitfield","trade":"string","contactName":"string"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Subcontractor papers expired or expiring

GET /organizations/{organizationId}/subcontractors/expiring-documents

Insurance certificates and licenses that have expired or expire within 30 days, soonest first. Read-only.

Permissionsubcontractors.read (Owner, Admin, Dispatcher, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolsubcontractors_expiring (toolset projects)

Example

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

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
vendorIdstring
subcontractorstring
expiresOnstring or null
statusstring

Add a subcontractor contact

POST /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts

Adds a person (owner, foreman, office) with a role, email and phone. isPrimary makes them the main contact.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_addContact (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).

Request body

FieldTypeRequiredDescription
namestringYesUp to 200 characters.
rolestring or nullNoUp to 100 characters.
emailempty string or string (email) or nullNo
phonestring or nullNoUp to 50 characters.
isPrimarybooleanNo

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/contacts" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Dana Whitfield"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Change a subcontractor contact

PATCH /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}

Changes a subcontractor contact: name, role, email, phone, or makes them the main contact.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_updateContact (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subContactIdpathstringYes

Request body

FieldTypeRequiredDescription
namestringNoUp to 200 characters.
rolestring or nullNoUp to 100 characters.
emailempty string or string (email) or nullNo
phonestring or nullNoUp to 50 characters.
isPrimarybooleanNo

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/contacts/{subContactId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Dana Whitfield","role":"string","email":"dana@example.com"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Delete a subcontractor contact

DELETE

/organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}

Destructive: removes a person from the subcontractor's contacts.

Permissionsubcontractors.manage (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 toolsubcontractors_deleteContact (toolset projects)
ApprovalOver MCP, this tool always waits for your approval in ServFlo. See Approvals.

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subContactIdpathstringYes

Example

curl -X DELETE "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/contacts/{subContactId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Add an insurance certificate, license or W-9

POST /organizations/{organizationId}/subcontractors/{subcontractorId}/documents

Records a paper with its number and expiry date (expiresOn); assigning the sub warns once it has expired. Attach the scan with POST …/documents/{subDocumentId}/file (browser) or …/file/content.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_addDocument (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).

Request body

FieldTypeRequiredDescription
kindenumYesOne of INSURANCE, LICENSE, W9, OTHER.
namestring or nullNoUp to 200 characters.
numberstring or nullNoUp to 100 characters.
expiresOnempty string or string or nullNo

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"INSURANCE"}'

Response

201: the answer's fields
FieldTypeDescription
documentstringThe new document's id.
subcontractorobject
subcontractor.idstring
subcontractor.namestring
subcontractor.tradestring or null
subcontractor.activeboolean
subcontractor.contactsarray of object
subcontractor.contacts[].idstring
subcontractor.contacts[].namestring
subcontractor.documentsarray of object
subcontractor.documents[].idstring
subcontractor.documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
subcontractor.documents[].namestring
subcontractor.documents[].expiresOnstring or null
subcontractor.documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
subcontractor.warningstring or nullExpired insurance or license, or none on file.

Change a subcontractor document

PATCH

/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}

Kind, name, number or expiry date (a renewed certificate).

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_updateDocument (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subDocumentIdpathstringYes

Request body

FieldTypeRequiredDescription
kindenumNoOne of INSURANCE, LICENSE, W9, OTHER.
namestringNoUp to 200 characters.
numberstring or nullNoUp to 100 characters.
expiresOnempty string or string or nullNo

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents/{subDocumentId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"INSURANCE","name":"Dana Whitfield","number":"string"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Delete a subcontractor document

DELETE

/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}

Destructive: removes the paper and its file.

Permissionsubcontractors.manage (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 toolsubcontractors_deleteDocument (toolset projects)
ApprovalOver MCP, this tool always waits for your approval in ServFlo. See Approvals.

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subDocumentIdpathstringYes

Example

curl -X DELETE "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents/{subDocumentId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Start uploading a document's scan

POST

/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/file

Step 1 of a browser upload (image or PDF, up to 25 MB): a signed URL to PUT it to (5 minutes), then POST …/file/confirm. Replaces an earlier scan.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_createDocumentUpload (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subDocumentIdpathstringYes

Request body

FieldTypeRequiredDescription
fileNamestringYesUp to 255 characters.
contentTypestringYesUp to 100 characters.
sizeBytesintegerYesAt least 1.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents/{subDocumentId}/file" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fileName":"string","contentType":"string","sizeBytes":1}'

Response

200: the answer's fields
FieldTypeDescription
uploadUrlstring

Finish uploading a document's scan

POST

/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/confirm

Step 2 of the browser upload: the PUT finished, so the scan is attached to the document.

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_confirmDocumentUpload (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subDocumentIdpathstringYes

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/confirm" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

Attach a document's scan (content in the request)

POST

/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/content

Attaches the scan of an insurance certificate, license or W-9 in one call: contentBase64 or a public sourceUrl (an image or PDF, up to 10 MB).

Permissionsubcontractors.manage (Owner, Admin, Dispatcher)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolsubcontractors_uploadDocument (toolset projects)

Parameters

NameInTypeRequiredDescription
subcontractorIdpathstringYesThe subcontractor (a vendor; GET /subcontractors).
subDocumentIdpathstringYes

Request body

FieldTypeRequiredDescription
fileNamestringNoThe file's name, e.g. receipt.jpg (default: from the URL, else 'file'). Up to 500 characters.
contentTypestringNoMIME type, e.g. image/jpeg or application/pdf. Optional: taken from a data: URL, the URL's answer or the file's first bytes. Up to 200 characters.
contentBase64stringNoThe file's bytes as base64 (a data: URL is accepted too). Up to 10 MB. Give this or sourceUrl.
sourceUrlstring (uri)NoA public http(s) URL ServFlo downloads the file from (up to 10 MB, 20 s, 3 redirects; private and internal addresses are refused). Give this or contentBase64. Up to 2000 characters.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/subcontractors/{subcontractorId}/documents/{subDocumentId}/file/content" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fileName":"string","contentType":"string","contentBase64":"string"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
namestring
tradestring or null
activeboolean
contactsarray of object
contacts[].idstring
contacts[].namestring
documentsarray of object
documents[].idstring
documents[].kindenumOne of INSURANCE, LICENSE, W9, OTHER.
documents[].namestring
documents[].expiresOnstring or null
documents[].statusenumOne of VALID, EXPIRING, EXPIRED, NO_DATE.
warningstring or nullExpired insurance or license, or none on file.

On this page