Skip to content

Developers

CrewFlow Public API

Version 1.0.0

Key-authenticated read and write access to your CrewFlow organisation's data. Every request is scoped to the organisation that owns the API key; there is NO cross-organisation access. Read and write are DISTINCT scopes — a key must hold the matching write scope (e.g. write:customers) to create or update, even if it can already read. Writes validate their body strictly (unknown fields are rejected), pin every new row to the key's organisation, compute money server-side, and return the created/updated record. Updates via PATCH are idempotent (re-sending the same body yields the same state); a repeated create (POST) makes a new record. VERSIONING: the version is in the URL path (/api/v1). Breaking changes ship under a new prefix (/api/v2) while /api/v1 keeps working; additive changes (new optional fields, new endpoints) are made in place.

Base URL: https://app.crewflow.uk/api/v1 · Machine-readable spec: openapi.json

Authentication

Send your API key as `Authorization: Bearer crewflow_sk_...`. Mint and scope keys in Settings → API keys. Keys can be revoked at any time and take effect on the next request.

Authorization: Bearer crewflow_sk_...

Scopes

Every key is granted a specific set of scopes. Read and write are distinct: a key needs the matching write scope to create or update, even if it can already read that resource.

ScopeGrants
read:jobsRead jobs
read:customersRead customers
read:invoicesRead invoices
read:quotesRead quotes
read:timeRead time entries
read:staffRead staff roster
read:expensesRead expenses
read:materialsRead material requests
write:customersCreate & update customers
write:leadsCreate leads
write:jobsCreate & update jobs
write:quotesCreate quotes
write:expensesCreate & update expenses
write:invoicesUpdate invoice status & metadata

Rate limits

Requests are limited to 120 per minute per key(shared across every v1 endpoint, keyed by the API key, not by IP). Over budget returns 429.

Endpoints

Identity

get/meany valid key

The identity the API key carries.

Example

curl https://app.crewflow.uk/api/v1/me \
  -H "Authorization: Bearer crewflow_sk_..."

Jobs

get/jobsread:jobs

List jobs.

Example

curl https://app.crewflow.uk/api/v1/jobs \
  -H "Authorization: Bearer crewflow_sk_..."
post/jobswrite:jobs

Create a job.

Request body

FieldTypeRequired
status"new" | "in-progress" | "completed" | "blocked" | "cancelled"No
scheduled_datestringNo
customer_idstringNo
notesstringNo
site_address_line1stringNo
site_address_line2stringNo
site_citystringNo
site_countystringNo
site_postcodestringNo
site_countrystringNo

Example

curl -X POST https://app.crewflow.uk/api/v1/jobs \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'
get/jobs/{id}read:jobs

Fetch a single job by id.

Example

curl https://app.crewflow.uk/api/v1/jobs/{id} \
  -H "Authorization: Bearer crewflow_sk_..."
patch/jobs/{id}write:jobs

Update a job.

Request body

FieldTypeRequired
status"new" | "in-progress" | "completed" | "blocked" | "cancelled"No
scheduled_datestringNo
customer_idstringNo
notesstringNo
site_address_line1stringNo
site_address_line2stringNo
site_citystringNo
site_countystringNo
site_postcodestringNo
site_countrystringNo

At least one field must be provided. Omitted fields are left unchanged.

Example

curl -X PATCH https://app.crewflow.uk/api/v1/jobs/{id} \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'

Customers

get/customersread:customers

List customers.

Example

curl https://app.crewflow.uk/api/v1/customers \
  -H "Authorization: Bearer crewflow_sk_..."
post/customerswrite:customers

Create a customer.

Request body

FieldTypeRequired
namestringYes
emailstringNo
phonestringNo
address_line1stringNo
address_line2stringNo
citystringNo
countystringNo
postcodestringNo
countrystringNo
notesstringNo

Example

curl -X POST https://app.crewflow.uk/api/v1/customers \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"..."}'
get/customers/{id}read:customers

Fetch a single customer by id.

Example

curl https://app.crewflow.uk/api/v1/customers/{id} \
  -H "Authorization: Bearer crewflow_sk_..."
patch/customers/{id}write:customers

Update a customer.

Request body

FieldTypeRequired
namestringNo
emailstringNo
phonestringNo
address_line1stringNo
address_line2stringNo
citystringNo
countystringNo
postcodestringNo
countrystringNo
notesstringNo

At least one field must be provided. Omitted fields are left unchanged.

Example

