Customers
List customer contracts and job costs
/a/Customer_contractsGetDT
Build the legacy customer Contracts table with direct jobs, costs, stock, labour, vehicles, dates, and file counts.
When to use this endpoint
Use Customer_contractsGetDT for the CRM1 customer Contracts panel, where a contract row is meaningful only when the requested customer has direct jobs on that contract.
The response performs several per-contract calculations and is not a lightweight contract lookup.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session. The handler performs no additional page or role-permission check.
The lookup and any write use the authenticated tenant; an ID from another tenant cannot be addressed through this call.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cid | Integer string | Consumed | Customer ID. It is read without presence, positivity, or existence validation. |
start | Integer string | Yes | Zero-based contract-query offset. Only presence is validated. |
length | Integer string | Consumed | Contract-query page size; read without explicit validation. |
draw | Integer string | No | DataTables counter copied to the response; defaults to 0. |
order[0][column] | Integer string | Consumed | 0 ID, 1 name, 9 creation date, 10 expiry date, or 11 active state; other values use name. |
order[0][dir] | String | Consumed | Exact desc selects descending; other values select ascending. |
search[value] | String | Consumed | Substring match on contract name; a numeric search also matches exact contract ID. |
active | Integer string | No | Exact active-state filter. Presence matters, so 0 selects inactive contracts. |
name | String | No | Additional contract-name substring filter. |
notes | String | No | Additional contract-notes substring filter. |
Example request
$contracts = FM_api('Customer_contractsGetDT', [
'cid' => '1088',
'start' => '0',
'length' => '10',
'draw' => '5',
'order' => [['column' => '1', 'dir' => 'asc']],
'search' => ['value' => 'maintenance'],
'active' => '1',
]);
Example response
{
"draw": 5,
"recordsTotal": "12",
"recordsFiltered": "1",
"data": [
["41", "Annual Maintenance", "C-0041", "2", [["7204","2026-09-24 10:30:00","JOB-7204","12"]], "5000.00", "80.00", "12.00", ["45.00",32.5,"5.00"], "Annual cover", [["36","2.0"]], [["7","18"]], [], "300.00", "369.00", "69.00", "", "1", "2026-01-01 09:00:00", "2026-01-01", "2026-12-31", null, 1]
]
}
The 23 positions are contract ID, name, number, type ID, jobs, budget, labour cost, mileage cost, [stock cost, Schedule of Rates cost, miscellaneous cost], notes, labour entries, vehicle entries, decoded stock groups, net, gross, tax, blank placeholder, active state, creation date, start date, expiry date, completion date, and non-deleted file count.
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"missing or invalid parameter: start"} | start is absent. |
Runtime warning or coerced defaults | The other legacy DataTables fields are absent. Send the complete request shape. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Only non-deleted contracts whose stored
customerstext matches the legacy suffix pattern%,<cid>]%are selected. This is a textual JSON-shape assumption, not parsed membership.recordsTotalis the tenant-wide count of all non-deleted contracts, not a customer count. - Jobs shown in the nested list require
customer_type=0, the requested customer ID, matchingcontract_id, and not deleted; they are ordered by job time ascending. - Aggregate financial values use non-deleted linked meetings whose numeric customer ID matches, but do not also constrain
customer_type. - Schedule of Rates labour component cost is multiplied by the job’s SOR quantity. Stock component cost is calculated as average stock cost times component quantity but is not multiplied by the SOR-row quantity, preserving the legacy calculation.
- Contract file count includes non-deleted files of type
14. Jobs related through relationship type6feed the aggregate financial calculation.
See it in Fieldmotion
CRM1
Open a customer and select Contracts. Filter Network requests for Customer_contractsGetDT; searching, active-state filtering, sorting, and paging reload this endpoint.
CRM2
A source search found no CRM2 caller for this legacy customer Contracts table.
Related endpoints
Customer_financialsGetDTreturns job-level financial rows rather than contract aggregates.- The customer Jobs data-table endpoint provides the wider customer job list.