Skip to content

Invoice an order

Open .md

Read first: Invoices and payments, for what an invoice bills, Auto Invoice, and how an order’s balance is worked out.

An invoice bills some of a sales order’s lines, with shipping fees, a discount or two, and a tax line of its own. This guide creates one, adds and edits its lines, reads it back across orders, and deletes or downloads it. It doesn’t record payments: see Record a payment.

  1. 1. Check for Auto InvoiceA managed order keeps its own invoice and won’t take one you create
  2. 2. Create an invoiceStarts from the order’s addresses and issue date
  3. 3. Add its linesBilled order lines, shipping fees, discounts and tax
  4. 4. Read and change itEdit lines, header and tax, except the lines Auto Invoice manages
  5. 5. Find it across ordersFilter your team’s invoices, or list one order’s
  6. 6. Read the totalsWhat’s billed, discounted, taxed and owed
  7. 7. Delete or download itDeleting frees its payments. Exporting makes a PDF
Check auto_invoice_managed before step 2: an Auto Invoice order refuses invoices you create yourself.
GET Get a sales order or quote /v2/api/store/{team_slug}/v2/sales_order/{order_unique_key}

Read the order’s auto_invoice_managed field before you invoice it by hand.

  • true: YoPrint maintains a single invoice itself, adding and updating lines as you change the order’s lines and shipping fees.
  • Creating an invoice yourself on that order is refused with 422 “You cannot create an invoice for an auto managed order.”
  • On the managed invoice, you can’t add, edit or delete its order lines, or edit or delete the shipping fees and discounts YoPrint added. You can still add your own discounts and shipping fees.

To invoice by hand, turn Auto Invoice off first with the configure_order_auto_invoice_managed action:

PUT Run an action on a sales order or quote /v2/api/store/{team_slug}/v2/sales_order/{order_unique_key}/action/{action_name}
Terminal window
curl -X PUT https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/action/configure_order_auto_invoice_managed \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "X-Yoprint-Decimal-Format: exact-v1" \
-H "Content-Type: application/json" \
-d '{ "auto_invoice_managed": false, "auto_invoice_shipment_price_type": "DONOTMANAGE", "auto_invoice_shipment_rate": { "value": 0, "dp": 0 } }'

All three fields are required. Turning it off leaves the invoices and their lines as they are. They stop being managed.

POST Create an invoice for a sales order /v2/api/store/{team_slug}/v2/sales_order/{unique_key}/invoice
Terminal window
curl https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/invoice \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "X-Yoprint-Decimal-Format: exact-v1" \
-H "Content-Type: application/json" \
-d '{ "issue_date": "2026-11-03T00:00:00Z" }'
  • Send {} for an empty invoice. Every field is optional: without billing_address_id, shipping_address_id or issue_date, the invoice takes the order’s own.
  • It gets the team’s next invoice number. The answer’s data.id is the invoice id. Keep it for every later step.
  • Add lines in the same call with item_actions, in the same shape as the bulk operation in the next step, or add them afterward.
  • Refused for a Shopify-synced order (“Cannot create invoice for a Shopify-synced order.”) and for an order with Auto Invoice turned on (step 1).
POST Add a line to an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key}/item

Four kinds of line, by product.type:

product.type What it bills
order_item One of the order’s lines, by the order line’s id
shipment_fee A shipping charge, with its own price
invoice_discount A discount, as a percent or a fixed amount
user_tax, override_tax or auto_tax The invoice’s one tax line (see step 4)

An order line’s id is data.item.id in the answer that added it, or id in the order’s items when you read the order. The answer here wraps the new invoice line the same way: its id is data.item.id.

A billed order line:

{
"product": { "type": "order_item", "properties": { "id": "ZJTJ2uF5dMiArL" } },
"quantity": { "type": "unit", "total": { "value": 24, "dp": 0 } },
"tax": { "type": "taxable" },
"position": 100
}

A shipping fee:

{
"product": { "type": "shipment_fee", "properties": { "name": "Shipping", "shipping_taxable": false } },
"pricing": { "type": "fee", "product": { "total": { "value": 1500, "dp": 2 } } },
"position": 900
}

