Skip to content
Knowledge ERP Docs

API Reference ↗
Purchasing

Purchase Orders

A purchase order records a request to procure goods from a vendor and tracks the full lifecycle from draft through line-item receiving to vendor invoice creation.

A purchase order (PO) is the formal record of a request to buy goods from a vendor. It holds the vendor, the receiving location, an ordered date, an expected delivery date, and one or more line items — each pairing a Product with a quantity and unit cost. When units arrive, you receive them against those lines and the resulting inventory units land directly in stock. After receiving, a vendor invoice can be generated from the PO in a single step.

POs connect purchasing to inventory. Receiving a line creates real inventory units and writes a Purchase movement on each one, so your stock levels and movement history are always accurate.

Creating a purchase order #

New purchase orders are created from Purchasing → Purchase Orders → New Purchase Order.

  • Vendor — the supplier you are ordering from. Required. Pulling up a vendor also surfaces any vendor SKU links you have recorded, which the line-item form can draw on for default costs.
  • PO Number — auto-generated as PO-0001, PO-0002, … if left blank, or you can type your own.
  • Status — defaults to Draft; see the lifecycle section below.
  • Receiving Location — which Location the stock should land in. Required: every line on a purchase order is a Product that has to physically arrive somewhere, and an order naming no Location is not counted as on order by the Reorder Queue, so you would be told to re-order something already coming. If you have one Location it is filled in for you and the field stays hidden; with several you are asked. It also sets the initial receiving bin on the receive page.
  • Order Date and Expected Delivery — informational dates shown in the list and on the PDF.
  • Notes — free-text field visible on the PO PDF sent to the vendor.
  • Tax Rate — an optional tax rate applied to the subtotal; the resulting tax_amount and total_amount are recomputed automatically whenever the rate or any line item changes.
  • Custom fields — any extra attributes defined for purchase orders appear at the bottom of the form.

Line items #

After saving the PO header, add lines on the Items tab (or in the relation manager on the edit page).

Each line captures:

  • Product — which product you are ordering. Required.
  • Vendor Part # — the vendor's own part number for this line. Auto-filled from the Product's vendor record for this PO's vendor when you pick the Product, but freely editable per line and printed on the PO PDF sent to the vendor.
  • Quantity Ordered — how many units you expect.
  • Unit Cost — what you are paying per unit. Stored and returned as an integer in cents (5000 = $50.00).
  • Notes — optional per-line notes.

The PO's total amount refreshes every time a line is added, edited, or deleted: it sums quantity_ordered × unit_cost across all lines, then adds the tax amount if a tax rate is set.

The purchase order lifecycle #

A PO moves through five statuses:

  • Draft — editable; not yet sent to the vendor.
  • Submitted — sent to the vendor. The Submit to Vendor action on the view page marks the PO submitted and, if the vendor has an email address, queues an email with a PDF attachment, branded as your business — the subject reads "Purchase Order PO-0007 from Tallgrass Outfitters" (your business name) and the sender name is yours, so the vendor recognises who is ordering. Submitting is subject to spend approval: a PO whose approval status is Pending is refused, and no email goes out.
  • Partially Received — at least one line item has stock received against it but not all lines are fully received. Status advances automatically when you receive the first unit.
  • Received — every line's quantity_received has reached quantity_ordered. Status advances automatically when the last receipt closes the last open line.
  • Cancelled — the PO is closed with no further receiving allowed.

You can also Print or Download PDF from the view page at any status — useful for sending the PO manually or keeping a paper record. Print opens the PO with your browser's print dialogue over it; Download PDF saves the file.

Spend approval #

A PO carries an approval status alongside its lifecycle status, so an order can be (say) Approved and Partially Received at the same time. It is one of Not Required, Pending, Approved, or Rejected, and only Not Required or Approved may be sent to the vendor.

Two per-person limits, both in cents, decide what happens on submit:

  • Purchase limit — what that person may commit on their own. Empty means unlimited, so nobody is blocked until you set limits.
  • Purchase approval limit — what that person may approve for others. 0 means no approval authority at all, which is what every existing user starts with; empty means unlimited.

When you press Submit to Vendor, the total is recomputed from the order's lines. Within your purchase limit, the PO submits with approval status Not Required. Above it — or if an automation rule with a Require Approval action matches — the PO becomes Pending and is not sent to the vendor.

An order that was rejected is the exception. However large your own purchase limit, submitting it does not send it: it goes back to Pending for an approver to look at again. Your limit governs orders nobody has turned down — it is not a way round somebody's decision.

Approving and rejecting #

A pending PO can be actioned by any user who holds the approve_purchase_orders permission and whose purchase approval limit covers the total. There is no supervisor chain: approvers are a pool, not a tree.

A role held at one location approves that location's orders. Someone whose Approve Purchase Orders permission comes from a role granted at a particular location can approve — and reject — orders for that location, and not orders for another. Someone who holds the permission account-wide approves anywhere, as before. An order that names no location can only be approved by an account-wide holder — granting the permission at a location does nothing for such an order. Orders you raise on the purchase order screen, through the API, from the Reorder Queue, from the Low Stock report or from a reorder point all name one. An order created by an automation rule does not, because that rule is never asked for a location.

Except whoever raised the order. You cannot approve your own purchase order while somebody else could approve it instead — the same rule vendor bills have always followed. If nobody else can, you can: a one-person business is not a segregation-of-duties problem, and refusing there would leave you unable to buy anything.

  • Approve records who approved it and when; the PO can then be submitted.

  • Reject requires a reason and returns the PO to an editable Draft, so the buyer can put right whatever was wrong with it. The rejection — who, when, and why — stays on the record permanently, so the history of a turned-down order is never erased.

    Sending it again needs an approver, whatever the buyer's own purchase limit. Pressing Submit to Vendor on a rejected order puts it back to Pending rather than sending it, and one of the approvers clears it from there. The rejection and its reason stay visible to whoever picks it up.

