Update Purchase Invoice
PUT/api/purchase-invoices/:purchase_invoice
Update an existing purchase invoice. All fields are optional on update (uses sometimes validation).
purchase-orders:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Authentication: Requires Bearer token.
Note: purchase_order_id cannot be changed on update.
When financial_lines are provided, each entry requires: id (an existing financial_lines.id), quantity (numeric), and amount (numeric). A 422 is returned if any are missing. On a purchase order with no product lines (charges only), changing financial_lines recalculates the order's invoice_status: it becomes invoiced once every charge is on a bill.
Returns 422 when the invoice is a committed-spend (provisional) bill — those are managed automatically by their purchase order.
bill_currency_rate (multi-currency payables) — the rate a bill on a foreign-currency purchase order posts at in its own currency (base units per one unit of the bill currency). Stamped automatically from the invoice date while "Send supplier bills in their own currency" is on; send a value to override it, or null to re-stamp. Ignored for bills that post in base currency. The detail response then carries document_currency_accounting ({currency_code, bill_rate, receipt_rate, realized_fx, sync_error}); realized_fx is informational — the provider books realized FX on payment, and each payment on such a bill carries the rate for its payment date. sync_error is null, or {title, message} when the accounting provider will not take the bill in its own currency (e.g. a QuickBooks vendor set up in another currency, or a Xero organisation without that currency) — what to change, in plain words.
Invoice line quantity: each purchase_invoice_lines[].quantity_invoiced must be at least 1 and less than 10,000,000 (the same per-line ceiling as a purchase order line). Larger values return 422 with "Quantity is too large (Index #n)."
Request
Responses
- 200
- 401
- 403
- 404
- 422
- 429
OK
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Not found — no record with the given identifier (or the route does not exist). Verify the ID before retrying.
Validation failed — the body is a field → messages map (Laravel shape) or the platform envelope with a stable machine-readable code. Fix the payload and resubmit.
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.