Contracts
Get requested contract details
/a/Contract_getRequestedDetails
Fetch selected mapped contract fields, optionally expanding each row with the totals and display values used by CRM2’s contract detail page.
When to use this endpoint
Use Contract_getRequestedDetails for CRM2 contract layouts and relationship pickers that need named mapped fields.
Set isContractMain=1 only for the full Contract detail view; the enrichment performs substantial per-row cost and relationship work.
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 |
|---|---|---|---|
id / ids | Integer string or native array | No | Optional contract IDs. With neither supplied, every matching non-deleted contract is returned without a limit. |
fields | Native array | No | Mapped fields to return; defaults to every field-map key. Unknown names are ignored and id is always included. |
Mapped field filters | Scalar or array | No | Supplying a map key outside fields also filters: text uses case-insensitive exact match and numeric values use equality/IN. |
order | Field name or array | No | Mapped ordering fields, optionally objects with id and dir=desc. Unknown fields are ignored. |
advanceSearch | Array | No | Shared mapped advanced-search clauses. |
isContractMain | Integer string | No | Exact integer 1 adds cost, price, job, customer/asset, and formatted-date fields. Any other present value causes this wrapper to return JSON null instead of the base result. |
Example request
$rows = FM_api('Contract_getRequestedDetails', [
'id' => ['720'],
'fields' => ['id', 'name', 'cDate', 'customers', 'budget', 'expiryDate', 'meta'],
'isContractMain' => '1',
]);
Example response
[
{
"id": 720,
"name": "North Region Service Contract",
"cDate": "Sep 25, 2026 10:30 AM",
"customers": "[[0,1042],[1,418]]",
"budget": "25000",
"expiryDate": "Sep 30, 2027",
"meta": "{\"stage\":\"renewal\"}",
"labourCost": "1250.00",
"mileageCost": "80.00",
"stockCost": "450.00",
"sorCost": 120,
"miscCost": "25.00",
"netPrice": "3000.00",
"grossPrice": "3690.00",
"jobs": [2039001],
"customerAssetID": "[1042,418]",
"sorCostPerJob": "[{\"id\":2039001,\"sorCost\":120}]"
}
]
Without main-page enrichment, only requested mapped keys are returned and stored JSON remains encoded. Enrichment appends all derived keys shown regardless of the requested field list.
Main-page expiryDate becomes No Expiration for null; cDate, expiry, and completion fields are reformatted for display.
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. |
[] | No non-deleted contract matches the IDs/filters. |
null | isContractMain is present but does not convert to 1. |
Runtime warnings or incomplete derived values | Main enrichment is requested without the mapped base fields it indexes, or a linked schedule-of-rates/stock record is missing. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- The base query excludes soft-deleted contracts but has no built-in pagination or limit.
- Main mode performs batched link/job/file reads followed by additional schedule-of-rates and stock lookups. Only completed/deleted filtering explicitly present in each query applies.
- When
customersDirtyis set, it rebuilds customer/asset relationships and touches the contract before constructing derived customer IDs. - The output
customerAssetIDdeliberately drops type information and can contain colliding customer/asset IDs.
Side effects
- A dirty customer-cache rebuild replaces relationship rows and updates
customers,meta, andlast_edited. Ordinary reads have no write side effect.
See it in Fieldmotion
CRM1
No direct production CRM1 caller was found; CRM1 uses Contract_get and purpose-built tables.
CRM2
Open a contract’s main detail page and filter Network requests for Contract_getRequestedDetails. CRM2 sends isContractMain=1 plus the full set of base fields required by enrichment; orders, assets, financials, history, and quote modules also request smaller field sets.
Related endpoints
Contracts_getDataTableprovides paged/list mapped queries.Contract_updateDatawrites the same field-map keys.Contract_getreturns the unselected legacy full row.