If nobody can approve it — not a colleague, and not you — the PO shows a warning naming the amount, and saying what to check: who holds Approve Purchase Orders at the order's location, and their purchase approval limits. The order is never silently approved and never left looking ordinary. What clears it depends on which it is — raise an approver's limit, or grant Approve Purchase Orders at that location. If neither seems to apply, check whether somebody who looks like they hold the permission has had it removed on their own record, which overrides anything their roles grant: it shows as Removed for this person only on their entry under People, and lifting it there is what restores them. On an order naming no location the warning says so instead, because only an account-wide holder can approve that one. You will not see this warning merely because you raised the order yourself: if you are the only person who could clear it, you still can.

An approved PO is locked #

An approval authorises a specific commitment: this much money, to this vendor. So once a PO is Approved, that commitment is frozen. Approving $900 and then raising the order to $9,000 would be an approval nobody actually gave.

Locked — the vendor, the tax rate, and the line items. Lines cannot be added, edited, removed, or moved between orders.

Still editable — notes, the PO number, order and expected-delivery dates, the receiving location, and custom fields. A buyer chasing a late delivery should not need a fresh approval to write down a new date. Receiving stock against the order is unaffected.

This is not a setting, and there is nothing to switch on. Some systems ship the equivalent lock turned off by default, which means out of the box a confirmed order's amount can be raised with nobody re-approving it.

Unlock for Editing re-opens a locked PO: it asks why, discards the approval, and returns the order to a Pending draft that must be approved — and submitted — again. Who unlocked it, when, and why are kept on the order. It is available while the PO is a Draft or Submitted, and not once stock has been received against it.

Unlocking needs the update purchase orders permission — the permission to edit an order, since that is what unlocking is for — held either account-wide or at the order's own location. It deliberately does not need approve_purchase_orders: the person fixing a line is usually the buyer, not an approver. Unlocking cannot spend anything (it removes the approval, and a resubmission is re-checked against the submitter's own purchase limit), but it does discard an approval someone else gave, so it is not open to everyone.

Receiving stock #

Click Receive Items on the PO's view page (visible for Submitted and Partially Received POs) to open the dedicated receive screen. There is one receiving screen and this is it — the Receive button beside an individual line on the Line Items tab opens the same screen with that line already selected, rather than a second form of its own.

Receiving needs the receive purchase orders permission, held either account-wide or at the order's own location — so a warehouse hand whose role covers one location can sign for deliveries there. Opening another location's order is refused, and so is sending the stock to a bin belonging to a location their role does not cover.

The receive screen shows each line with its ordered and remaining quantities. For each line you want to receive:

  1. Select the line — click it in the list, or scan a Product barcode to jump straight to the matching line.
  2. Set the destination — choose the location and bin where the stock should land. The screen pre-fills the location's default receiving bin — or, if that location has none set, wherever the Product was last put away. You can also scan a bin barcode to switch destinations on the fly.
  3. Enter quantity — defaults to the remaining quantity on the line.
  4. Optionally enter a lot number and expiration date if the Product's category tracks them.
  5. Click Receive (or press Enter).

Each receipt creates one inventory unit per unit received and writes a Purchase movement against that unit, carrying that unit's share of the receipt — so the movements for one receipt add up to the quantity received, not to the quantity multiplied by the number of units. The line's quantity_received increments and the PO status updates automatically. A scrollable Recent Receipts log shows the last five receipts so you can catch mistakes quickly.

Creating a vendor invoice from a PO #

Once a PO reaches Received status, the Record Invoice action appears on the view page. Clicking it opens a small form where you confirm the vendor's invoice number, invoice date, due date, and amount due (pre-filled from the PO total). Saving creates a vendor invoice with one line per PO line — quantities and costs are carried over automatically — and takes you straight to the new invoice.

The purchase order list #

Purchasing → Purchase Orders shows each PO with its PO number, vendor, status badge, ordered date, expected delivery date, and total. Filter by status (multi-select), Product (finds any PO whose lines include that Product), or use the Trashed filter to view soft-deleted orders.

What lives on the PO page #

Open a PO to see its header infolist and tabs for everything attached to it:

  • Line Items — the line items; new lines cannot be added once the PO is fully received.
  • Received Inventory — every inventory unit created by receiving against this PO, with its current location and status.
  • Vendor Invoices — vendor invoices linked to this PO.
  • Attachments — any files uploaded against the PO.
  • Changes — a full audit trail of edits.

Doing it from the API #

# Create a purchase order
curl -X POST "https://your-domain.com/api/v1/purchasing/purchase-orders" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "vendor_id": "...",
    "ordered_at": "2026-06-02",
    "expected_at": "2026-06-16",
    "notes": "Please ship via ground freight."
  }'

# Add a line item (unit_cost in cents)
curl -X POST "https://your-domain.com/api/v1/purchase-order-items" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "purchase_order_id": "...",
    "product_id": "...",
    "quantity_ordered": 10,
    "unit_cost": 4500
  }'

# List POs for a specific vendor
curl "https://your-domain.com/api/v1/purchasing/purchase-orders?vendor_id=..." \
  -H "Authorization: Bearer $TOKEN"

Money fields are integers in cents over the API — unit_cost: 4500 means $45.00, and total_amount is returned the same way.