curl -X PATCH https://app.crewflow.uk/api/v1/customers/{id} \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'

Leads

post/leadswrite:leads

Capture a lead.

Request body

FieldTypeRequired
contact_namestringYes
contact_emailstringNo
contact_phonestringNo
source"phone" | "web" | "referral" | "walk_in" | "social" | "repeat" | "portal" | "other"Yes
servicestringNo
urgency"low" | "normal" | "high" | "urgent"No
postcodestringNo
estimated_valuenumberNo
notesstringNo
customer_idstringNo

At least one of contact_email or contact_phone is required.

Example

curl -X POST https://app.crewflow.uk/api/v1/leads \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"contact_name":"...","source":"phone"}'

Invoices

get/invoicesread:invoices

List invoices.

Example

curl https://app.crewflow.uk/api/v1/invoices \
  -H "Authorization: Bearer crewflow_sk_..."
get/invoices/{id}read:invoices

Fetch a single invoice by id.

Example

curl https://app.crewflow.uk/api/v1/invoices/{id} \
  -H "Authorization: Bearer crewflow_sk_..."
patch/invoices/{id}write:invoices

Update an invoice's status and metadata (never its money).

Request body

FieldTypeRequired
status"draft" | "sent" | "awaiting_payment" | "partially_paid" | "paid"No
due_datestringNo
notesstringNo

Update invoice status and metadata. Money columns (amount, vat_total, total, number) are not writable. 'overdue' is derived, not stored, and is rejected. At least one field must be provided.

Example

curl -X PATCH https://app.crewflow.uk/api/v1/invoices/{id} \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'

Quotes

get/quotesread:quotes

List quotes.

Example

curl https://app.crewflow.uk/api/v1/quotes \
  -H "Authorization: Bearer crewflow_sk_..."
post/quoteswrite:quotes

Create a draft quote.

Request body

FieldTypeRequired
customer_idstringYes
property_idstringNo
lead_idstringNo
valid_untilstringNo
notesstringNo
termsstringNo
line_itemsQuoteLineItemInput[]Yes

Totals (subtotal, vat_total, total) are computed server-side from the line items — never send them.

line_items[] items (QuoteLineItemInput)

FieldTypeRequired
descriptionstringYes
qtynumberYes
unitstringNo
unit_pricenumberYes
vat_rate0 | 5 | 20Yes

Example

curl -X POST https://app.crewflow.uk/api/v1/quotes \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"...","line_items":[]}'

Time

get/timeread:time

List time entries.

Example

curl https://app.crewflow.uk/api/v1/time \
  -H "Authorization: Bearer crewflow_sk_..."

Staff

get/staffread:staff

List staff (role and join date only — no identity).

Example

curl https://app.crewflow.uk/api/v1/staff \
  -H "Authorization: Bearer crewflow_sk_..."

Expenses

get/expensesread:expenses

List expenses.

Example

curl https://app.crewflow.uk/api/v1/expenses \
  -H "Authorization: Bearer crewflow_sk_..."
post/expenseswrite:expenses

Record an expense.

Request body

FieldTypeRequired
amountnumberYes
vat_rate0 | 5 | 20No
categorystringNo
notesstringNo
job_idstringNo

Record a cost. vat_total is computed server-side (amount * vat_rate) and can never be sent. Currency is fixed to GBP.

Example

curl -X POST https://app.crewflow.uk/api/v1/expenses \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"amount":0}'
get/expenses/{id}read:expenses

Fetch a single expense by id.

Example

curl https://app.crewflow.uk/api/v1/expenses/{id} \
  -H "Authorization: Bearer crewflow_sk_..."
patch/expenses/{id}write:expenses

Update an expense.

Request body

FieldTypeRequired
amountnumberNo
vat_rate0 | 5 | 20No
categorystringNo
notesstringNo

At least one field must be provided. Omitted fields are left unchanged. job_id and vat_total are not updatable.

Example

curl -X PATCH https://app.crewflow.uk/api/v1/expenses/{id} \
  -H "Authorization: Bearer crewflow_sk_..." \
  -H "Content-Type: application/json" \
  -d '{}'

Materials

get/materialsread:materials

List material requests.

Example

curl https://app.crewflow.uk/api/v1/materials \
  -H "Authorization: Bearer crewflow_sk_..."

Versioning

A new major version gets a new path prefix; older versions continue to answer. Additive changes (new optional fields, new endpoints) are made in place.

CrewFlow API, Developer docs · CrewFlow