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/jobs

Response

{
  "id": "21172159",
  "number": "16",
  "site_id": "3065756"
}

Fields

site
string
Site ID the job is for. Fetch valid IDs from /v1/sites. Provide exactly one of `site` or `new_site`. Example: `"site": "3065756"`.
new_site
object
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_type
string
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"`.
titlerequired
string
Short label shown on the job in lists and on the calendar. 1–200 chars. Example: `"Quarterly safety inspection"`.
start_timerequired
ISO 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_time
ISO 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"`.
notes
string
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_number
string
Your PO number for the job, if you use them. Surfaces on the job record. ≤ 100 chars. Example: `"PO-12345"`.
external_id
string
Your own reference for the job — typically a record ID in your system. Lets you reconcile webhooks back to your records. ≤ 36 chars.
projectrequired
string
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_fields
object<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.