Quotes: queries, documents and delivery
Load quote form and costing widgets
/a/Quote_getLayoutDetails
Build mapped quote fields and widget rows for the CRM2 layout editor.
When to use this endpoint
Use when opening a quote layout with costing tables or form-answer widgets. It returns a list even for one ID.
Authentication and permissions
Authenticate with signed API-key fields or a CRM session. Requires Quotes View (pageQuotes_view); non-admin users blocked by legacy crm_access bit 32 are denied. Client administrators inherit page permissions.
Quote visibility follows the account’s department/account-manager customer filters for non-admin users, including signed keys. Export routes additionally require pageMain_exportTableData. Linked Jobs require Jobs View and their TeamAccess scope; invoice enrichment requires Invoices View and the legacy invoice access check.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id / ids | Scalar ID or native array of IDs | ID or customer selector | Positive scalar/native ID list. Missing, null, empty or malformed selectors fail unless a positive customerID/customer picker filter is supplied. id takes precedence. |
fields | Native array of mapped/widget names | Yes | Use ordinary mapped aliases plus widgetTableStock, widgetTableSOR, widgetTableLabour, widgetTableOther, widgetTableVerbose, widgetTableSummary and widgetFormField. Unknown aliases are ignored. Do not JSON-encode. |
Mapped field filters | Mapped scalar, array or picker object | No | Top-level mapped aliases filter by equality/in-list; text is trimmed/case-folded. Numeric scalar filters integer-convert, including decimal fields in this detail helper. Picker aliases such as customer accept an object containing id. |
order | Native array of mapped names or {id,dir} objects | No | Mapped order only; desc is recognized explicitly. No default order, page size or ID-input-order guarantee. |
advanceSearch | Native array of CRM filter rows | No | Shared advanced filter input; use mapped field conditions only. Raw SQL filter controls are legacy internals and must not be accepted from untrusted callers. |
Example request
$widgets = FM_api('Quote_getLayoutDetails', [
'id'=>'1042',
'fields'=>['id','widgetTableStock','widgetTableSummary'],
]);
Example response
[{"id":"1042","widgetTableStock":{"customerID":"1088","customerType":0},"widgetTableSummary":{"discountRate":0}}]
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: fields"} | fields omitted/null. |
{"error":"permission denied"} | Required Quotes/Export permission is absent or legacy access restrictions apply. |
{"error":"missing or invalid parameter: id"} | A positive explicit ID list or supported positive customer selector is required. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Uses the same validated explicit id/ids or positive customer selection as Quote_getRequestedDetails, with active quote/customer visibility. fields must be a native list.
- Builds widgetTableStock, widgetTableSOR, widgetTableLabour, widgetTableOther and widgetTableVerbose from stored rows through their widget maps. Unknown keys/non-row entries are omitted; legacy tax values are preserved. This is a projection, not a cost recalculation.
- Cost widgets supply customerID and customerType=0, with rows only when the section exists. Supporting fields not originally requested are removed; picker backing fields can remain.
- Explicitly requested non-null meta is decoded here; ordinary formFields remains stored JSON text/null. widgetFormField contains formID/formFields. widgetTableSummary keeps the fractional discountRate as a number instead of truncating it to an integer.
- Mapped sorting and advanced filter structures are validated; raw SQL/grouping is not supported. No pagination or primary writes.
- No direct caller for this endpoint was found in the mobile app or its m-service intermediary.
Side effects
- Reads active permitted records without quote cost, history, email or derived Job-cache writes.
See it in Fieldmotion
CRM1
No direct caller found; CRM1 uses raw Quote_get and Quote_costsGet.
CRM2
Quotes → open a layout/cost group: moduleQuotes beforeGroupValueLoad calls Quote_getLayoutDetails with the five costing widget names; inspect that request.
Related endpoints
Quote_getRequestedDetailsreads mapped values without layout widget conversion.Quote_costsGetreturns the raw costs object.