REST endpoints for forms in ServFlo: 10 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}/jobs/{jobId}/forms
The forms attached to the job (from templates matching its service type, 'always attach' templates, or added by hand): field snapshot, answers, status and missing required fields. Read-only. Also included in GET /jobs/{jobId}.
Permission: jobs.read (Owner, Admin, Dispatcher, Technician (own jobs), Member); risk read (OAuth scope servflo.read).
Permission jobs.readRisk read, OAuth scope servflo.read. Read: reads only.MCP tool jobForms_list (toolset scheduling)
Name In Type Required Description jobIdpath string Yes
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /jobs/{jobId}/forms" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields An array of objects:
Field Type Description idstring jobIdstring templateIdstring or null namestring descriptionstring or null fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. answersobject statusenum One of DRAFT, SUBMITTED. submittedByUserIdstring or null submittedAtstring (date-time) or null createdAtstring (date-time) updatedAtstring (date-time) missingarray of string Ids of required fields still unanswered.
POST /organizations/{organizationId}/jobs/{jobId}/forms
Attaches a template (GET /form-templates) to the job as a new draft form with a snapshot of its fields; adding one already on the job returns that form. Its required fields then block completing the job.
Permission jobs.write (Owner, Admin, Dispatcher)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool jobForms_attach (toolset scheduling)
Name In Type Required Description jobIdpath string Yes
Field Type Required Description templateIdstring Yes
curl -X POST "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /jobs/{jobId}/forms" \
-H "Authorization: Bearer $SERVFLO_API_KEY " \
-H "Content-Type: application/json" \
-d '{"templateId":"template_id"}'
201: the answer's fields Field Type Description idstring jobIdstring templateIdstring or null namestring descriptionstring or null fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. answersobject statusenum One of DRAFT, SUBMITTED. submittedByUserIdstring or null submittedAtstring (date-time) or null createdAtstring (date-time) updatedAtstring (date-time) missingarray of string Ids of required fields still unanswered.
PATCH /organizations/{organizationId}/jobs/{jobId}/forms/{formId}
Replaces the form's answers with answers, keyed by field id: checkbox → boolean, text/textarea/select/date → string, number → number, multiselect → string[], photo → ids of this job's photos (POST …/photos first), signature → { name, dataUrl (PNG data URL), signedAt }. Wrong types are refused (400); missing required answers are allowed until submit or completion. A submitted form goes back to DRAFT.
Permission jobs.work (Owner, Admin, Dispatcher, Technician)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool jobForms_save (toolset scheduling)
Name In Type Required Description jobIdpath string Yes formIdpath string Yes
Field Type Required Description answersobject Yes Answers keyed by field id; see the description for each type.
curl -X PATCH "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /jobs/{jobId}/forms/{formId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY " \
-H "Content-Type: application/json" \
-d '{"answers":{}}'
200: the answer's fields Field Type Description idstring jobIdstring templateIdstring or null namestring descriptionstring or null fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. answersobject statusenum One of DRAFT, SUBMITTED. submittedByUserIdstring or null submittedAtstring (date-time) or null createdAtstring (date-time) updatedAtstring (date-time) missingarray of string Ids of required fields still unanswered.
DELETE /organizations/{organizationId}/jobs/{jobId}/forms/{formId}
Destructive: removes the form and its answers from the job (the template stays). Cannot be undone.
Permission jobs.write (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 jobForms_remove (toolset scheduling)Approval Over MCP, this tool always waits for your approval in ServFlo. See Approvals .
Name In Type Required Description jobIdpath string Yes formIdpath string Yes
curl -X DELETE "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /jobs/{jobId}/forms/{formId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description oktrue
POST /organizations/{organizationId}/jobs/{jobId}/forms/{formId}/submit
Marks the form SUBMITTED by the caller. Refused (400, naming the fields) while a required field is unanswered. Emits form.submitted. Completing the job submits complete drafts automatically.
Permission jobs.work (Owner, Admin, Dispatcher, Technician)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool jobForms_submit (toolset scheduling)
Name In Type Required Description jobIdpath string Yes formIdpath string Yes
curl -X POST "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /jobs/{jobId}/forms/{formId}/submit" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring jobIdstring templateIdstring or null namestring descriptionstring or null fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. answersobject statusenum One of DRAFT, SUBMITTED. submittedByUserIdstring or null submittedAtstring (date-time) or null createdAtstring (date-time) updatedAtstring (date-time) missingarray of string Ids of required fields still unanswered.
GET /organizations/{organizationId}/form-templates
Every job form template (active first) with its fields, the service types it is assigned to, whether it always attaches, and how many jobs carry it. Read-only.
Permission catalog.read (Owner, Admin, Dispatcher, Technician, Member)Risk read, OAuth scope servflo.read. Read: reads only.MCP tool formTemplates_list (toolset settings)
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /form-templates" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields An array of objects:
Field Type Description idstring namestring descriptionstring or null activeboolean alwaysAttachboolean fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. serviceTypeIdsarray of string createdAtstring (date-time) updatedAtstring (date-time) jobFormCountinteger
POST /organizations/{organizationId}/form-templates
Creates a template. From now on, new jobs of its service types (or every new job, with alwaysAttach) get a copy to fill in; existing jobs are unchanged (add it by hand with POST /jobs/{jobId}/forms). Fields are validated (unique ids, choices for selects). Returns the template.
Permission forms.manage (Owner, Admin)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool formTemplates_create (toolset settings)
Field Type Required Description namestring Yes Up to 200 characters. descriptionstring or null No Up to 2000 characters. activeboolean No Inactive templates attach to no new jobs. alwaysAttachboolean No Attach to every new job, whatever its service type. fieldsarray of any Yes The fields, in order: { id, type (heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature), label, required, help?, options? (select/multiselect), min?, max?, unit? }. Up to 100 items. serviceTypeIdsarray of string No Service types (GET /service-types) whose new jobs get this form. Up to 100 items.
curl -X POST "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /form-templates" \
-H "Authorization: Bearer $SERVFLO_API_KEY " \
-H "Content-Type: application/json" \
-d '{"name":"Dana Whitfield","fields":[null]}'
201: the answer's fields Field Type Description idstring namestring descriptionstring or null activeboolean alwaysAttachboolean fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. serviceTypeIdsarray of string createdAtstring (date-time) updatedAtstring (date-time) jobFormCountinteger
GET /organizations/{organizationId}/form-templates/{templateId}
One template with its fields and assigned service types. Read-only.
Permission catalog.read (Owner, Admin, Dispatcher, Technician, Member)Risk read, OAuth scope servflo.read. Read: reads only.MCP tool formTemplates_get (toolset settings)
Name In Type Required Description templateIdpath string Yes
curl "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /form-templates/{templateId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description idstring namestring descriptionstring or null activeboolean alwaysAttachboolean fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. serviceTypeIdsarray of string createdAtstring (date-time) updatedAtstring (date-time) jobFormCountinteger
PATCH /organizations/{organizationId}/form-templates/{templateId}
Changes the fields sent. serviceTypeIds replaces the assignment. Forms already on jobs keep their own copy of the fields. Returns the template.
Permission forms.manage (Owner, Admin)Risk write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.MCP tool formTemplates_update (toolset settings)
Name In Type Required Description templateIdpath string Yes
Field Type Required Description namestring No Up to 200 characters. descriptionstring or null No Up to 2000 characters. activeboolean No Inactive templates attach to no new jobs. alwaysAttachboolean No Attach to every new job, whatever its service type. fieldsarray of any No The fields, in order: { id, type (heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature), label, required, help?, options? (select/multiselect), min?, max?, unit? }. Up to 100 items. serviceTypeIdsarray of string No Service types (GET /service-types) whose new jobs get this form. Up to 100 items.
curl -X PATCH "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /form-templates/{templateId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY " \
-H "Content-Type: application/json" \
-d '{"name":"Dana Whitfield","description":"string","active":true}'
200: the answer's fields Field Type Description idstring namestring descriptionstring or null activeboolean alwaysAttachboolean fieldsarray of object Up to 100 items. fields[].idstring Stable id of the field within the template; answers are keyed by it. Up to 64 characters. fields[].typeenum What kind of answer the field takes. One of heading, checkbox, text, textarea, number, select, multiselect, date, photo, signature. fields[].labelstring Up to 200 characters. fields[].requiredboolean A required field must be answered before the job can be completed. Default false. fields[].helpstring or null Help text shown under the field. Up to 500 characters. fields[].optionsarray of string Choices for select and multiselect fields. Up to 50 items. fields[].minnumber or null Smallest allowed value (number fields). fields[].maxnumber or null Largest allowed value (number fields). fields[].unitstring or null Unit shown after a number, e.g. psi. Up to 20 characters. serviceTypeIdsarray of string createdAtstring (date-time) updatedAtstring (date-time) jobFormCountinteger
DELETE /organizations/{organizationId}/form-templates/{templateId}
Destructive: deletes the template; forms already filled in on jobs keep their copy. Prefer active: false to stop attaching it.
Permission forms.manage (Owner, Admin)Risk sensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.MCP tool formTemplates_delete (toolset settings)Approval Over MCP, this tool always waits for your approval in ServFlo. See Approvals .
Name In Type Required Description templateIdpath string Yes
curl -X DELETE "https://app.servflo.ai/api/organizations/ $ORGANIZATION_ID /form-templates/{templateId}" \
-H "Authorization: Bearer $SERVFLO_API_KEY "
200: the answer's fields Field Type Description oktrue