Skip to main content

Update Purchase Order

PUT 

/api/purchase-orders/:purchase_order

Update an existing purchase order. All fields are optional (sometimes).

Required scope: purchase-orders:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Authentication: Requires Bearer token.

Note: Updates acquire a Redis lock to serialize concurrent edits to the same PO. The request blocks for up to 10 seconds waiting for the lock; if the lock still cannot be acquired it returns 409 Conflict.

Update-only fields:

  • po_number: alias for purchase_order_number
  • purchase_order_lines[].id: ID of existing line to update (omit line from array to delete it)
  • financial_lines[].id: ID of existing financial line to update

Cost lines: financial_lines replaces the order's entire set of cost lines. Any existing line omitted from the array is deleted, including lines currently attached to one of this order's purchase invoices. Send an empty array to clear them all. Omit the key entirely to leave cost lines untouched.

Cannot reduce line quantity below received or invoiced quantity.

Requires permission: purchase_orders.update

Removing lines: a line omitted from lines is deleted. The update is refused with 422 when that line has already been received, or when an authorized vendor credit reduces the cost of its goods — void or unauthorize that credit first.

Approval policy: When the purchase-order approval policy is enabled, sending approval_status: approved approves and opens the order only if you can approve it in one call (its amount is within your limit, or its tier auto-approves). Otherwise the order stays in draft, an approval request is raised to the policy's approvers, and the response adds top-level approval: {requested: true, request_id}. The data object also adds approval — present only while the purchase-order approval policy is enabled (omitted otherwise, so responses are unchanged without a policy). Fields: policy_enabled, request_id, status (pending, approved, rejected, withdrawn, superseded; null when no request was ever raised), reason, tier_name, waiting_on[] (id, name of users who can act now), reapproval_pending (an open order whose changes await re-approval), awaiting_viewer (you can act on it now), and on single-order responses can_approve_directly (you can approve it in one call — within your limit), blocked_reason (why not), send_blocked_reason (why it cannot be sent to the supplier yet) and deposit_blocked_reason (why no new vendor deposit can be taken against it). Use GET /api/approval-requests/for/purchase_order/{id} for the full approval timeline.

Editing an approved order so that its total rises by more than the policy's re-approval tolerance, its supplier or currency changes, or lines are added raises a re-approval request: the order stays open, but it cannot be re-sent to the supplier or take new vendor deposits until the change is approved.

purchase_order_number may be omitted but cannot be cleared — sending null or an empty string returns 422.

Request​

Responses​

OK

Response Headers
    Content-Type