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

ParameterTypeRequiredDescription
id / idsScalar ID or native array of IDsID or customer selectorPositive scalar/native ID list. Missing, null, empty or malformed selectors fail unless a positive customerID/customer picker filter is supplied. id takes precedence.
fieldsNative array of mapped/widget namesYesUse ordinary mapped aliases plus widgetTableStock, widgetTableSOR, widgetTableLabour, widgetTableOther, widgetTableVerbose, widgetTableSummary and widgetFormField. Unknown aliases are ignored. Do not JSON-encode.
Mapped field filtersMapped scalar, array or picker objectNoTop-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.
orderNative array of mapped names or {id,dir} objectsNoMapped order only; desc is recognized explicitly. No default order, page size or ID-input-order guarantee.
advanceSearchNative array of CRM filter rowsNoShared 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

ResponseCondition
{"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