Work with purchase orders
AI agents: read /llms.txt; add .md to any page URL. This page as Markdown: /guides/purchase-orders.md. Index of every page and the rules for every call: /llms.txt. Guides and concepts in one file: /llms-full.txt. OpenAPI: /openapi.json.
Read first: Purchasing and stock, for purchase orders, needs ordering, receiving and stock.
A purchase order (PO) buys blanks and supplies from a vendor. Receiving a PO records what arrived, and moves it into stock.
What the public API can do with purchasing today:
| To | Operations |
|---|---|
| Manage vendors and their contacts | Vendors |
| Link purchase orders to the sales orders they supply | Sales order PO links |
| Export purchase orders to CSV | PO export, data export |
| Read a PO’s history | PO history |
| Report on purchasing | PO report |
| React when a PO’s status changes | The purchase_order.status_changed webhook |
| Read one PO, or change its status | Two operations kept for YoPrint’s Zapier app |
1. Manage vendors
Section titled “1. Manage vendors”/v1/api/store/{team_slug}/vendor
POST Create a vendor /v1/api/store/{team_slug}/vendor
PUT Update a vendor /v1/api/store/{team_slug}/vendor/{hash_id}
Vendors have contacts, like customers do:
POST Add a contact to a vendor/v1/api/store/{team_slug}/vendor/{hash_id}/contact
2. Link a purchase order to a sales order
Section titled “2. Link a purchase order to a sales order”Linking shows which POs supply which sales order. Add the PO ids in item.
The public API has no PO list, so take a PO’s id from a purchase_order.status_changed webhook, or from the links already on another sales order.
/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/purchase_order_link/add
curl -X PUT https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/purchase_order_link/add \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "item": [{ "id": "oovEHf2HhdHhwR" }] }'Only sales orders take links, not quotes. To see and remove links:
GET List the purchase orders linked to an order/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/purchase_order_link
PUT Unlink purchase orders from an order /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/purchase_order_link/remove
3. Export purchase orders
Section titled “3. Export purchase orders”For a CSV of the POs issued in a date range:
POST Export purchase orders by issue date/v1/api/store/{team_slug}/purchase_order/export
{ "start_date": "2026-10-01T00:00:00Z", "end_date": "2026-10-31T23:59:59Z" }Add "list_only": true to get the same rows as JSON instead of a CSV file. The rows carry PO numbers, not ids. For the CSV, when no PO matches the answer is 422 with “Purchase Order not found”. With list_only: true it returns an empty data list. In both formats, amounts such as ordered_total and received_total are decimal strings (such as "120.00"). See Money and quantities.
For a whole-team list, use the queued data export. See Export and import data.
POST Export purchase orders in a date range to CSV/v1/api/store/{team_slug}/data_export/export_purchase_order_list
4. Read history and report
Section titled “4. Read history and report”/v1/api/store/{team_slug}/purchase_order/{hash_id}/history
POST Report purchase orders by issue date /v1/api/store/{team_slug}/report/purchase_order
In the purchase order report, amounts (calc_subtotal, calc_tax, calc_total) are decimal strings with 4 decimal places, such as "125.0000". Parse them as decimals. See Money and quantities.
PO statuses, for filters and webhooks:
GET List purchase order statuses/v1/api/store/{team_slug}/setting/status/purchase_order
5. Follow status changes
Section titled “5. Follow status changes”Subscribe to purchase_order.status_changed to hear when a PO’s status is set, for example to Completed when everything has arrived. It fires on every status change call, even when the status stays the same. Narrow it to some statuses with purchase_order_status_changed_options. See Receive events with webhooks.
6. The Zapier app’s purchase order operations
Section titled “6. The Zapier app’s purchase order operations”YoPrint’s Zapier app finds a purchase order by its id and changes its status with these two operations. They exist so that Zaps keep working, and their answer keeps the shape the Zapier app reads:
GET Get a purchase order/v1/api/store/{team_slug}/purchase_order/{hash_id}
PUT Change a purchase order's status /v1/api/store/{team_slug}/purchase_order/{hash_id}/status
- Reading needs permission to view purchase orders, and changing the status needs permission to update them. A role that sees only its own POs reaches only the POs its user created or is assigned to.
- Money in
v1_public_purchase_order_showis in thousandths (10800is 10.80):calc_subtotal,calc_taxandcalc_totalon the purchase order and on each line, and each line’sprice. Usually a whole number of thousandths. An amount finer than a thousandth comes back as a decimal string such as"12656.3". Parse them as decimals. See Money and quantities. - In lines,
quantityis what is still to receive, not what was ordered.received_totalis what has arrived. - The new status is a purchase order status id, from the status list in step 4. When the PO’s warehouse holds stock, moving it to its final status needs every line except fees fully received first.
Each operation’s reference page has its exact request and answer.
Pitfalls
Section titled “Pitfalls”- No create or receive. Don’t look for them in the public reference. They aren’t there.
- Links are for sales orders. A quote can’t be linked to a PO.
- The PO id is its hash id. A PO number such as
PO0042isn’t an id, and the export shows only numbers. See IDs. - An empty CSV export is an error. A date range with no POs answers
422, not an empty file (withlist_only: trueit returns an empty list). - Amounts are decimal strings or thousandths. The PO report and exports return decimal strings (
"125.0000"or"120.00"). The Zapier show operation returns amounts in thousandths (10800is 10.80). See Money and quantities.
