When to use this endpoint

Use for the legacy Form selector before printing or emailing. Changing the form does not generate a document.

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.
valInteger-compatibleYesNonnegative integer Form ID; zero clears it. A selected form must exist, have type 5 and not be archived.

Example request

$result = FM_api('PurchaseOrder_setForm', [
	'id'=>'1042',
	'val'=>'225',
]);

Example response

{
  "ok": 1
}

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": "id and val parameters are both required"}Either value absent/null.
{"error": "purchase order does not exist"}No matching order.
{"error": "form does not exist"}Nonzero form ID does not exist.
{"error": "wrong form type"}Existing form type is not 5.
{"error": "permission denied"}The required page/action or legacy visibility setting denies access.
{"error": "form is archived"}The selected type-5 form is archived.

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

Behaviour and edge cases

  • Zero clears the report form. A nonzero form must exist, be type 5 and not be archived.
  • Changing report form does not generate/send a document, reset approval or recalculate line totals. Identical values are idempotent no-ops.

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.

See it in Fieldmotion

CRM1

In CRM1 Purchase Orders, click a Form cell, load type-5 Forms, and choose one or the blank option. Filter for PurchaseOrder_setForm.

CRM2

No direct caller was found in CRM2 source. Its Purchase Order screen uses mapped reads and generic field saves rather than this legacy endpoint.

Related endpoints