Spec revision aee5b4e, published 2026-10-01.
REST API for Forz field-service management.
/settings/api_keys. Format: fz_<UUIDv7>.application/problem+json with stable code field. See the error code catalog.Link header. List responses wrap {data, has_more}.?sort=field (prefix - for descending), ?field=value / ?field[gte|lte|gt|lt|in]=value filters, and ?q= free-text search. Each endpoint allowlists its own fields — see that endpoint's parameters. All three bind to the cursor: changing a filter or q mid-pagination returns cursor.invalid_filters, and sort is fixed by the cursor on continuation pages. Unknown query parameter, filter field or operator → filter.invalid (400); unknown sort field → sort.invalid (400).RateLimit-* headers on every response.Idempotency-Key REQUIRED on financial POSTs (invoices, sales_orders).Returns the account/company, user, API key (id + granted scopes) and
resolved api_version that the presenting Bearer key maps to. Read-only
and idempotent — the canonical "which tenant am I about to write to?"
check before a mutation.
Requires only a valid key — no scope is needed, so a scopeless key can still introspect itself. The body carries no secrets (never the token, its hash, or its prefix) and no environment field (there is a single environment).
| Cache-Control | string Always |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": {
- "account": {
- "id": 42,
- "name": "Acme Co"
}, - "user": {
- "id": 7,
- "name": "Jane Doe",
- "email": "jane@acme.com"
}, - "api_key": {
- "id": "0190a1b2-9c3d-7e4f-8a1b-2c3d4e5f6071",
- "scopes": [
- "customers:read",
- "jobs:read"
]
}, - "api_version": "2026-04-30"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across the customer's searchable fields (organization, number, status, reference, and the primary site's address). Narrows the result set; ordering still follows |
| sort | string Enum: "created_at" "-created_at" "updated_at" "-updated_at" "organization" "-organization" "number" "-number" "status" "-status" Sort the list by a single field. Prefix with |
| organization | string Filter by exact organization name. |
| number | string Filter by exact customer number. |
string or object Filter by status. Equality ( | |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Customer) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Acme Plumbing Co.",
- "main_phone": "+1 555-0100",
- "fax": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "status": "Active",
- "number": "string",
- "labels": [
- "VIP",
- "Net-30"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "afternoon",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "referral"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| organization required | string Display name. Must be unique per tenant (case-insensitive). |
| main_phone | string Primary phone for the organization. |
| fax | string Fax number. |
| website | string Public website URL. |
| description | string Free-text customer description. |
| reference | string Partner-defined reference. |
| assignee_id | integer <int64> Assignee user ID. Surfaced as 'Assignee' in the Forz UI. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
| customer_notes | string Internal rich-text notes (not surfaced on customer PDFs). |
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Customer) A customer (org / company / individual) in the tenant's CRM. Contact
and address data live on linked Contact and Site records (via the
|
{- "organization": "Acme Plumbing Co.",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "number": "string",
- "labels": [
- "VIP",
- "Net-30"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "morning",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "google"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Acme Plumbing Co.",
- "main_phone": "+1 555-0100",
- "fax": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "status": "Active",
- "number": "string",
- "labels": [
- "VIP",
- "Net-30"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "afternoon",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "referral"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Customer) A customer (org / company / individual) in the tenant's CRM. Contact
and address data live on linked Contact and Site records (via the
|
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Acme Plumbing Co.",
- "main_phone": "+1 555-0100",
- "fax": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "status": "Active",
- "number": "string",
- "labels": [
- "VIP",
- "Net-30"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "afternoon",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "referral"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| organization | string Display name. Must be unique per tenant. |
| main_phone | string Primary phone for the organization. |
| fax | string Fax number. |
| website | string Public website URL. |
| description | string Free-text customer description. |
| reference | string Partner-defined reference. |
| assignee_id | integer <int64> Assignee user ID. |
| status | string Tenant-configured status display_name. |
| labels | Array of strings Replaces the full label list (sets, not append). Each value must
match a Label |
| customer_notes | string Internal rich-text notes. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Customer) A customer (org / company / individual) in the tenant's CRM. Contact
and address data live on linked Contact and Site records (via the
|
{- "organization": "Acme Plumbing Co.",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "status": "string",
- "labels": [
- "VIP"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "morning"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Acme Plumbing Co.",
- "main_phone": "+1 555-0100",
- "fax": "string",
- "description": "string",
- "reference": "string",
- "assignee_id": 0,
- "status": "Active",
- "number": "string",
- "labels": [
- "VIP",
- "Net-30"
], - "customer_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "afternoon",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "referral"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: site name, address (street / city / state / zip), and the customer's organization. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
| customer_id | string <uuid> Sites owned by this customer (siteable_type=Customer, siteable_id= |
| lead_id | string <uuid> Sites owned by this lead (siteable_type=Lead, siteable_id= |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Site) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "site_name": "string",
- "street": "1 Market St",
- "street2": "string",
- "city": "string",
- "state": "NY",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "South wing"
}, - "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "siteable_id": "73b60e13-abe0-4989-9ed7-ef74b50eea55",
- "siteable_type": { },
- "created_by": 0,
- "name_address": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| site_name required | string Display name. |
| street required | string Street line 1. |
| street2 | string Street line 2 (optional). |
| city required | string City. |
| state required | string State / province. |
| zip_code | string Postal / ZIP code. |
| description | string Free-text description. |
| latitude | number Override the auto-geocode result. |
| longitude | number Override the auto-geocode result. |
| recurring_instructions | string Standing instructions for jobs at this site. |
object Tenant-defined custom fields. | |
| position | integer Display order; defaults to end of list. |
| system_option_id | string <uuid> FK to the SystemOption catalog row. |
| siteable_id required | string Parent Customer or Lead ID UUID v7 identifier. |
| siteable_type required | string Enum: "Customer" "Lead" Class name of the parent record. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Site) A physical service location attached to a Customer or Lead via the
polymorphic |
{- "site_name": "string",
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": { },
- "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "siteable_id": "string",
- "siteable_type": "Customer"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "site_name": "string",
- "street": "1 Market St",
- "street2": "string",
- "city": "string",
- "state": "NY",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "South wing"
}, - "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "siteable_id": "73b60e13-abe0-4989-9ed7-ef74b50eea55",
- "siteable_type": { },
- "created_by": 0,
- "name_address": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Site) A physical service location attached to a Customer or Lead via the
polymorphic |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "site_name": "string",
- "street": "1 Market St",
- "street2": "string",
- "city": "string",
- "state": "NY",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "South wing"
}, - "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "siteable_id": "73b60e13-abe0-4989-9ed7-ef74b50eea55",
- "siteable_type": { },
- "created_by": 0,
- "name_address": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| site_name | string Display name. |
| street | string Street line 1. |
| street2 | string Street line 2. |
| city | string City. |
| state | string State / province. |
| zip_code | string Postal / ZIP code. |
| description | string Free-text description. |
| latitude | number Geocoded latitude (override). |
| longitude | number Geocoded longitude (override). |
| recurring_instructions | string Standing instructions for jobs at this site. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
| position | integer Display order. |
| system_option_id | string <uuid> FK to the SystemOption catalog row. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Site) A physical service location attached to a Customer or Lead via the
polymorphic |
{- "site_name": "string",
- "street": "string",
- "street2": "string",
- "city": "string",
- "state": "string",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": { },
- "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "site_name": "string",
- "street": "1 Market St",
- "street2": "string",
- "city": "string",
- "state": "NY",
- "zip_code": "string",
- "description": "string",
- "latitude": 0,
- "longitude": 0,
- "recurring_instructions": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "South wing"
}, - "position": 0,
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "siteable_id": "73b60e13-abe0-4989-9ed7-ef74b50eea55",
- "siteable_type": { },
- "created_by": 0,
- "name_address": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: first name, last name, email, and title. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Contact) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "first_name": "Ada",
- "last_name": "Lovelace",
- "email": "ada@example.com",
- "phone": "string",
- "mobile": "string",
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "string",
- "number": "(415) 555-0199",
- "extension": "204",
- "plain": "14155550199"
}
], - "title": "string",
- "contact_method": "string",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": { },
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Tuesday afternoons"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| first_name | string Given name. |
| last_name | string Family name. |
string <email> Primary email. | |
| phone | string Office phone. |
| mobile | string Mobile phone. |
| title | string Job title. |
| contact_method | string Preferred channel hint. |
| linkable_id | string Parent record ID to attach to UUID v7 identifier. |
| linkable_type | string Enum: "Customer" "Lead" "Site" Parent record class name. |
object Tenant-defined custom field map. | |
Array of objects (PhoneNumberInput) Initial phone numbers. Supplying this suppresses the legacy |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Contact) A person attached to one or more Customer / Lead / Site records via
the contact_linkages join table. The polymorphic |
{- "first_name": "string",
- "last_name": "string",
- "email": "user@example.com",
- "phone": "string",
- "mobile": "string",
- "title": "string",
- "contact_method": "string",
- "linkable_id": "string",
- "linkable_type": "Customer",
- "custom_fields": { },
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "Mobile",
- "number": "(415) 555-0199",
- "extension": "204"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "first_name": "Ada",
- "last_name": "Lovelace",
- "email": "ada@example.com",
- "phone": "string",
- "mobile": "string",
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "string",
- "number": "(415) 555-0199",
- "extension": "204",
- "plain": "14155550199"
}
], - "title": "string",
- "contact_method": "string",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": { },
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Tuesday afternoons"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Contact) A person attached to one or more Customer / Lead / Site records via
the contact_linkages join table. The polymorphic |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "first_name": "Ada",
- "last_name": "Lovelace",
- "email": "ada@example.com",
- "phone": "string",
- "mobile": "string",
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "string",
- "number": "(415) 555-0199",
- "extension": "204",
- "plain": "14155550199"
}
], - "title": "string",
- "contact_method": "string",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": { },
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Tuesday afternoons"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| first_name | string Given name. |
| last_name | string Family name. |
string <email> Primary email. | |
| phone | string Office phone. |
| mobile | string Mobile phone. |
| title | string Job title. |
| contact_method | string Preferred channel hint. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
Array of objects (PhoneNumberInput) Snapshot replace of the full phone number list. Send |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Contact) A person attached to one or more Customer / Lead / Site records via
the contact_linkages join table. The polymorphic |
{- "first_name": "string",
- "last_name": "string",
- "email": "user@example.com",
- "phone": "string",
- "mobile": "string",
- "title": "string",
- "contact_method": "string",
- "custom_fields": { },
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "Mobile",
- "number": "(415) 555-0199",
- "extension": "204"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "first_name": "Ada",
- "last_name": "Lovelace",
- "email": "ada@example.com",
- "phone": "string",
- "mobile": "string",
- "phone_numbers": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "string",
- "number": "(415) 555-0199",
- "extension": "204",
- "plain": "14155550199"
}
], - "title": "string",
- "contact_method": "string",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": { },
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Tuesday afternoons"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Refused with 409 contact.has_linkages while the contact is linked to any record; unlink it first.
| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}Every Customer / Lead / Site this contact is linked to, oldest first. Not paginated.
| id required | string <uuid> The contact's UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (ContactLinkage) |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": "Customer",
- "relationship_type": "associated",
- "primary": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Links an existing contact to a Customer, Lead or Site. The first contact
linked to a record becomes its primary; later ones don't unless
primary: true is sent, which moves the record's primary to this contact.
| id required | string <uuid> The contact's UUID v7 identifier. |
| linkable_id required | string <uuid> The record to link to. |
| linkable_type required | string Enum: "Customer" "Lead" "Site" The record's class name. |
| relationship_type | string Enum: "associated" "billing" "technical" "decision_maker" Defaults to |
| primary | boolean Make this contact the record's primary. The first contact linked to a record is primary regardless. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (ContactLinkage) One link between a contact and a Customer, Lead or Site. |
{- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": "Customer",
- "relationship_type": "associated",
- "primary": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": "Customer",
- "relationship_type": "associated",
- "primary": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Changes the relationship type, or makes this contact the record's primary
(primary: true demotes the previous primary). A primary can't be cleared
with primary: false; make another contact primary instead.
| id required | string <uuid> The contact's UUID v7 identifier. |
| linkage_id required | string <uuid> The linkage's UUID v7 identifier. |
| relationship_type | string Enum: "associated" "billing" "technical" "decision_maker" The contact's role on this record. |
| primary | boolean
|
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (ContactLinkage) One link between a contact and a Customer, Lead or Site. |
{- "relationship_type": "associated",
- "primary": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "linkable_id": "a45259cf-641e-4d02-8ce9-41e8763e7643",
- "linkable_type": "Customer",
- "relationship_type": "associated",
- "primary": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Removes the link; the contact itself stays. Refused with 409
contact.primary_linkage while this contact is the record's primary.
To move a contact, link it to the new record, then unlink the old one.
| id required | string <uuid> The contact's UUID v7 identifier. |
| linkage_id required | string <uuid> The linkage's UUID v7 identifier. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: number, job type, status, reference, labels, the customer's organization, the site (name + address), the assignee's name, and the system type. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Job) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "ticket_id": "595be628-f6f2-4262-9c10-6389c6c4a5b8",
- "assignee_id": 0,
- "workorderable_type": { },
- "workorderable_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
- "route_id": "dd833dbc-f3c5-44d9-98a2-7ba12ebc8160",
- "route_planner_id": "feaf5141-622b-43c7-9061-98a3762c067c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "number": "string",
- "status": "string",
- "title": "Annual fire alarm inspection",
- "scope_of_work": "Inspect all 12 smoke detectors and 4 pull stations; replace any failed batteries.",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "job_type": "Annual Inspection",
- "priority": "High",
- "due_date": "2026-05-15",
- "schedule_date": "2019-08-24",
- "week_days": [
- "string"
], - "routable": true,
- "discount_type": "string",
- "discount_value": 0,
- "discount_total": 0,
- "discounts": { },
- "taxes": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "labels": [
- "Urgent",
- "Warranty"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Building A",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "2026-05-30"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| customer_id | string Customer the job is for (UUID v7). |
| site_id | string Site where the job is performed (UUID v7). Required unless the tenant set Job module |
| contact_id | string On-site Contact (UUID v7). |
| title | string Short job title. |
| scope_of_work | string Free-text scope of work (UI label: 'Job description'). |
| work_description | string Internal work description. |
| customer_notes | string Internal customer notes. |
| reference | string Partner-defined reference. |
| system_id | string Specific System instance on the site (UUID v7). Required when the System module is enabled; sets the job site when |
| job_type | string Tenant-configured job type. |
| priority | string Priority string. |
| due_date | string <date> Due date (plain calendar date). |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( | |
Array of objects (LineitemInput) Initial lineitems for the job. Each entry creates a new line.
Server populates |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Job) |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "title": "string",
- "scope_of_work": "string",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "string",
- "job_type": "string",
- "priority": "string",
- "due_date": "2019-08-24",
- "number": "string",
- "labels": [
- "Urgent"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Building A"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "ticket_id": "595be628-f6f2-4262-9c10-6389c6c4a5b8",
- "assignee_id": 0,
- "workorderable_type": { },
- "workorderable_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
- "route_id": "dd833dbc-f3c5-44d9-98a2-7ba12ebc8160",
- "route_planner_id": "feaf5141-622b-43c7-9061-98a3762c067c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "number": "string",
- "status": "string",
- "title": "Annual fire alarm inspection",
- "scope_of_work": "Inspect all 12 smoke detectors and 4 pull stations; replace any failed batteries.",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "job_type": "Annual Inspection",
- "priority": "High",
- "due_date": "2026-05-15",
- "schedule_date": "2019-08-24",
- "week_days": [
- "string"
], - "routable": true,
- "discount_type": "string",
- "discount_value": 0,
- "discount_total": 0,
- "discounts": { },
- "taxes": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "labels": [
- "Urgent",
- "Warranty"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Building A",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "2026-05-30"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Job) |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "ticket_id": "595be628-f6f2-4262-9c10-6389c6c4a5b8",
- "assignee_id": 0,
- "workorderable_type": { },
- "workorderable_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
- "route_id": "dd833dbc-f3c5-44d9-98a2-7ba12ebc8160",
- "route_planner_id": "feaf5141-622b-43c7-9061-98a3762c067c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "number": "string",
- "status": "string",
- "title": "Annual fire alarm inspection",
- "scope_of_work": "Inspect all 12 smoke detectors and 4 pull stations; replace any failed batteries.",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "job_type": "Annual Inspection",
- "priority": "High",
- "due_date": "2026-05-15",
- "schedule_date": "2019-08-24",
- "week_days": [
- "string"
], - "routable": true,
- "discount_type": "string",
- "discount_value": 0,
- "discount_total": 0,
- "discounts": { },
- "taxes": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "labels": [
- "Urgent",
- "Warranty"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Building A",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "2026-05-30"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| customer_id | string Customer the job is for (UUID v7). |
| site_id | string Site where the job is performed (UUID v7). Required unless the tenant set Job module |
| contact_id | string On-site Contact (UUID v7). |
| title | string Short job title. |
| scope_of_work | string Free-text scope of work. |
| work_description | string Internal work description. |
| customer_notes | string Internal customer notes. |
| reference | string Partner-defined reference. |
| system_id | string Specific System instance on the site (UUID v7). Required when the System module is enabled; sets the job site when |
| job_type | string Tenant-configured job type. |
| priority | string Priority string. |
| due_date | string <date> Due date. |
| status | string Tenant-configured Job status. |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
Array of objects (LineitemInput) Snapshot replace of the full lineitem list. Send |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Job) |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "title": "string",
- "scope_of_work": "string",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "string",
- "job_type": "string",
- "priority": "string",
- "due_date": "2019-08-24",
- "status": "string",
- "labels": [
- "Warranty"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "2026-06-01"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "ticket_id": "595be628-f6f2-4262-9c10-6389c6c4a5b8",
- "assignee_id": 0,
- "workorderable_type": { },
- "workorderable_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
- "route_id": "dd833dbc-f3c5-44d9-98a2-7ba12ebc8160",
- "route_planner_id": "feaf5141-622b-43c7-9061-98a3762c067c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "number": "string",
- "status": "string",
- "title": "Annual fire alarm inspection",
- "scope_of_work": "Inspect all 12 smoke detectors and 4 pull stations; replace any failed batteries.",
- "work_description": "string",
- "customer_notes": "string",
- "reference": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "job_type": "Annual Inspection",
- "priority": "High",
- "due_date": "2026-05-15",
- "schedule_date": "2019-08-24",
- "week_days": [
- "string"
], - "routable": true,
- "discount_type": "string",
- "discount_value": 0,
- "discount_total": 0,
- "discounts": { },
- "taxes": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "labels": [
- "Urgent",
- "Warranty"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Building A",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "2026-05-30"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: number, amount, status, and the customer's organization. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Estimate) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Draft",
- "title": "Q3 fire alarm refresh",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2026-05-01",
- "expiration_date": "2026-06-01",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_type": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Pending review"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Net 30 PO required"
}, - "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| title | string Short estimate title. |
| description | string Free-text description. |
| scope_of_work | string Detailed scope of work. |
| estimate_date | string <date> Issue date. |
| expiration_date | string <date> Expiration date. |
| job_type | string Tenant-configured job type. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
object Tenant-defined custom field map. | |
| customer_notes | string Customer-facing notes shown on the estimate PDF. |
| tax_rate_id | string <uuid> Tax rate ID. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
Array of objects (LineitemInput) Initial estimate lineitems. Server populates computed totals. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Estimate) A pre-sale quote / proposal sent to a Customer. Lineitems carry parts/
labor/services; the top-level |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "title": "string",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2019-08-24",
- "expiration_date": "2019-08-24",
- "job_type": "string",
- "system_id": "string",
- "reference": "string",
- "labels": [
- "Pending review"
], - "custom_fields": { },
- "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "number": "string",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Draft",
- "title": "Q3 fire alarm refresh",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2026-05-01",
- "expiration_date": "2026-06-01",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_type": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Pending review"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Net 30 PO required"
}, - "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Estimate) A pre-sale quote / proposal sent to a Customer. Lineitems carry parts/
labor/services; the top-level |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Draft",
- "title": "Q3 fire alarm refresh",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2026-05-01",
- "expiration_date": "2026-06-01",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_type": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Pending review"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Net 30 PO required"
}, - "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| title | string Short estimate title. |
| description | string Free-text description. |
| scope_of_work | string Detailed scope of work. |
| estimate_date | string <date> Issue date. |
| expiration_date | string <date> Expiration date. |
| job_type | string Tenant-configured job type. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
| customer_notes | string Customer-facing notes shown on the estimate PDF. |
| tax_rate_id | string <uuid> Tax rate ID. |
| status | string Tenant-configured Estimate status. |
Array of objects (LineitemInput) Snapshot replace of the full lineitem list. Send |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Estimate) A pre-sale quote / proposal sent to a Customer. Lineitems carry parts/
labor/services; the top-level |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "title": "string",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2019-08-24",
- "expiration_date": "2019-08-24",
- "job_type": "string",
- "system_id": "string",
- "reference": "string",
- "labels": [
- "string"
], - "custom_fields": { },
- "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "status": "string",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Draft",
- "title": "Q3 fire alarm refresh",
- "description": "string",
- "scope_of_work": "string",
- "estimate_date": "2026-05-01",
- "expiration_date": "2026-06-01",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "job_type": "string",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Pending review"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Net 30 PO required"
}, - "customer_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across the invoice's searchable fields (number, reference, amount, balance, status, and the customer's organization). Narrows the result set; ordering still follows |
| sort | string Enum: "created_at" "-created_at" "updated_at" "-updated_at" "invoice_date" "-invoice_date" "due_date" "-due_date" "number" "-number" "status" "-status" Sort the list by a single field. Prefix with |
| customer_id | string <uuid> Filter to invoices for a given customer (UUID v7). |
| number | string Filter by exact invoice number. |
string or object Filter by status. Equality ( | |
object Filter by invoice date. Operators: gte, lte, gt, lt (ISO-8601 date). | |
object Filter by due date. Operators: gte, lte, gt, lt (ISO-8601 date). |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Invoice) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Sent",
- "title": "May service",
- "invoice_date": "2026-05-01",
- "due_date": "2026-05-31",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "balance": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "paid_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Disputed"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "PO-12345",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| Idempotency-Key required | string [ 1 .. 255 ] characters Required on financial POST per CONT-09. Missing → 400 problem+json |
| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| payment_term_id | string <uuid> PaymentTerm ID. |
| title | string Short invoice title. |
| invoice_date | string <date> Issue date. |
| due_date | string <date> Due date. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
object Tenant-defined custom field map. | |
| public_notes | string Public notes (visible on customer PDF). |
| customer_notes | string Internal customer notes (not on PDF). |
| back_office_notes | string Internal accounting notes (not on PDF). |
| tax_rate_id | string <uuid> Tax rate ID. |
| po_number | string Customer's PO number. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
Array of objects (LineitemInput) Initial invoice lineitems. Server populates computed totals. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Invoice) A billable invoice issued to a Customer. Lineitems carry parts/labor/
services; |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "title": "string",
- "invoice_date": "2019-08-24",
- "due_date": "2019-08-24",
- "system_id": "string",
- "reference": "string",
- "labels": [
- "Disputed"
], - "custom_fields": { },
- "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "string",
- "number": "string",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Sent",
- "title": "May service",
- "invoice_date": "2026-05-01",
- "due_date": "2026-05-31",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "balance": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "paid_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Disputed"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "PO-12345",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Invoice) A billable invoice issued to a Customer. Lineitems carry parts/labor/
services; |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Sent",
- "title": "May service",
- "invoice_date": "2026-05-01",
- "due_date": "2026-05-31",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "balance": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "paid_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Disputed"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "PO-12345",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| payment_term_id | string <uuid> PaymentTerm ID. |
| title | string Short invoice title. |
| invoice_date | string <date> Issue date. |
| due_date | string <date> Due date. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
| public_notes | string Public notes. |
| customer_notes | string Internal customer notes. |
| back_office_notes | string Internal accounting notes. |
| tax_rate_id | string <uuid> Tax rate ID. |
| po_number | string Customer's PO number. |
Array of objects (LineitemInput) Snapshot replace of the full lineitem list. Send |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Invoice) A billable invoice issued to a Customer. Lineitems carry parts/labor/
services; |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "title": "string",
- "invoice_date": "2019-08-24",
- "due_date": "2019-08-24",
- "system_id": "string",
- "reference": "string",
- "labels": [
- "string"
], - "custom_fields": { },
- "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "string",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Sent",
- "title": "May service",
- "invoice_date": "2026-05-01",
- "due_date": "2026-05-31",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "balance": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "paid_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "taxes": { },
- "labels": [
- "Disputed"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "public_notes": "string",
- "customer_notes": "string",
- "back_office_notes": "string",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "po_number": "PO-12345",
- "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: number, status, and the customer's organization. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (SalesOrder) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Confirmed",
- "date": "2026-05-01",
- "due_date": "2026-05-15",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| Idempotency-Key required | string [ 1 .. 255 ] characters Required on financial POST per CONT-09. Missing → 400 problem+json |
| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| payment_term_id | string <uuid> PaymentTerm ID. |
| date | string <date> Order date. |
| due_date | string <date> Due date. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( | |
Array of objects (LineitemInput) Initial sales-order lineitems. Server populates computed totals. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (SalesOrder) A confirmed sale, sitting between Estimate and Invoice in the
accounting flow. SalesOrders are intentionally minimal at the
header level — line totals roll up from |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "date": "2019-08-24",
- "due_date": "2019-08-24",
- "system_id": "string",
- "reference": "string",
- "number": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Confirmed",
- "date": "2026-05-01",
- "due_date": "2026-05-15",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (SalesOrder) A confirmed sale, sitting between Estimate and Invoice in the
accounting flow. SalesOrders are intentionally minimal at the
header level — line totals roll up from |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Confirmed",
- "date": "2026-05-01",
- "due_date": "2026-05-15",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| customer_id | string Customer ID (UUID v7). |
| site_id | string Site ID (UUID v7). Service address — required unless the tenant set Job module |
| contact_id | string Contact ID (UUID v7). |
| payment_term_id | string <uuid> PaymentTerm ID. |
| date | string <date> Order date. |
| due_date | string <date> Due date. |
| system_id | string System instance ID (UUID v7). Required when the System module is enabled and a |
| reference | string Partner-defined reference. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to | |
Array of objects (LineitemInput) Snapshot replace of the full lineitem list. Send |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (SalesOrder) A confirmed sale, sitting between Estimate and Invoice in the
accounting flow. SalesOrders are intentionally minimal at the
header level — line totals roll up from |
{- "customer_id": "string",
- "site_id": "string",
- "contact_id": "string",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "date": "2019-08-24",
- "due_date": "2019-08-24",
- "system_id": "string",
- "reference": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088-rev1"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "description": "string",
- "unit_price": 0,
- "qty": 0,
- "discount": 0,
- "discount_type": "percent",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "position": 0,
- "labor_hours_per_unit": 0,
- "labor_rate": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a"
}
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "Confirmed",
- "date": "2026-05-01",
- "due_date": "2026-05-15",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "reference": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "PO-2026-088"
}, - "lineitems": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "item_id": "4d8cd62e-a579-4dae-af8c-3172f96f8f7c",
- "item_name": "string",
- "description": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "qty": "4",
- "discount": "string",
- "discount_type": { },
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "tax_applied": true,
- "position": 0,
- "discount_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "tax_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "line_total": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "labor_rate": "95.0",
- "labor_amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: name, SKU, location code, unit cost, unit price, item type, number, and the category/subcategory names. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Item) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "SKU-1234",
- "item_type": "string",
- "unit": "pcs",
- "location_code": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "unit_cost": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "active": true,
- "taxable": true,
- "reorder_point": "string",
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "case",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "EU"
}, - "inventory_levels": [
- {
- "id": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a",
- "inventory_location_name": "string",
- "quantity": "string",
- "location_code": "string",
- "reorder_point": "string"
}
], - "total_quantity": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| name required | string Display name. |
| description | string Free-text description. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| item_sku | string Stock keeping unit. |
| item_type | string Enum: "Inventory" "NonInventory" "Service" Type of item. Must be one of the three allowed values (matches the web). 'Inventory' tracks stock; 'Service' relaxes the unit requirement. Unknown values are rejected with 422 validation.failed. |
| unit | string Unit of measure ('pcs', 'lb', 'ft', 'hr', etc.). |
| location_code | string Default bin / shelf code. |
| active | boolean Active in pickers. Changing it requires the toggle-active permission (403 |
| taxable | boolean Subject to tax. |
| reorder_point | number Reorder threshold (item-level default). |
| item_category_id | string <uuid> ItemCategory FK. |
| item_subcategory_id | string <uuid> ItemSubcategory FK. |
| income_account_id | string <uuid> QBO income GL account. |
| expense_account_id | string <uuid> QBO expense GL account. |
| inventory_asset_account_id | string <uuid> QBO inventory asset GL account. |
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Item) A catalog item (inventoried part, service, or non-inventory good).
|
{- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "string",
- "item_type": "Inventory",
- "unit": "string",
- "location_code": "string",
- "active": true,
- "taxable": true,
- "reorder_point": 0,
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "case"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "SKU-1234",
- "item_type": "string",
- "unit": "pcs",
- "location_code": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "unit_cost": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "active": true,
- "taxable": true,
- "reorder_point": "string",
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "case",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "EU"
}, - "inventory_levels": [
- {
- "id": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a",
- "inventory_location_name": "string",
- "quantity": "string",
- "location_code": "string",
- "reorder_point": "string"
}
], - "total_quantity": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Item) A catalog item (inventoried part, service, or non-inventory good).
|
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "SKU-1234",
- "item_type": "string",
- "unit": "pcs",
- "location_code": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "unit_cost": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "active": true,
- "taxable": true,
- "reorder_point": "string",
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "case",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "EU"
}, - "inventory_levels": [
- {
- "id": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a",
- "inventory_location_name": "string",
- "quantity": "string",
- "location_code": "string",
- "reorder_point": "string"
}
], - "total_quantity": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| name | string Display name. |
| description | string Free-text description. |
| number | string Item number. |
| item_sku | string SKU. |
| item_type | string Enum: "Inventory" "NonInventory" "Service" Type of item. Must be one of the three allowed values (matches the web). Unknown values are rejected with 422 validation.failed. |
| unit | string Unit of measure. |
| location_code | string Default bin / shelf code. |
| active | boolean Active in pickers. Changing it requires the toggle-active permission (403 |
| taxable | boolean Subject to tax. |
| reorder_point | number Reorder threshold. |
| item_category_id | string <uuid> ItemCategory FK. |
| item_subcategory_id | string <uuid> ItemSubcategory FK. |
| income_account_id | string <uuid> QBO income GL account. |
| expense_account_id | string <uuid> QBO expense GL account. |
| inventory_asset_account_id | string <uuid> QBO inventory asset GL account. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Item) A catalog item (inventoried part, service, or non-inventory good).
|
{- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "string",
- "item_type": "Inventory",
- "unit": "string",
- "location_code": "string",
- "active": true,
- "taxable": true,
- "reorder_point": 0,
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "US"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "number": "string",
- "item_sku": "SKU-1234",
- "item_type": "string",
- "unit": "pcs",
- "location_code": "string",
- "unit_price": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "unit_cost": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "labor_hours_per_unit": "1.55",
- "active": true,
- "taxable": true,
- "reorder_point": "string",
- "item_category_id": "b40c2bb0-da8f-44b4-8f96-939fb5329d88",
- "item_subcategory_id": "6c524674-237d-49ad-8c20-c3bc4cb8ddf0",
- "income_account_id": "120da5b6-0cd6-45ee-b703-6fe22e631416",
- "expense_account_id": "f5ceaf7b-31e3-413d-9069-4d4a3986f549",
- "inventory_asset_account_id": "00f363b5-de3b-47c2-8ffa-e8d84d916100",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "case",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "EU"
}, - "inventory_levels": [
- {
- "id": 0,
- "inventory_location_id": "35afa96a-fcba-4d64-abca-23409993171a",
- "inventory_location_name": "string",
- "quantity": "string",
- "location_code": "string",
- "reorder_point": "string"
}
], - "total_quantity": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| q | string Free-text search across: number, status, title, description, and the assignee's name. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Task) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "Follow up with customer about quote",
- "description": "string",
- "status": "Open",
- "number": "string",
- "position": 0,
- "due_date": "2026-05-15",
- "completed_at": "2019-08-24T14:15:22Z",
- "taskable_type": { },
- "taskable_id": "6435a0c3-baa0-4f5a-a573-3126acc41cbe",
- "user_id": 0,
- "assignee_id": 0,
- "creator_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| title required | string Short task title. |
| description | string Free-text description. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| due_date | string <date> Due date. |
| taskable_type | string Enum: "Customer" "Job" "Lead" "Project" "SalesOrder" "Invoice" "Estimate" Parent record class name. |
| taskable_id | string Parent record ID (UUID v7). |
| user_id | integer <int64> Legacy assignee alias — prefer |
| assignee_id | integer <int64> Assignee user ID. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Task) A todo / follow-up tied to a parent record (Customer, Job, Lead, etc.)
via the polymorphic |
{- "title": "string",
- "description": "string",
- "number": "string",
- "due_date": "2019-08-24",
- "taskable_type": "Customer",
- "taskable_id": "string",
- "user_id": 0,
- "assignee_id": 0
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "Follow up with customer about quote",
- "description": "string",
- "status": "Open",
- "number": "string",
- "position": 0,
- "due_date": "2026-05-15",
- "completed_at": "2019-08-24T14:15:22Z",
- "taskable_type": { },
- "taskable_id": "6435a0c3-baa0-4f5a-a573-3126acc41cbe",
- "user_id": 0,
- "assignee_id": 0,
- "creator_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Task) A todo / follow-up tied to a parent record (Customer, Job, Lead, etc.)
via the polymorphic |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "Follow up with customer about quote",
- "description": "string",
- "status": "Open",
- "number": "string",
- "position": 0,
- "due_date": "2026-05-15",
- "completed_at": "2019-08-24T14:15:22Z",
- "taskable_type": { },
- "taskable_id": "6435a0c3-baa0-4f5a-a573-3126acc41cbe",
- "user_id": 0,
- "assignee_id": 0,
- "creator_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| title | string Short task title. |
| description | string Free-text description. |
| status | string Tenant-configured Task status. |
| due_date | string <date> Due date. |
| taskable_type | string Enum: "Customer" "Job" "Lead" "Project" "SalesOrder" "Invoice" "Estimate" Parent record class name. |
| taskable_id | string Parent record ID (UUID v7). |
| user_id | integer <int64> Legacy assignee alias — prefer |
| assignee_id | integer <int64> Assignee user ID. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Task) A todo / follow-up tied to a parent record (Customer, Job, Lead, etc.)
via the polymorphic |
{- "title": "string",
- "description": "string",
- "status": "string",
- "due_date": "2019-08-24",
- "taskable_type": "Customer",
- "taskable_id": "string",
- "user_id": 0,
- "assignee_id": 0
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "Follow up with customer about quote",
- "description": "string",
- "status": "Open",
- "number": "string",
- "position": 0,
- "due_date": "2026-05-15",
- "completed_at": "2019-08-24T14:15:22Z",
- "taskable_type": { },
- "taskable_id": "6435a0c3-baa0-4f5a-a573-3126acc41cbe",
- "user_id": 0,
- "assignee_id": 0,
- "creator_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: number, status, organization, industry, labels, the assignee's name, and the site address. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Lead) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Lead Co.",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "status": "New",
- "number": "string",
- "labels": [
- "Hot lead",
- "Trade show"
], - "lead_notes": "string",
- "position": 0,
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "trade_show",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| organization required | string Display name. Unique per tenant. |
| industry | string Free-text industry label. |
| main_phone | string Primary phone. |
| fax | string Fax number. |
| website | string Website URL. |
| description | string Free-text lead description. |
| assignee_id | integer <int64> Assignee user ID. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
| lead_notes | string Internal rich-text notes. |
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Lead) A pre-conversion sales prospect. Mirror of Customer with a pipeline-
oriented status flow ("New" → "Contacted" → "Qualified" → "Converted"
/ "Lost"). Converting a lead to a Customer is not exposed via v2 —
setting |
{- "organization": "Lead Co.",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "number": "string",
- "labels": [
- "Hot lead"
], - "lead_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "trade_show"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Lead Co.",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "status": "New",
- "number": "string",
- "labels": [
- "Hot lead",
- "Trade show"
], - "lead_notes": "string",
- "position": 0,
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "trade_show",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Lead) A pre-conversion sales prospect. Mirror of Customer with a pipeline-
oriented status flow ("New" → "Contacted" → "Qualified" → "Converted"
/ "Lost"). Converting a lead to a Customer is not exposed via v2 —
setting |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Lead Co.",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "status": "New",
- "number": "string",
- "labels": [
- "Hot lead",
- "Trade show"
], - "lead_notes": "string",
- "position": 0,
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "trade_show",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| organization | string Display name. |
| industry | string Free-text industry label. |
| main_phone | string Primary phone. |
| fax | string Fax number. |
| website | string Website URL. |
| description | string Free-text lead description. |
| assignee_id | integer <int64> Assignee user ID. |
| status | string Tenant-configured Lead status display_name. |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
| lead_notes | string Internal rich-text notes. |
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Lead) A pre-conversion sales prospect. Mirror of Customer with a pipeline-
oriented status flow ("New" → "Contacted" → "Qualified" → "Converted"
/ "Lost"). Converting a lead to a Customer is not exposed via v2 —
setting |
{- "organization": "string",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "status": "string",
- "labels": [
- "Trade show"
], - "lead_notes": "string",
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "google"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization": "Lead Co.",
- "industry": "string",
- "main_phone": "string",
- "fax": "string",
- "website": "string",
- "description": "string",
- "assignee_id": 0,
- "status": "New",
- "number": "string",
- "labels": [
- "Hot lead",
- "Trade show"
], - "lead_notes": "string",
- "position": 0,
- "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "trade_show",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
object Filter by custom field value: | |
| q | string Free-text search across: number, name, status, labels, source, description, the customer's/lead's organization, and the assignee's name. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Deal) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "number": "string",
- "status": "string",
- "description": "string",
- "source": "string",
- "probability": 60,
- "close_date": "2019-08-24",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "lead_id": "9bddab70-98e6-43a9-8f32-c9788b9de0c0",
- "assignee_id": 0,
- "labels": [
- "High value"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Inbound",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| name required | string Short deal name. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| description | string Free-text description. |
| source | string Lead source / channel. |
| probability | number Win probability percentage 0–100. |
| close_date | string <date> Expected close date. |
| customer_id | string <uuid> Customer FK UUID v7 (mutually exclusive with lead_id). |
| lead_id | string <uuid> Lead FK UUID v7 (mutually exclusive with customer_id). |
| assignee_id | integer <int64> Assignee user ID. |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
object Tenant-defined custom field values. Keys are custom-field definition
UUIDs ( |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Deal) A sales opportunity attached to either a Customer or a Lead (mutually
exclusive — pre-conversion deals carry |
{- "name": "string",
- "number": "string",
- "description": "string",
- "source": "string",
- "probability": 0,
- "close_date": "2019-08-24",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "lead_id": "9bddab70-98e6-43a9-8f32-c9788b9de0c0",
- "assignee_id": 0,
- "labels": [
- "High value"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Inbound"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "number": "string",
- "status": "string",
- "description": "string",
- "source": "string",
- "probability": 60,
- "close_date": "2019-08-24",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "lead_id": "9bddab70-98e6-43a9-8f32-c9788b9de0c0",
- "assignee_id": 0,
- "labels": [
- "High value"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Inbound",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Deal) A sales opportunity attached to either a Customer or a Lead (mutually
exclusive — pre-conversion deals carry |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "number": "string",
- "status": "string",
- "description": "string",
- "source": "string",
- "probability": 60,
- "close_date": "2019-08-24",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "lead_id": "9bddab70-98e6-43a9-8f32-c9788b9de0c0",
- "assignee_id": 0,
- "labels": [
- "High value"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Inbound",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| name | string Short deal name. |
| status | string Tenant-configured Deal status. |
| description | string Free-text description. |
| source | string Lead source. |
| probability | number Win probability percentage 0–100. |
| close_date | string <date> Expected close date. |
| customer_id | string Customer FK (UUID v7). |
| lead_id | string Lead FK (UUID v7). |
| assignee_id | integer <int64> Assignee user ID. |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
object Merges into existing custom fields — keys not in the payload are
preserved. Set a key to |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Deal) A sales opportunity attached to either a Customer or a Lead (mutually
exclusive — pre-conversion deals carry |
{- "name": "string",
- "status": "string",
- "description": "string",
- "source": "string",
- "probability": 0,
- "close_date": "2019-08-24",
- "customer_id": "string",
- "lead_id": "string",
- "assignee_id": 0,
- "labels": [
- "string"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q4-2026"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "number": "string",
- "status": "string",
- "description": "string",
- "source": "string",
- "probability": 60,
- "close_date": "2019-08-24",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "lead_id": "9bddab70-98e6-43a9-8f32-c9788b9de0c0",
- "assignee_id": 0,
- "labels": [
- "High value"
], - "custom_fields": {
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "Inbound",
- "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7c": "Q3-2026"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| q | string Free-text search across: number, name, status, project type, the customer's organization, the site address, and the contact's name. Narrows results; ordering follows |
| sort | string Sort by a single field; prefix with |
object Filter by creation time. Operators: gte, lte, gt, lt (ISO-8601). | |
object Filter by last-update time. Operators: gte, lte, gt, lt (ISO-8601). | |
string or object Filter by status. Equality ( |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Project) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "name": "Acme HQ retrofit",
- "status": "Active",
- "description": "string",
- "project_type": "customer",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "user_ids": [
- 0
], - "labels": [
- "Phase-1",
- "Behind schedule"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| name required | string Short project name. |
| number | string Optional document number. When omitted the server auto-generates a sequential value; when supplied it is respected and must be unique per tenant. Immutable after creation (cannot be changed via PATCH). |
| description | string Free-text description. |
| project_type | string Enum: "customer" "internal" Required (mirrors the web's New-project chooser). 'customer' needs customer_id and a service address; 'internal' needs only a name. Unknown values are rejected with 422 validation.failed. |
| customer_id | string Customer FK (UUID v7). Required for customer-type projects; omitted for internal projects. |
| site_id | string Site FK (UUID v7). Service address for customer-type projects — required unless the tenant set Job module |
| assignee_id | integer <int64> Assignee (project manager) user ID. |
| contact_id | string Primary Contact FK (UUID v7). |
| user_ids | Array of integers <int64> [ items <int64 > ] Project team — array of User IDs (HABTM). An id that is not a user in this account is a 422 on |
| labels | Array of strings Tenant-defined labels to apply. Each value must match a Label
|
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Project) A long-lived multi-job engagement (think: kitchen remodel, building
retrofit). Aggregates Jobs, Estimates, Invoices, etc. under a single
identity. |
{- "name": "string",
- "number": "string",
- "description": "string",
- "project_type": "customer",
- "customer_id": "string",
- "site_id": "string",
- "assignee_id": 0,
- "contact_id": "string",
- "user_ids": [
- 0
], - "labels": [
- "Phase-1"
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "name": "Acme HQ retrofit",
- "status": "Active",
- "description": "string",
- "project_type": "customer",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "user_ids": [
- 0
], - "labels": [
- "Phase-1",
- "Behind schedule"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Project) A long-lived multi-job engagement (think: kitchen remodel, building
retrofit). Aggregates Jobs, Estimates, Invoices, etc. under a single
identity. |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "name": "Acme HQ retrofit",
- "status": "Active",
- "description": "string",
- "project_type": "customer",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "user_ids": [
- 0
], - "labels": [
- "Phase-1",
- "Behind schedule"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| name | string Short project name. |
| status | string Tenant-configured Project status. |
| description | string Free-text description. |
| project_type | string Enum: "customer" "internal" 'customer' or 'internal'. The web sets it at creation and does not change it afterwards; unknown values are rejected with 422 validation.failed. |
| customer_id | string Customer FK (UUID v7). Required for customer-type projects. |
| site_id | string Site FK (UUID v7). Service address for customer-type projects — required unless the tenant set Job module |
| assignee_id | integer <int64> Assignee user ID. |
| contact_id | string Primary Contact FK (UUID v7). |
| user_ids | Array of integers <int64> [ items <int64 > ] Replaces the project team (HABTM). An id that is not a user in this account is a 422 on |
| labels | Array of strings Replaces the full label list. Each value must match a Label
|
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Project) A long-lived multi-job engagement (think: kitchen remodel, building
retrofit). Aggregates Jobs, Estimates, Invoices, etc. under a single
identity. |
{- "name": "string",
- "status": "string",
- "description": "string",
- "project_type": "customer",
- "customer_id": "string",
- "site_id": "string",
- "assignee_id": 0,
- "contact_id": "string",
- "user_ids": [
- 0
], - "labels": [
- "string"
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "name": "Acme HQ retrofit",
- "status": "Active",
- "description": "string",
- "project_type": "customer",
- "amount": {
- "amount_cents": 12345,
- "currency_iso_4217": "USD"
}, - "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "assignee_id": 0,
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "user_ids": [
- 0
], - "labels": [
- "Phase-1",
- "Behind schedule"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
{- "title": "Authorization header missing",
- "status": 401,
- "code": "auth.missing_token",
- "detail": "Provide an Authorization: Bearer <token> header.",
- "instance": "/api/v2/customers",
- "request_id": "01J0Z9V6Q5G3R7M9F1H2K3T4N5",
- "errors": {
- "site_id": [
- "was not found in this account"
]
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Tool) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "display_name": "string",
- "tool_type": "string",
- "manufacturer": "string",
- "model_number": "string",
- "serial_number": "string",
- "description": "string",
- "current_location": "string",
- "active": true,
- "assignee_id": 0,
- "held_since": "2019-08-24",
- "requested_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Tool) Tracked equipment / tools assigned to technicians. Read-only via the API; comments at /api/v2/tools/{id}/notes. |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "display_name": "string",
- "tool_type": "string",
- "manufacturer": "string",
- "model_number": "string",
- "serial_number": "string",
- "description": "string",
- "current_location": "string",
- "active": true,
- "assignee_id": 0,
- "held_since": "2019-08-24",
- "requested_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Vendor) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "organization": "string",
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "main_phone": "string",
- "mobile_phone": "string",
- "fax": "string",
- "website": "string",
- "street": "string",
- "city": "string",
- "state": "string",
- "zip_code": "string",
- "description": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Vendor) Suppliers referenced by purchase orders and item costs. Read-only via the API; comments at /api/v2/vendors/{id}/notes. |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "organization": "string",
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "main_phone": "string",
- "mobile_phone": "string",
- "fax": "string",
- "website": "string",
- "street": "string",
- "city": "string",
- "state": "string",
- "zip_code": "string",
- "description": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Ticket) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "title": "string",
- "description": "string",
- "status": "string",
- "assignee_id": 0,
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Ticket) Support tickets raised against a customer / site / system. Read-only via the API; comments at /api/v2/tickets/{id}/notes. |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "title": "string",
- "description": "string",
- "status": "string",
- "assignee_id": 0,
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (PurchaseOrder) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "string",
- "po_date": "2019-08-24",
- "due_date": "2019-08-24",
- "vendor_id": "98232994-9d54-43ee-a280-d7c895362d0c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "sales_order_id": "5e95a238-d0d8-4280-92bc-08d83c9c12a6",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "public_notes": "string",
- "custom_fields": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (PurchaseOrder) Purchase orders issued to vendors. Line items are not exposed yet. Read-only via the API; comments at /api/v2/purchase_orders/{id}/notes. |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "status": "string",
- "po_date": "2019-08-24",
- "due_date": "2019-08-24",
- "vendor_id": "98232994-9d54-43ee-a280-d7c895362d0c",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "sales_order_id": "5e95a238-d0d8-4280-92bc-08d83c9c12a6",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "public_notes": "string",
- "custom_fields": { },
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (RecurringJob) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "job_type": "string",
- "scope_of_work": "string",
- "frequency": "string",
- "next_date": "2019-08-24",
- "active": true,
- "reference": "string",
- "labels": [
- "string"
], - "assignee_id": 0,
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (RecurringJob) Recurring job schedules that generate jobs on |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "job_type": "string",
- "scope_of_work": "string",
- "frequency": "string",
- "next_date": "2019-08-24",
- "active": true,
- "reference": "string",
- "labels": [
- "string"
], - "assignee_id": 0,
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (RecurringInvoice) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "reference": "string",
- "frequency": "string",
- "next_date": "2019-08-24",
- "labels": [
- "string"
], - "customer_notes": "string",
- "back_office_notes": "string",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}| id required | string <uuid> Server-generated UUID v7 identifier. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (RecurringInvoice) Recurring invoice schedules that generate invoices on |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "number": "string",
- "reference": "string",
- "frequency": "string",
- "next_date": "2019-08-24",
- "labels": [
- "string"
], - "customer_notes": "string",
- "back_office_notes": "string",
- "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
- "contact_id": "f245e2a3-e141-4d41-912c-b1c1f5bd5598",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_id": "6ed1f7c4-3772-4fa8-92a5-defb7f18dbc4",
- "tax_rate_id": "6156135d-450b-464c-b854-039a7690a62e",
- "payment_term_id": "d5e53127-7029-4c3e-a9e2-28cd951529f8",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on a record (/api/v2/
User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}User-authored comments on the parent record, newest first. System
activity entries (record created, viewed, address changed, …) are
excluded. Requires the parent resource's <resource>:read scope
(e.g. jobs:read for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| Link | string RFC 5988 link to next page. Format: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Note) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Requires the parent resource's <resource>:write scope
(e.g. jobs:write for /api/v2/jobs/{id}/notes).
| id required | string <uuid> Parent record UUID v7. |
required | object |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (Note) A user-authored comment on a record (the web "Comments" tab). |
{- "note": {
- "description": "Called back, wants a quote by Friday."
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "description": "string",
- "author_id": 0,
- "author_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Read-only reference catalogs (payment terms, tax rates, job types, item categories, system options, labels). Resolve FKs and validate categorical fields on other resources.
Returns the tenant's catalog of PaymentTerm rows (Net-15, Net-30,
custom, etc.). Use the id returned here to set
Invoice.payment_term_id and SalesOrder.payment_term_id.
Archived rows are filtered out.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (PaymentTerm) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Net 30",
- "due_days": 0,
- "term_type": { },
- "default": true,
- "archived": true,
- "position": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of TaxRate rows. Use the id returned
here to set tax_rate_id on Invoice / Estimate / Job / Lineitem.
Archived and discarded rows are filtered out.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (TaxRate) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "NY Sales Tax",
- "rate": 0.08875,
- "default": true,
- "archived": true,
- "position": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of JobType rows. Use the
display_name returned here as the value to post for
Job.job_type / Estimate.job_type (those fields are free-form
strings backed by this catalog). Discarded rows are filtered out.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (JobType) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Annual Inspection",
- "position": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of ItemCategory rows. Use the id
returned here to set Item.item_category_id and
Item.item_subcategory_id. Subcategories are modeled via the
parent_item_category_id self-FK — categories with that field set
are subcategories of the parent.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (ItemCategory) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Plumbing Fixtures",
- "parent_item_category_id": "a63beda9-a8de-4525-82c6-f7d9196da97d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of SystemOption rows (Fire Alarm, HVAC,
Sprinkler, etc.). Use the id returned here to set
Site.system_option_id. has_device_inventory distinguishes systems
that track devices (e.g. extinguishers) from those that don't.
Discarded rows are filtered out.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (SystemOption) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "system_type": "Fire Alarm",
- "has_device_inventory": true,
- "position": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of Label rows. Labels are tenant-defined
per-resource categorical tags — the related_name column constrains
which resource type each label applies to (Customer / Lead / Job /
Deal / Estimate / Invoice / Project).
Use the display_name returned here as the value to put in the
labels: [] array on the parent resource. Partners write strings,
not ids — labels are stored as display_name strings in the JSONB
column on every parent record, and label renames are migrated to
existing records by the server (LabelsUpdateRelatedJob).
Filter to one resource type via ?related_name=Customer.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| related_name | string Enum: "Customer" "Lead" "Job" "Deal" "Estimate" "Invoice" "Project" Filter to a single resource type's label catalog. Omit to list all. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (Label) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "VIP",
- "related_name": "Customer",
- "description": "string",
- "color": "#FFB300",
- "position": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns the tenant's catalog of StatusOption rows. Statuses are
tenant-configurable per resource type — the related_name column
constrains which resource each status applies to (Customer / Job /
Estimate / Invoice / Lead / Deal / Project / Task / ...).
Use the display_name returned here as the value to put in the
status field on the parent resource. Writes are validated against
these values; an unknown status is rejected with 422 status.transition_invalid.
Filter to one resource type via ?related_name=Customer.
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| related_name | string Filter to a single resource type's status catalog (e.g. Customer, Job, Estimate). Omit to list all. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (StatusOption) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Active",
- "related_name": "Customer",
- "description": "string",
- "color": "#31B237",
- "position": 0,
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Read-only discovery of tenant-defined custom-field templates and their field definitions. Use to interpret the custom_fields JSONB on Customer, Lead, Job, Estimate, Invoice, and other resources.
Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Stores the uploaded file and sets the field to {"url", "filename"}
(the same shape the web app writes), replacing any previous value.
Only an uploaded file is accepted — a URL cannot be set as the value.
Any content type; maximum 10 MB. Requires the resource's
<resource>:write scope and If-Match, like PATCH. Other field types
are written with PATCH custom_fields (422 here).
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| file required | string <binary> |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Removes the field's key from custom_fields. Same scope and If-Match rules as PUT.
| id required | string <uuid> Record UUID v7. |
| field_id required | string <uuid> Attachment-type custom field definition id (GET /api/v2/custom_field_definitions). |
| If-Match required | string^W/"[0-9]+-[0-9]+"$ Weak ETag from a prior GET on this resource. Mismatched ETag emits 412 Precondition Failed; missing header on PATCH/DELETE emits 428 Precondition Required. |
| ETag | string^W/"[0-9]+-[0-9]+"$ Examples: "W/\"1745596800-3\"" Weak ETag — |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object |
{- "data": { }
}Returns the tenant's catalog of custom-field definition groups — one per module (Customer, Lead, Job, Estimate, Invoice, etc.) plus optional SystemOption-scoped sub-groups (Device, DeviceInspection).
Use the id of each entry inside fields[] as the JSONB key when
reading or writing the custom_fields blob on the parent resource.
For example, a Customer with
custom_fields: { "0190a1f2-1c3d-7e4f-8a9b-2c3d4e5f6a7b": "blue" }
means that field id (e.g. "Preferred color") is set to "blue".
Filter by module via ?related_name=Customer (case-sensitive,
matches the group's related_name — see the enum on
CustomFieldDefinitionGroup.related_name).
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| related_name | string Enum: "Customer" "Contact" "Job" "SalesOrder" "Invoice" "PurchaseOrder" "Bill" "Estimate" "Site" "Item" "Lead" "Deal" "Device" "DeviceInspection" "SystemOption" Filter to a single module's definition group(s). Omit to list all. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (CustomFieldDefinitionGroup) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Customer",
- "related_name": "Customer",
- "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "Preferred contact time",
- "field_type": "dropdown",
- "position": 0,
- "required": false,
- "options": [
- "morning",
- "afternoon",
- "evening"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Returns a single definition group by id, including its ordered list of field definitions. 404 if the id does not belong to the authenticated tenant.
| id required | string <uuid> Custom field definition group id. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
| id required | string <uuid> Server-generated UUID v7 identifier. |
| display_name | string or null Human-readable name (typically equal to |
| related_name required | string Enum: "Customer" "Contact" "Job" "SalesOrder" "Invoice" "PurchaseOrder" "Bill" "Estimate" "Site" "Item" "Lead" "Deal" "Device" "DeviceInspection" "SystemOption" Canonical module key the definition group applies to. Use this to find the definitions for a given resource type. |
| parent_id | string or null <uuid> Self-FK (UUID). Non-null only for SystemOption-scoped sub-groups (Device, DeviceInspection). |
Array of objects (CustomFieldDefinition) Ordered list of field definitions. Order matches | |
| created_at required | string <date-time> ISO 8601 UTC creation timestamp. |
| updated_at required | string <date-time> ISO 8601 UTC last-mutation timestamp. |
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "Customer",
- "related_name": "Customer",
- "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "label": "Preferred contact time",
- "field_type": "dropdown",
- "position": 0,
- "required": false,
- "options": [
- "morning",
- "afternoon",
- "evening"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Serviced equipment on a Site (list + create; System module only). Resolve system_id for jobs, estimates, invoices and sales orders.
Returns the tenant's Systems — pieces of serviced equipment (HVAC unit,
fire panel, etc.) attached to a Site. On tenants with the System
module enabled, Job requires a system_id; resolve a valid id here
and post it on job create. Discarded rows are filtered out.
Optional filters narrow the list to the parent you're creating a job for:
?site_id=<uuid> (systems on one Site) or ?customer_id=<uuid>
(systems on any Site belonging to that Customer).
Available only when the System module is enabled for the tenant
(otherwise 403).
| cursor | string Opaque HMAC-signed pagination cursor. Omit on the first page; partners pass through verbatim — they MUST NOT decode or modify it (the signing secret rotates annually per D-21). |
| limit | integer [ 1 .. 100 ] Default: 25 Maximum number of items per page. Capped at 100 (CONT-07); requesting more emits 400 problem+json |
| site_id | string <uuid> Filter to systems on a specific Site. |
| customer_id | string <uuid> Filter to systems on any Site belonging to this Customer. |
object Filter by custom field value: |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | Array of objects (System) |
| has_more required | boolean |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "system_type": "Fire Alarm",
- "description": "string",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "has_device_inventory": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "has_more": true
}Creates a System on a Site. Requires the System module.
Provide site_id (a Site in your tenant) and system_option_id (the
type, from GET /api/v2/system_options). system_type and
has_device_inventory are derived server-side from the SystemOption,
so they are not accepted in the body.
Duplicate guard (web parity): if a System of the same
system_option_id already exists on the same site_id, the request is
refused with 409 system.duplicate. Resend with "confirmed": true to
create it anyway (mirrors the web confirmation dialog).
| site_id required | string <uuid> UUID v7 FK to the parent Site (must belong to your tenant). |
| system_option_id required | string <uuid> UUID v7 FK to the SystemOption (type). See GET /api/v2/system_options. |
| description | string Optional free-text description. |
| confirmed | boolean Set true to create even if a system of this type already exists on the site (otherwise 409 system.duplicate). |
object Tenant-defined custom field values keyed by definition UUID. See GET /api/v2/custom_field_definitions?related_name=System. |
| RateLimit-Limit | integer Requests permitted in the current window. |
| RateLimit-Remaining | integer Requests remaining in the current window. |
| RateLimit-Reset | integer Seconds until the window resets. |
required | object (System) A piece of serviced equipment attached to a Site. Set |
{- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "description": "string",
- "confirmed": true,
- "custom_fields": { }
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "system_type": "Fire Alarm",
- "description": "string",
- "site_id": "72771e6a-6f5e-4de4-a5b9-1266c4197811",
- "system_option_id": "abbc4268-b361-493d-a39f-efc997227e78",
- "has_device_inventory": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}