Purchase orders
Change an order target
/a/PurchaseOrder_setLink
Set the header’s target type and ID without moving or allocating stock.
When to use this endpoint
Use to associate an order with a Contract, Customer, Quote, Job, Department, Location or Warehouse. This legacy header setter is different from the stock-allocation helpers PurchaseOrder_setLinkToJob and PurchaseOrder_setLinkToQuote.
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 | Integer-compatible | Yes | Positive local Purchase Order ID/digit string; not the displayed po_num. Missing, malformed or inaccessible IDs fail. |
target_type | Integer-compatible | Yes | Integer 0 No Link, 1 Contract, 2 Customer, 3 Quote, 4 Job, 5 Department, 6 Location or 7 Warehouse. Unknown types fail. |
target_id | Integer-compatible | Except Warehouse | Zero for No Link/Warehouse (omitted becomes zero); positive accessible object ID for other types. |
Example request
$result = FM_api('PurchaseOrder_setLink', [
'id'=>'1042',
'target_type'=>'7',
'target_id'=>'0',
]);
Example response
{
"ok": 1
}
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: id"} | id converts below 1. |
{"error": "missing or invalid parameter: target_type"} | Type converts below 1. |
{"error": "missing or invalid parameter: target_id"} | Non-Warehouse ID converts below 1. |
{"error": "invalid warehouse target"} | Warehouse ID converts to a nonzero value. |
{"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. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Accepts only defined target types 0–7: No Link, Contract, Customer, Quote, Job, Department, Location, Warehouse. No Link and Warehouse require ID zero; other types require a positive accessible reference.
- The target’s page permission and record scope are checked, and the prospective target must satisfy the caller’s Purchase Order boundary. Unknown/inaccessible references fail. Scoped roles cannot move an order to an unscoped No Link/Warehouse sentinel.
- Only the header association changes. Generic linking does not move/reallocate Job stock or rewrite order containers; use the specialised stock-link workflows when allocation is intended.
Side effects
- Header writes lock the existing order and tenant owner, check persistence and record history in the same transaction. Errors roll back the header and audit; a true no-op returns {ok:1,warning:"no change needed"} without a new event/history entry. Cache invalidation and edit-event follow-ups run after the owning transaction commits; an event exception returns saved=1 and a no-replay warning.
- A changed header emits PurchaseOrder_edit after commit; configured account listeners may perform integration work. No order email/PDF is sent directly by this route.
See it in Fieldmotion
CRM1
In CRM1 Purchase Order details, change the Linked To selector. Filter for PurchaseOrder_setLink.
CRM2
No direct generic PurchaseOrder_setLink caller was found in CRM2. Its mapped save uses PurchaseOrder_updateData and may then invoke specialised Job/Quote linking helpers.
Related endpoints
PurchaseOrder_getTargetDetails— Describe the linked target.PurchaseOrder_findAddresses— Build delivery-address candidates.PurchaseOrder_getLayoutDetails— Load mapped layout enrichment.