Purchases
Purchase orders with approvals and receipts, vendor bills and payments.
Overview
The Purchases module covers what you buy: a purchase order (po_...) goes through approval, is sent to the vendor and received (adding stock when Inventory is on). A bill (pinv_...) is the vendor invoice you have to pay, created from an order or manually, with its payments (accounts payable).
Requires the Purchases module. An owner or admin turns it on in Settings > Modules. While it is off, every endpoint on this page returns 403 with type permission_error and code module_disabled.
Every write is recorded with the user who owns the API key as the author. That user is also the one checked as approver when you approve or reject an order.
Purchase Order Lifecycle
| Action | From | To |
|---|---|---|
submit | draft, rejected (with at least one line) | pending_approval, or approved when approvals are off |
approve / reject | pending_approval | approved / rejected |
mark_sent | approved | sent (no email is sent) |
receive | approved, sent, partially_received | partially_received or received |
cancel | Any status before goods are received or bills exist | cancelled |
The Purchase Order Object
Endpoints
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /v1/purchase-orders | read | List orders (status, vendor_id, from, to) |
POST | /v1/purchase-orders | write | Create a draft (submit: true to submit it) |
GET | /v1/purchase-orders/{id} | read | Retrieve an order with lines and receipts |
POST | /v1/purchase-orders/{id} | write | Update (lines replaces all lines) |
DELETE | /v1/purchase-orders/{id} | admin | Delete a draft |
POST | /v1/purchase-orders/{id}/submit | write | Submit for approval |
POST | /v1/purchase-orders/{id}/approve | write | Approve (optional comment) |
POST | /v1/purchase-orders/{id}/reject | write | Reject (comment required) |
POST | /v1/purchase-orders/{id}/mark_sent | write | Mark as sent to the vendor |
POST | /v1/purchase-orders/{id}/cancel | write | Cancel (optional reason) |
POST | /v1/purchase-orders/{id}/receive | write | Receive goods |
GET | /v1/bills | read | List bills (status, vendor_id, purchase_order_id, overdue, from, to) |
POST | /v1/bills | write | Create a draft bill (register: true to register it) |
GET | /v1/bills/{id} | read | Retrieve a bill with lines and payments |
POST | /v1/bills/{id} | write | Update a bill |
DELETE | /v1/bills/{id} | admin | Delete a draft bill |
POST | /v1/bills/{id}/register | write | Register (draft to open) |
POST | /v1/bills/{id}/record_payment | write | Record a payment to the vendor |
POST | /v1/bills/{id}/cancel | write | Cancel a bill without payments |
Create a Purchase Order
Only vendor_id is required. Currency and payment terms default to the vendor profile (otherwise the company currency). Each line needs quantity and unit_cost, plus item_id or item_name (up to 200 lines). Lines are validated before creating; if a later step fails (for example submit), the draft is deleted and you get the error. Emits purchase_order.created, and purchase_order.approved when it is auto-approved.
Approve and Receive
- An approver who is not configured, or whose
max_amountis below the total, gets403 not_allowed receivereturns201with the new receipt inreceipts. A line cannot exceed its pending quantity- With Inventory on, received goods enter
warehouse_id(or the order warehouse) as apurchasemovement. Emitspurchase_order.received
The Bill Object
Bill statuses: draft, open, partial, paid and cancelled. overdue is true for open or partial bills past their due_date.
Bill an Order and Pay It
- Manual bill: send
vendor_idandlinesinstead ofpurchase_order_id. With Inventory on it adds stock when registered (affects_stock, needs awarehouse_id) - A fully billed order returns
409 resource_conflict - Payments need an
openorpartialbill, up toamount_due. Methods:bank_transfer(default),cash,check,credit_card,debit_card,other - With the Cash module on, a
cashpayment is also recorded as a cash out in the register - Cancel a bill only without payments; stock it added is returned
- Events:
bill.registered,bill.payment_recorded,bill.paid,bill.cancelled
Errors
| Status | Code | When |
|---|---|---|
| 400 | resource_missing | A referenced id does not exist (param says which: vendor_id, warehouse_id, tax_id, lines...) |
| 400 | invalid_request | A business rule, e.g. "Only draft or rejected orders can be submitted." |
| 403 | not_allowed | The key owner cannot approve or reject this order |
| 403 | module_disabled | The Purchases module is off |
| 404 | purchase_order_not_found / bill_not_found | Unknown id in this company |
| 409 | resource_conflict | The order is already fully billed |