A discount:

{
"product": { "type": "invoice_discount", "properties": { "type": "percent", "rate": { "value": 10, "dp": 0 }, "applies_to_shipping": false, "name": "Loyalty discount" } },
"position": 950
}

The tax line, from a tax preset:

{
"product": { "type": "user_tax", "properties": { "id": "KC48n7qAAfGYMM" } },
"position": 1000
}
  • One invoice can’t bill the same order line twice: a second time is 422 “Invoice already has the same Order Item”.
  • You can bill fewer than was ordered (the order line shows “partly” invoiced) or more (it shows “over-invoiced”). The quantity can’t be negative.
  • An invoice holds at most one tax line. To switch kinds, use Change the tax instead of creating a second line.

To add, change and remove several lines in one save:

POST Add, change and remove invoice lines at once /v2/api/store/{team_slug}/v2/invoice/{unique_key}/item/bulk
[
{ "bid": "row-1", "action": "create", "payload": { "product": { "type": "order_item", "properties": { "id": "ZJTJ2uF5dMiArL" } }, "quantity": { "type": "unit", "total": { "value": 24, "dp": 0 } }, "position": 100 } },
{ "bid": "row-2", "action": "update", "cart_item_id": "wigm2YNiE4PciF", "payload": { "quantity": { "type": "unit", "total": { "value": 6, "dp": 0 } } } },
{ "bid": "row-3", "action": "delete", "cart_item_id": "DW7m2sWa8vVVDL" }
]
  • Runs every delete, then every create, then every update, then recalculates once: all saved, or none.
  • Tax lines can’t be added or changed here: 422 “Tax Item is not allow in bulk operations.”
GET Get an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key} GET List the lines of an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key}/item
  • Get an invoice returns its header, lines under items, and its order. Send X-Yoprint-Decimal-Format: exact-v1 so large totals come back exact. See Money and quantities.
  • List the lines returns them unsorted: sort by position yourself.

To change the header, its lines and its tax together:

PUT Update an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key}
{
"issue_date": "2026-11-03T00:00:00Z",
"item_actions": [
{ "bid": "row-1", "action": "create", "payload": { "product": { "type": "order_item", "properties": { "id": "ZJTJ2uF5dMiArL" } }, "quantity": { "type": "unit", "total": { "value": 24, "dp": 0 } }, "position": 100 } }
],
"tax_selection": { "expected_tax": null, "desired_tax": { "type": "user_tax", "properties": { "id": "KC48n7qAAfGYMM" } } },
"resort_items": false
}
  • Everything saves together or not at all. item_actions can delete the tax line, except on an Auto Invoice invoice, but can’t create or change it: use tax_selection for that.
  • There’s no locked or permanently paid state: you can edit a paid invoice, and YoPrint redistributes (reallocates) the order’s recorded payments across its invoices to match.

Or change one line at a time:

PUT Update an invoice line /v2/api/store/{team_slug}/v2/invoice/item/{unique_key}
{ "quantity": { "type": "unit", "total": { "value": 12, "dp": 0 } }, "lock_version": 1730000000000000 }
  • Send only what you change. A line’s kind can’t change.
  • lock_version is the value from when you read the line. Someone else’s save since then is 422 optimistic_lock_conflict.
DELETE Remove a line from an invoice /v2/api/store/{team_slug}/v2/invoice/item/{unique_key}
  • On an Auto Invoice invoice you can’t remove its order lines, shipping fees or discounts: “You cannot delete order Item for an auto managed invoice.”
PUT Change the tax on an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key}/tax-selection
{
"expected_tax": { "id": "WzHB84GM5mzqAw", "lock_version": 1730000000000001 },
"desired_tax": { "type": "override_tax", "properties": { "mode": "tax_exempt", "total": { "value": 0, "dp": 0 } } }
}
  • expected_tax is the tax line you think is there now (its id and lock_version, or null when there’s none). A mismatch changes nothing: 422 invoice_tax_conflict.
  • desired_tax is what you want, or null to remove the tax line. A different type from the current one replaces the line. The same type updates it.
  • Setting a tax line makes it yours: YoPrint stops managing it, even on an Auto Invoice invoice.
