Purchasing, transfers, and the books
ZORT runs the buying side of a business as well as the selling side: purchase orders to suppliers, goods received by lot, returns to suppliers, transfers between warehouses, and money that never touches an order. This guide covers the calls the tool schemas cannot make for you.
A purchase order's life
| status | meaning | stock |
|---|---|---|
| Pending | ordered | unchanged |
| Waiting, Shipping | progress markers you set | unchanged |
| Partial Transfer | some lines received | up by what arrived |
| Success | everything received | up by the rest |
| Voided | cancelled |
Receiving is the step that moves stock, and it names the warehouse the goods land in:
zort_receive_purchase_order(
purchase_order_number: "PO-0001",
warehousecode: "WH1",
actiondate: "2026-10-03",
items: [{ sku: "P-RESIN-25KG", number: 40 }]
)
When the whole order has arrived, pass receive_all: true instead of items. It is never the default. A call that forgets its items fails rather than receiving the entire order.
Creating a PO with status: "success" receives it at the moment of creation. That suits recording a purchase after the fact, but not ordering ahead.
Receive against the PO, not with an adjustment
zort_adjust_stock(mode: "increase") gets the shelf count right and leaves the PO wrong. The PO still shows the goods outstanding, so the next person receives them again and stock is counted twice. If there is a PO, receive against it.
Lots and expiry
After receiving, record which lot the goods belong to:
zort_set_purchase_order_lot(
purchase_order_number: "PO-0001",
sku: "P-RESIN-25KG",
lot: "L2026-10-A",
quantity: 40,
expiredate: "2027-04-30"
)
Make one call per lot. A delivery of 40 split across two lots is two calls.
ZORT's own reference calls the quantity field lotnumber, which reads like an identifier. It is a number, and it comes back as the lot's quantity, so the tool names it quantity. The lot's name or code goes in lot. Recorded lots show up on each line in zort_get_purchase_order.
Paying suppliers
GetPurchaseOrders has no payment-status filter. To find POs with nothing paid, pass topaymentamount: 0. Partly paid POs show Partial Payment in their paymentStatus.
Each payment carries an id. A payment recorded twice is removed with zort_void_purchase_order_payment, not by voiding the PO.
Returning goods to a supplier
A purchase return is a record of its own. Link it to the PO it came from with referencenumber. Nothing enforces the link, and without it the return cannot be traced back. A pending return moves nothing. success takes the goods out of the warehouse.
The reference documents the status parameter as statu. The tool sends both spellings, because a server that read only the documented name would fall back to its default, Success, and ship the goods out of stock.
Moving stock between warehouses
Use a transfer, not a decrease in one warehouse and an increase in the other. A transfer is one document with both ends and a date. Two adjustments are unrelated edits that nobody can reconcile later.
A pending transfer moves nothing until zort_complete_transfer, which takes items for a partial arrival or complete_all: true.
zort_list_transfers also shows ZORT's other stock movements: Initial, Adjust, Assembly, Disassembly, and Reserve. Filter with transfertype. The API can list these but not create them, since AddTransfer takes no type.
What actually moved
List tools show the paperwork. zort_list_stock_movements shows what physically moved and when, by source: purchase_order, purchase_return, transfer, or order. "What came in this week" is a movement query, not a PO query:
zort_list_stock_movements(source: "purchase_order", dateafter: "2026-10-01", datebefore: "2026-10-07", warehousecode: "WH1")
Quotations
Approving a quotation marks it Success and nothing more. It does not create a sales order. Create the order with zort_create_order from the quotation's lines. Voided quotations come back in responses but cannot be filtered for.
Money outside orders
| kind | for |
|---|---|
income | money in that is not a sales order: scrap sales, service fees |
expense | money out that is not a purchase order: rent, utilities, repairs |
money_transfer | money moving between your own accounts, such as cash to bank |
A supplier's invoice for goods on a PO is paid on the PO. Booking it again as an expense counts the cost twice. A money transfer is neither income nor expense, so do not record a bank deposit of the till as either.
Income and expense entries carry paymentStatus and their payments, the same as orders. Record later payments with zort_record_finance_payment.
Documents
Receipts, tax invoices, and invoices come back from zort_list_documents with a url to the document itself. Pass order_id for one order's documents.
zort_add_order_document takes no document type, so ZORT decides which it issues. Read the list it returns. It reuses an existing document by default. Passing use_existing: false issues another, and a second tax invoice for the same sale is an accounting problem, not a duplicate you can quietly delete.
Retries
Every create except a purchase return takes uniquenumber, and ZORT rejects a repeat of the same value. Set it on anything that might be retried, derived from something stable such as the supplier's reference. AddReturnPurchaseOrder has no such key, so check zort_list_purchase_returns before retrying a failed create.