Purchase orders
Change one mapped header field
/a/PurchaseOrder_updateField
Apply one mapped scalar field to selected orders with checked header validation and approval handling.
When to use this endpoint
Use for a focused mapped-field change. Dedicated setters provide clearer contracts for links, supplier, status, carriage and invoice details. Unlike updateData, this route enters the checked existing-header wrapper.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. Session requests use dispatcher CSRF protection when configured. API keys use their owner’s permissions.
Requires explicit View on Purchase Order or Purchase Orders, plus Edit on either page. Non-administrators with legacy Purchase Orders visibility disabled (crm_access bit 256) are denied.
Explicit order IDs must identify active, visible records in the authenticated tenant. TeamAccess follows linked Contracts, Customers, Jobs, Quotes and Departments; legacy department filtering follows Customer, Quote-customer and ordinary customer-Job links. Scoped users cannot read unlinked or Warehouse orders through this check.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id / ids | Positive scalar, native or JSON ID array | Yes | id takes precedence; all selected headers are validated and updated in one transaction. |
field | Mapped field name | Yes | Recognised mapped stored column/path or picker, such as reference, formID, supplierID or target. Pure layout calculations have no writable column; id and server-owned metadata are protected. |
val | Scalar field value | Yes | Mapped value; scalar or native picker as appropriate. Missing/null fails isset. reference permits 32 Unicode characters, deliveryDate is a real ISO date, and protected metadata/id cannot be changed. |
Example request
$result = FM_api('PurchaseOrder_updateField', [
'id'=>'1042',
'field'=>'reference',
'val'=>'Revised supplier reference',
]);
Example response
{
"ok": 1,
"oldData": [
{
"id": "1042",
"reference": "Original reference"
}
]
}
Scalar helper no-ops can return {"ok":"1","warning":"no change required"} without oldData. Raw oldData types follow the database driver; picker writes return prior header snapshots.
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"} | Page/action rights or the legacy visibility setting deny access. |
{"error": "purchase order does not exist"} | An explicit parent/header ID is absent, deleted or outside the caller’s scope. |
{"error": "missing or invalid field"} | field is not recognised by the map. |
{"error": "read-only purchase order field: dateApproved"} | A checked protected field would change. |
{"error": "Editing an approved Purchase Order is disabled for your account"} | The approved-edit restriction blocks this financial change. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Normalizes scalar/native/JSON IDs and applies checked field validation to all selected active scoped headers in one transaction. The id column and changed creation/edit/creator/approval/sent metadata are protected; createdBy picker aliases cannot bypass that rule.
- Supplier/form/target/status/date/carriage inputs follow the same reference and value rules as dedicated setters. Picker values are expanded through the mapped updater rather than coerced into a scalar ID. Stored path fields remain mapped metadata.
- Supplier, carriage and changed line data clear approval and require approval again. Exact no-op saves retain approval. Non-administrators with crm_access bit 8192 cannot make financial changes to approved orders.
- Recalculates totals for every selected header when changing deliveryNet/deliveryTax/orderNet/orderTax. Stored line totals plus carriage remain authoritative. The underlying single-field write now propagates persistence failures so the wrapper can roll back.
- Returns raw oldData for changed scalar writes; picker writes return prior header snapshots. A shared scalar no-op can return string ok="1" with warning "no change required" and no oldData. No updateData completion-triggered Job copy or configured update notification is performed.
Side effects
- Writes use the tenant-owner lock and a transaction or caller savepoint. A rejected operation rolls back its local writes and checked history. Earlier separate API requests remain committed.
- Edit events, notifications and form follow-ups run after the owning commit. A saved/no-replay warning identifies committed data with a failed follow-up; inspect the saved state rather than repeating creation or sending.
- Writes the mapped field and edit timestamp, shared field history and header/approval history. Does not send email or allocate stock directly.
See it in Fieldmotion
CRM1
No direct CRM1 caller was found; dedicated setters are used for the legacy header editor.
CRM2
The CRM2 layout mapping uses PurchaseOrder_updateData for header saves. No direct PurchaseOrder_updateField caller was found in the searched pages.
Related endpoints
PurchaseOrder_updateData— Compare the full mapped-header save contract.PurchaseOrder_approve— Reapprove after financial changes.