Getting started
Setup & verification
Connect your key, confirm your scope, and make a couple of test requests before you wire anything up.
1. Receive your API key
Your integration contact will provide an API key (e.g. fi_pk_live_…) and the gateway hostname. Treat the key like a password — store it in a secret manager, never in source control. If a key is ever leaked, contact us and we’ll rotate it with a grace window so your integration doesn’t break.
2. Confirm authentication
Every request must include a Authorization: Bearer fi_pk_… header. The simplest way to confirm the key works is to fetch your customers:
curl -sS -H "Authorization: Bearer fi_pk_…" \ https://<host>/v1/customers
If you see 401 unauthorized, the key is wrong, missing, or doesn’t have the scope this endpoint needs.If you see 403 no-scope, the key is valid but no customers have been assigned yet — contact us so we can finish setting it up.
3. Discover the IDs you need
Sites, projects, job types and statuses are identified by numeric IDs. The lookup endpoints exist so you can resolve them once during setup and cache the results. See Lookups for the full list. At minimum, before creating a job you’ll want:
/v1/sites— which site is the job for/v1/job-types— what kind of work/v1/custom-fields— what custom fields you’re allowed to send
If the site you need doesn’t exist yet, you can add it with POST /v1/sites (requires the sites:write scope). You cannot create a site as a side-effect of POST /v1/jobs — create the site first, then reference its ID on the job.
4. Try a read
Pull the open jobs already in your scope. An empty list is fine — it means the key works and there’s simply nothing open yet.
curl -sS -H "Authorization: Bearer fi_pk_…" \ "https://<host>/v1/jobs?state=open&page_size=5"
5. Try a write
Use a real site ID + job type from step 3. The start_time and end_time are your preferred window — the scheduling team confirms the actual time.
curl -sS -X POST -H "Authorization: Bearer fi_pk_…" \
-H "Content-Type: application/json" \
-d '{
"site": "3065756",
"job_type": "29400",
"title": "Integration check",
"start_time": "2026-07-01T09:00:00+10:00",
"end_time": "2026-07-01T11:00:00+10:00",
"notes": "Created during initial integration."
}' \
https://<host>/v1/jobs6. Wire it in
A few habits make the integration easier to operate later:
- Cache the lookup results (sites, job types, custom fields). See Rate limits for the budget.
- Log the
X-Request-Idfrom each response next to your own request ID — it’s a quick way to pivot between logs if something needs investigating. - For ongoing sync, pass
updated_at_fromtoGET /v1/jobsso you only pull what changed.
Jump to the full reference starting at List jobs.