Purchase orders
Read an order layout projection
/a/PurchaseOrder_getLayoutDetails
Load Purchase Order fields with optional supplier cards and Goods Received links.
When to use this endpoint
Use for CRM2 order-page layouts. It adds layout enrichment around the same mapped read used by PurchaseOrder_getRequestedDetails; it is not the raw PurchaseOrder_get object.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. Session requests use dispatcher CSRF protection when configured.
Requires explicit View on Purchase Order or Purchase Orders. Writes also require the matching Edit permission; clearing invoice details requires Delete. A non-administrator blocked by the legacy Purchase Orders visibility flag (crm_access bit 256) is denied. API keys use their owner’s permissions.
The primary order is checked against the current tenant and Purchase Order record scope. Configured TeamAccess follows permitted linked Contracts, Customers, Jobs, Quotes and Departments; the legacy department filter follows direct Customer/Quote/customer-Job links. An inaccessible or missing order returns purchase order does not exist.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id / ids | Scalar ID, JSON or native ID list | Yes | Explicit positive ID/digit string, native list, or JSON-encoded list. id takes precedence. Empty [] returns []; missing, malformed, nested and nonpositive IDs fail. |
fields | Native mapped-name list | No | Native mapped-name list plus grnIDs and supported supplier widgetCard descriptors. Omitted fields becomes []; a present non-array or malformed descriptor is rejected. |
Mapped field filters | Scalar or native list | No | Mapped fields with stored IDs are exact filters: quoted scalar values compare lowercased equality; lists use IN; numeric values integer-convert. Picker objects such as target:{id,type} expand to the underlying fields. |
order | Mapped name, or native list | No | A mapped field name or list of names/{id,dir} objects. Exact desc chooses descending; other directions use ascending. No default order or ID tiebreaker. |
advanceSearch | Native list | No | Native list of allowlisted column/mapped id,condition,value,andOr expressions. Supported conditions are equal,contains,notEqual,greaterThan,greaterThanOrEqual,lesserThan,lesserThanOrEqual with AND/OR. Raw where SQL and nested values are rejected. |
fields[].widgetCard | Nested native descriptor list | No | For related supplier cards, use {widgetCard:[{table:"supplier",fields:["id","name"]}]}. Only the configured one-to-one supplier relation is traversed, and the first descriptor group is processed. This is CRM layout input, not arbitrary SQL/table access. |
Example request
$result = FM_api('PurchaseOrder_getLayoutDetails', [
'id'=>'1042',
'fields'=>['poNum','grnIDs'],
]);
Example response
[
{
"poNum": "318",
"widgetCard": [],
"grnIDs": []
}
]
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": "permission denied"} | The required page/action or legacy visibility setting denies access. |
{"error": "purchase order does not exist"} | The primary order is missing or outside the caller’s permitted scope. |
{"error": "missing or invalid parameter: id/ids"} | Neither selection key is supplied. |
{"error": "invalid advanced search"} | The expression is malformed or contains raw SQL. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Requires an explicit id or ids selection. Flat native/JSON ID lists are supported; explicit [] returns []; omitted/null IDs and malformed/nonpositive/nested values fail. No accidental whole-tenant fallback.
- Returns an array of visible non-deleted orders. IDs/ordinary fields retain database types; orderNet/orderTax are numeric line-only amounts derived by subtracting carriage from persisted totals. Raw total_net/total_tax remain delivery-inclusive.
- Mapped picker fields retain {id,type} or {id} shapes and their backing IDs. Pure map calculations are client layout fields rather than independently stored response columns.
- Native fields, order, mapped filters and advanced-search entries are validated before SQL. Raw where SQL is rejected. No pagination/counts or default sort is added; callers control bounded batches.
- Omitted fields means an empty requested projection, not every map key. Every returned row receives widgetCard; supplier cards require Suppliers View. The current supplier relationship is the supported card relation.
- Requested grnIDs returns a flat receipt-ID list only with Goods Received View. Injected supplier fields and a grnIDs helper id are cleaned up unless originally requested.
Side effects
- Reads data without changing Purchase Orders, stock, edit markers, history or notifications.
See it in Fieldmotion
CRM1
No direct CRM1 caller was found; CRM1 renders its own header from PurchaseOrder_get.
CRM2
Open CRM2 Purchase Orders → an order. The page bootstrap and display/layout framework call PurchaseOrder_getLayoutDetails with native fields; watch this route while changing the configured layout.
Related endpoints
PurchaseOrder_getRequestedDetails— Read mapped fields with explicit IDs.PurchaseOrder_getGRNs— List linked receipt IDs.