When to use this endpoint

Use the CRM2 post-save follow-up for a Quote-linked order. For a header-only link, use PurchaseOrder_setLink, which does not perform these allocation attempts.

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

ParameterTypeRequiredDescription
idPositive integer or digit stringYesLocal Purchase Order ID; not po_num. Missing, malformed or inaccessible IDs fail.
quoteIDPositive integer or digit stringYesExisting active Quote visible to this user. Requires Quote View and Edit, including its customer scope.

Example request

$result = FM_api('PurchaseOrder_setLinkToQuote', ['id'=>'1042','quoteID'=>'421']);

Example response

{
  "ok": 1
}

Missing data returns {"warning":"missing costs"} or {"warning":"missing stock"}, without ok.

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": "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.

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 the destination Quote’s View/Edit and active customer scope. Reads meta.costs.stock, decoding stored JSON. Missing costs or missing stock retains the warning-only response and does not change the header link.
  • Accepts catalogue stock rows using id or legacy sid; conflicting IDs fail. A zero-ID row with nonempty text is miscellaneous. Quantity must be finite/nonnegative. Allocation identities use catalogue ID or miscellaneous text and the order-container type convention.
  • Preflights and applies exact desired quantities under the owner/order/Quote locks. Existing allocation to that Quote counts toward the desired total, making an exact replay harmless. Missing/short availability or another destination is an error.
  • The complete allocation and header link/history commit together. A later shortage rolls back earlier container moves and leaves the header unchanged. It does not receive inventory or change approval.

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.
  • Moves available Purchase containers to Quote destination type 12, stores target_type=3/target_id and records checked history/edit event. Legacy orders without any containers can initialize availability only when no receipt exists.

See it in Fieldmotion

CRM1

No direct CRM1 caller was found; the generic header-link setter has a smaller scope.

CRM2

In CRM2 Purchase Order details, save an editable order linked to a Quote. After totals refresh, the page calls PurchaseOrder_setLinkToQuote. The mobile app goes through m/www’s separate PurchaseOrder_save/OrdersM workflow; its validation and ownership rules do not establish this office endpoint’s contract.

Related endpoints