When to use this endpoint

Use for older CRM screens and integrations that expect one object. For camelCase fields and batch IDs use PurchaseOrder_getRequestedDetails.

Read line items separately; this endpoint does not include purchase_order_entries.

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

ParameterTypeRequiredDescription
idInteger-compatibleYesPositive local Purchase Order ID/digit string; not the displayed po_num. Missing, malformed or inaccessible IDs fail.
fieldsJSON or native string listNoJSON-encoded or native flat string list. Allowed header fields: po_id,po_num,target_type,target_id,status,total_net,total_tax,cdate,created_by,supplier_id,delivery_date,reference,date_approved,date_sent,attention,instructions,tax_inc,delivery_address,delivery_net,delivery_taxcode,delivery_tax. Supplier fields: name,street_address1,street_address2,town,county,country,postcode,email,phone,tax_id,account_number,on_hold. Unknown names fail; [] fails; omitted uses the historical default.

Example request

$result = FM_api('PurchaseOrder_get', [
	'id'=>'1042',
	'fields'=>json_encode(['po_id','po_num','total_net','total_tax','reference']),
]);

Example response

{
  "po_id": "1042",
  "po_num": "318",
  "total_net": 289.37,
  "total_tax": "0",
  "reference": "no reference"
}

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: id"}id absent/null.
{"error": "purchase order does not exist"}No non-deleted row, or the legacy query fails.
{"error": "permission denied"}The required page/action or legacy visibility setting denies access.
{"error": "no fields selected"}Explicit fields is empty.
{"error": "unknown purchase order field"}A requested field is not allowlisted.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • Returns a single non-deleted order object. IDs and ordinary fields retain database scalar types; only total_net is explicitly converted to a number. No pagination or line items are included.
  • Omitted fields retains the historical default projection, excluding on_hold. Explicit [] returns no fields selected; unknown names return unknown purchase order field. An invalid custom projection never falls back to a broad response.
  • The supplier join is built when any supplier-owned field is requested; name is not required. Supplier fields are qualified to avoid ambiguity and become null without Suppliers View or a visible linked supplier. Values are current supplier data, not a historical snapshot.
  • po_id is the raw ID alias and is not automatically added to a custom projection. Use the mapped readers for camelCase field names or batch IDs.

Side effects

  • Reads data without changing Purchase Orders, stock, edit markers, history or notifications.

See it in Fieldmotion

CRM1

Open CRM1 Purchase Order details, Customer Orders, the Job purchase-order link or a Goods Received Note. Filter network requests for PurchaseOrder_get; callers supply a JSON fields list.

CRM2

CRM2 Customer Orders still calls PurchaseOrder_get for linked order information. The main Purchase Order detail page uses PurchaseOrder_getLayoutDetails. The mobile app uses m/www’s separate PurchaseOrder_get contract with ownership/status and app permissions; its wrapped response is not this CRM response.

Related endpoints