Reference · POST /v1/jobs
Create job
Create job
Submit a new job request. The job is created unscheduled — your scheduling team picks the actual time. You can still edit the request (via PATCH) while it’s in that pre-scheduled state.
Request
curl -X POST -H "Authorization: Bearer fi_pk_…" \
-H "Content-Type: application/json" \
-d '{
"site": "3065756",
"job_type": "29400",
"title": "Annual service",
"start_time": "2026-07-01T09:00:00+10:00",
"end_time": "2026-07-01T11:00:00+10:00",
"notes": "Site contact prefers morning visits. Gate code 1742#.",
"purchase_order_number": "PO-12345",
"external_id": "client-ref-001",
"project": "1052232",
"custom_fields": { "scope_of_work": "Install" }
}' \
https://<host>/v1/jobsResponse
{
"id": "21172159",
"number": "16",
"site_id": "3065756"
}Fields
sitestring
Site ID the job is for. Fetch valid IDs from /v1/sites. Provide exactly one of `site` or `new_site`. Example: `"site": "3065756"`.
new_siteobject
Create a site inline instead of referencing an existing `site`. Requires `business_name` and `address`; optional `first_name`, `last_name`, `mobile_number`, `email`, `external_id`. The site is owned by your scoped customer. Its id comes back as `site_id` in the response. Example: `{ "business_name": "New Depot", "address": "5 Side St" }`.
job_typestring
Job-type ID — describes the kind of work (e.g. Installation, Service, Inspection). Fetch IDs from /v1/job-types. Optional: if omitted, your tenant’s configured default job type is used; if no default is set, the request is rejected. Example: `"job_type": "29400"`.
titlerequiredstring
Short label shown on the job in lists and on the calendar. 1–200 chars. Example: `"Quarterly safety inspection"`.
start_timerequiredISO 8601
Preferred start. This is a hint — scheduling staff confirm the actual time. Include a timezone offset so it’s unambiguous. Example: `"2026-07-01T09:00:00+10:00"`.
end_timeISO 8601
Preferred end. Same notes as start_time. Optional — defaults to one hour after start_time when omitted. Example: `"2026-07-01T11:00:00+10:00"`.
notesstring
Office-scoped log against the job — not shown to the field tech. Use it for internal context the scheduling and admin team should see: booking history, status updates, customer correspondence. Pair this with custom_fields when the tech needs to see something on the work order. ≤ 2000 chars.
purchase_order_numberstring
Your PO number for the job, if you use them. Surfaces on the job record. ≤ 100 chars. Example: `"PO-12345"`.
external_idstring
Your own reference for the job — typically a record ID in your system. Lets you reconcile webhooks back to your records. ≤ 36 chars.
projectrequiredstring
Project ID the job rolls up to. Required — fetch allowed IDs from /v1/projects. Example: `"project": "1052232"`. If your tenant has no projects in scope, ask your admin to add one.
custom_fieldsobject<string, string>
Map of friendly field names to values. The valid names come from /v1/custom-fields. Unknown names are rejected. Example: `{ "scope_of_work": "Install + commissioning" }`.
Errors
400 invalid-body400 unknown-custom-field400 project-not-in-scope400 field-not-writable401 unauthorized403 no-scope409 multi-customer-create-unsupported422 no-projects-configured422 job-type-required422 invalid-request429 rate-limited502 schema-drift503 writes-disabled
Provide exactly one of `site` (an existing site ID) or `new_site` (create one inline) — sending both, or neither, is rejected. Job status, customer, and the `unscheduled` flag are set automatically and can’t be overridden.