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 .
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.
Permission subcontractors.read (Owner, Admin, Dispatcher, Member)Risk read, OAuth scope servflo.read. Read: reads only.MCP tool subcontractors_list (toolset projects)
Name In Type Required Description searchquery string No Up to 200 characters. tradequery string No Up to 100 characters. includeInactivequery boolean No
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields An array of objects:
Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
POST /organizations/{organizationId}/subcontractors
Adds a subcontractor (a vendor marked as a sub) with a trade and main contact. Add papers with POST …/documents.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_create (toolset projects)
Field Type Required Description namestring Yes Up to 200 characters. tradestring or null No Electrical, Plumbing, Drywall… Up to 100 characters. contactNamestring or null No Up to 200 characters. emailempty string or string (email) or null No phonestring or null No Up to 50 characters. termsstring or null No Up to 200 characters. notesstring or null No Up to 5000 characters.
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"}'
201: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
GET /organizations/{organizationId}/subcontractors/{subcontractorId}
One subcontractor with contacts and papers. Read-only.
Permission subcontractors.read (Owner, Admin, Dispatcher, Member)Risk read, OAuth scope servflo.read. Read: reads only.MCP tool subcontractors_get (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors).
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors/{subcontractorId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
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).
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_update (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors).
Field Type Required Description namestring No Up to 200 characters. tradestring or null No Electrical, Plumbing, Drywall… Up to 100 characters. contactNamestring or null No Up to 200 characters. emailempty string or string (email) or null No phonestring or null No Up to 50 characters. termsstring or null No Up to 200 characters. notesstring or null No Up to 5000 characters. activeboolean No subcontractorboolean No
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"}'
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
GET /organizations/{organizationId}/subcontractors/expiring-documents
Insurance certificates and licenses that have expired or expire within 30 days, soonest first. Read-only.
Permission subcontractors.read (Owner, Admin, Dispatcher, Member)Risk read, OAuth scope servflo.read. Read: reads only.MCP tool subcontractors_expiring (toolset projects)
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors/expiring-documents" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields An array of objects:
Field Type Description vendorIdstring subcontractorstring expiresOnstring or null statusstring
POST /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts
Adds a person (owner, foreman, office) with a role, email and phone. isPrimary makes them the main contact.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_addContact (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors).
Field Type Required Description namestring Yes Up to 200 characters. rolestring or null No Up to 100 characters. emailempty string or string (email) or null No phonestring or null No Up to 50 characters. isPrimaryboolean No
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"}'
201: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
PATCH /organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}
Changes a subcontractor contact: name, role, email, phone, or makes them the main contact.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_updateContact (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subContactIdpath string Yes
Field Type Required Description namestring No Up to 200 characters. rolestring or null No Up to 100 characters. emailempty string or string (email) or null No phonestring or null No Up to 50 characters. isPrimaryboolean No
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"}'
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
DELETE
/organizations/{organizationId}/subcontractors/{subcontractorId}/contacts/{subContactId}
Destructive: removes a person from the subcontractor's contacts.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk sensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.MCP tool subcontractors_deleteContact (toolset projects)Approval Over MCP, this tool always waits for your approval in ServFlo. See Approvals .
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subContactIdpath string Yes
curl -X DELETE "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors/{subcontractorId}/contacts/{subContactId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
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.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_addDocument (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors).
Field Type Required Description kindenum Yes One of INSURANCE, LICENSE, W9, OTHER. namestring or null No Up to 200 characters. numberstring or null No Up to 100 characters. expiresOnempty string or string or null No
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"}'
201: the answer's fields Field Type Description documentstring The 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[].kindenum One of INSURANCE, LICENSE, W9, OTHER. subcontractor.documents[].namestring subcontractor.documents[].expiresOnstring or null subcontractor.documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. subcontractor.warningstring or null Expired insurance or license, or none on file.
PATCH
/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}
Kind, name, number or expiry date (a renewed certificate).
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_updateDocument (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subDocumentIdpath string Yes
Field Type Required Description kindenum No One of INSURANCE, LICENSE, W9, OTHER. namestring No Up to 200 characters. numberstring or null No Up to 100 characters. expiresOnempty string or string or null No
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"}'
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
DELETE
/organizations/{organizationId}/subcontractors/{subcontractorId}/documents/{subDocumentId}
Destructive: removes the paper and its file.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk sensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.MCP tool subcontractors_deleteDocument (toolset projects)Approval Over MCP, this tool always waits for your approval in ServFlo. See Approvals .
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subDocumentIdpath string Yes
curl -X DELETE "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors/{subcontractorId}/documents/{subDocumentId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
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.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_createDocumentUpload (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subDocumentIdpath string Yes
Field Type Required Description fileNamestring Yes Up to 255 characters. contentTypestring Yes Up to 100 characters. sizeBytesinteger Yes At least 1.
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}'
200: the answer's fields Field Type Description uploadUrlstring
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.
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_confirmDocumentUpload (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subDocumentIdpath string Yes
curl -X POST "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /subcontractors/{subcontractorId}/documents/{subDocumentId}/file/confirm" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.
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).
Permission subcontractors.manage (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool subcontractors_uploadDocument (toolset projects)
Name In Type Required Description subcontractorIdpath string Yes The subcontractor (a vendor; GET /subcontractors). subDocumentIdpath string Yes
Field Type Required Description fileNamestring No The file's name, e.g. receipt.jpg (default: from the URL, else 'file'). Up to 500 characters. contentTypestring No MIME 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. contentBase64string No The file's bytes as base64 (a data: URL is accepted too). Up to 10 MB. Give this or sourceUrl. sourceUrlstring (uri) No A 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.
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"}'
201: the answer's fields Field Type Description idstring namestring tradestring or null activeboolean contactsarray of object contacts[].idstring contacts[].namestring documentsarray of object documents[].idstring documents[].kindenum One of INSURANCE, LICENSE, W9, OTHER. documents[].namestring documents[].expiresOnstring or null documents[].statusenum One of VALID, EXPIRING, EXPIRED, NO_DATE. warningstring or null Expired insurance or license, or none on file.