POST Filter invoices /v2/api/store/{team_slug}/v2/invoice/filter
{
"filters": [
{ "key": "payment_status", "operator": "eq", "value": "unpaid" },
{ "key": "quote", "operator": "eq", "value": false }
],
"sort": [{ "key": "full_amount_due", "direction": "asc" }]
}
  • Filters: payment_status (paid, unpaid or overdue), quote, order_status_id, order_customer_id, external_type, and dates.
  • The date filters read the invoice’s order: order_issue_date, order_cust_due_date, order_ship_due_date, deposit_due and full_amount_due. Each takes a whole number of days from today, and compares whole UTC days, day N included: { "key": "full_amount_due", "operator": "lte", "value": 7 } finds invoices whose order’s full amount is due by the end of the 7th UTC day from today, overdue ones included. The invoice’s own created_at leaves day N out, like the other v2 filters. See Filtering and sorting.
  • Needs Manage Sales Orders view access. Other roles get 403.

To list one order’s invoices instead:

GET List the invoices of a sales order /v2/api/store/{team_slug}/v2/sales_order/{unique_key}/invoice
  • The path’s {unique_key} takes the order’s id only. Send the order’s own unique_key string instead and the list comes back empty, not an error.
  • An id that isn’t one of your orders also returns an empty list.
On the invoice What it is
cart_item_subtotal Billed lines and shipping fees, before discounts and tax. shipment_subtotal is the shipping part of it, already included.
discount_subtotal Discounts on the invoice.
tax_subtotal Tax on the invoice.
total cart_item_subtotal − discount_subtotal + tax_subtotal (plus a card surcharge, when there is one).

They’re decimal pairs at dp 4: read dp every time. See Money and quantities.

On the order, once invoices exist:

On the order What it is
invoiced_total What’s been billed, across every invoice.
order_balance_due invoiced_total minus what’s been paid.

See How the balance works for how YoPrint gets from the order’s lines to what the customer owes.

DELETE Delete an invoice /v2/api/store/{team_slug}/v2/invoice/{unique_key}
  • Deletes the invoice and its lines. Its payments stay on the order: the amounts allocated to this invoice are redistributed across the order’s other invoices, or returned to unallocated balance.
  • Refused for an Auto Invoice invoice (“You cannot delete an auto managed invoice.”) and for one synced from Shopify.
  • Deleting an invoice that’s already deleted succeeds and changes nothing.

Download one or more invoices as a PDF:

POST Download invoices as one PDF /v1/api/store/{team_slug}/invoice/export_pdf
Terminal window
curl https://secure.yoprint.com/v1/api/store/your-team/invoice/export_pdf \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-H "X-Yoprint-Decimal-Format: exact-v1" \
-H "Content-Type: application/json" \
-d '{ "invoice": [{ "id": "cBRpSf5nw6upt5" }, { "id": "gtnwEWU4Npp9eC" }] }'
  • 1 to 100 invoices per call, combined into one PDF made while you wait. Nothing is stored.
  • An id that isn’t your team’s is skipped without an error: check your ids first, or you can get back an empty PDF rather than a failure.
  • Each invoice also carries its own link in pdf_url (from Get an invoice or the order’s invoice list), with its own long-lived access token: don’t publish it.
  • Invoice creates aren’t idempotent. There’s no operation_key. If a create times out, list the order’s invoices (step 5) before retrying. See Retries and duplicates.
  • There are no invoice webhooks or events. Read the order or invoice again, or poll on a schedule, to follow a change.
  • The bulk line operation skips the lock_version check. Unlike the single update, a bulk update can silently overwrite someone else’s edit.
  • is_valid: false means the invoice needs fixing, even though the save succeeded: no lines, lines with no tax line, or a customer that doesn’t match the order’s.
  • Changing only the addresses on a manual invoice doesn’t recalculate its tax. Send tax_selection in the same Update an invoice call to redo tax for the new address.
  • A discount’s amount comes back as total, though you send it as rate.