Take payments and refunds
AI agents: read /llms.txt; add .md to any page URL. This page as Markdown: /guides/payments.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: Invoices and payments, for how money works on an order, deposits and payment terms, the ways a customer pays, and store credit.
This guide records payments you already received, works out what’s still owed, and refunds, splits or moves that money. It doesn’t charge cards. Customers pay by card in the Customer Portal, and your team charges cards in the web app. The API can refund a card payment through the gateway, but its card charge operations are built for YoPrint’s own payment screens: see Cards and the API. Invoicing an order is a separate guide: see Invoice an order.
- 1. Record a paymentCash, a check or a bank transfer you already received
- 2. Check the balanceDeposit due, balance due, and what’s been paid
- 3. List, change or deleteRead back the order’s payments, fix a reference, or remove one
- 4. RefundGive money back, recorded by hand or through the card gateway
- 5. Store creditPay an order from credit, or move payments onto it
- 6. Split with a payment linkRecord how one payment is allocated across invoices
1. Record a payment
Section titled “1. Record a payment”Get the payment method you were paid with, such as Cash or Bank Transfer. payment_method_id is optional, but without it the payment has no method. Each entry has its name and id:
/v1/api/store/{team_slug}/setting/payment_method
{ "data": [{ "id": "XbLngLA87AC5t5", "name": "Bank Transfer", "default": false, "trashed": false }] }Then record the payment:
POST Record a payment on a sales order/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment
curl https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/payment \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "amount": 75000, "date": "2026-11-03", "payment_method_id": "Kst6z3ULXLBrmN", "reference_id": "CHK-1001" }'amountis a whole number of thousandths, not a decimal pair:75000is 75.00. A number with decimals, such as75000.5, is refused with422validation_failed, and nothing is recorded.error.fields.amountsays “The amount must be a whole number of thousandths of the currency unit, such as 12500 for 12.50.” Its sign is ignored:-75000also records 75.00. See Money and quantities.date(orcreated_at) is required.reference_idis your reference, such as a check number.reference_descriptionis a note on the payment.- The order must be published: a draft order refuses with 422 (“Payment Action Not Allowed - due to order internal state”).
- No money moves, no receipt is emailed, and the payment is allocated to the order’s invoices automatically.
- Fires
payment_received.any_amountevery time. It also firespayment_received.deposit_amountwhen the order’s paid total now exactly equals the deposit, andpayment_received.full_amountwhen nothing is left to pay. A payment that goes past the deposit, or overpays, fires neither of those two.
2. Check the deposit and the balance
Section titled “2. Check the deposit and the balance”/v2/api/store/{team_slug}/v2/sales_order/{order_unique_key}
curl https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1"order_balance_dueis what’s left to pay: invoiced total minus paid. A decimal pair.deposit_amount_dueis what’s left of the deposit: 0 or less means the deposit is paid. A decimal pair.paid_amountis what’s been paid so far. Thousandths, not a decimal pair.- See How the balance works and Deposits and payment terms for how each is worked out, and Money and quantities for reading
dp.
Example. An order’s lines are worth 600.00, and its terms ask for a 50% deposit, so the deposit is 300.00. Only the tees, 300.00 with no tax, are invoiced so far. After a 300.00 payment, paid_amount is 300000, deposit_amount_due is 0 (the deposit is paid), and order_balance_due is 0 too: the other 300.00 isn’t owed until it’s invoiced.
3. List, change and delete payments
Section titled “3. List, change and delete payments”/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment
Returns every money record on the order at once, newest first, no pagination: payments, refunds and customer credit moves.
GET Get one payment of a sales order/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment/{payment_reference}
PUT Update a recorded payment /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment/{payment_reference}
{ "date": "2026-11-04", "reference_id": "CHK-1002" }/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment/{payment_reference}
- Update changes a payment’s date, references and, on a recorded payment, its method. Delete removes a payment or refund record, and the answer has no data.
- Card payments can’t be deleted here: refund them, or move their money to customer credit (see below).
What you can change, and what’s blocked
| Field | On update |
|---|---|
date or created_at |
Required (one of them). |
payment_method_id |
Only on a recorded payment (ORDER_PAYMENT). Send null to clear it. Ignored on other records. |
reference_id, reference_description (a note) |
Yes. Send null to clear either. |
amount |
No. Send the record’s own amount, or leave it out. A different amount is refused (payment_amount_not_editable): delete the payment and record it again instead. |
A Customer Portal payment, credit linked to one, or a record synced from an integration such as Shopify can’t be changed or deleted here.
4. Refunds
Section titled “4. Refunds”A recorded refund
Section titled “A recorded refund”/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment/{id}/refund
curl -X PUT https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/payment/hAwWd7vPrqjuHD/refund \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "amount": 25000, "date": "2026-11-05", "reference_description": "Returned two shirts" }'- Records that you gave back money outside YoPrint. No money moves, and the refund can’t be more than the payment’s amount minus its own refunds and the credit already spent from it.
amountis thousandths:25000is 25.00. A number with decimals is refused with422. Its sign is ignored, and the answer shows the refund as a negative amount (-25000).{id}in the path is the payment’sid. For a card payment, use the card refund below instead: this one only records a refund and returns no money.- The money comes first from the payment’s own unallocated amount, then from unspent customer credit issued from it (recorded as
ORDER_CREDIT_RECOVERYon the order), then from its invoices, newest first. - Fires
payment.refund_issued.
A card refund through the gateway
Section titled “A card refund through the gateway”/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment_gateway_refund/{id}
curl -X PUT https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/payment_gateway_refund/JMQ642WFe4sANJ \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "amount": 25000, "locking_token": "refund-1001-a" }'- Refunds real money back to the card, through the gateway that took the payment. Send both
amount, in thousandths (25000is 25.00), and a one-timelocking_tokenof your own. Withoutamountthe call fails with HTTP 500 before the gateway is called. - Fires
payment.refund_issued. If the provider later reports the refund failed, YoPrint gives the money back to the payment (REFUND_REVERSAL) instead of leaving it lost.
5. Store credit
Section titled “5. Store credit”Pay from credit
Section titled “Pay from credit”/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/credit/pay_with_customer_credit
{ "amount": 50000 }Uses the customer’s credit to pay part of a published order. amount is thousandths (50000 is 50.00). It can’t be 0 or more than the credit available, and a number with decimals is refused with 422. Fires the same payment_received.* events, with the same exact-match rule, as recording a payment.
Move payments to credit
Section titled “Move payments to credit”Despite the operations’ names, this isn’t a card refund: it takes money already paid on the order and keeps it as the customer’s store credit, to spend on another order. The order’s paid amount goes down by that much.
POST Move part of an order's payments to customer credit/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/credit/refund_to_customer_credit
PATCH Move all of an order's payments to customer credit /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/credit/refund_all_to_customer_credit
{ "amount": 25000, "reference_description": "Overpayment" }- Both need the order published. The first moves part of what’s paid on this order into the customer’s credit, to use on another order. Its
amountis thousandths (25000is 25.00). The second moves everything at once, deleting the order’s payment links first, and takes no amount. - Only money not yet allocated to an invoice can move with the first call. Payments are allocated when they’re recorded, so delete the payment link first, or use the second call instead.
- Neither sends a webhook. A frozen payment (an open dispute or review) blocks both the same way as a card refund, above.
Add or take out credit on a customer
Section titled “Add or take out credit on a customer”/v1/api/store/{team_slug}/customer/{hash_id}/credit
curl https://secure.yoprint.com/v1/api/store/your-team/customer/Rm4rRTDxipKY3n/credit \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "action": "deposit", "amount": 50000, "payment_method_id": "6nz3Vu9sFR4dxM", "reference_id": "CHQ-1001" }'actionisdepositorwithdraw. A withdrawal can’t be more than the credit available now (credit held by an open dispute isn’t available).amountis thousandths:50000adds 50.00. A number with decimals is refused with422.- It isn’t idempotent: each call adds a new entry. List the credit history before you retry after a timeout.
Read the credit history
Section titled “Read the credit history”/v1/api/store/{team_slug}/customer/{hash_id}/credit
Of the credit operations here, only adding or taking out credit by hand fires a customer_credit webhook (customer_credit.deposited or customer_credit.withdrew). Paying from credit fires the same payment_received.* events as any payment.
6. Split a payment across invoices with a payment link
Section titled “6. Split a payment across invoices with a payment link”A payment link records how much of an already-received payment went to which invoice. The web app calls it a payment allocation. It’s not a page or a URL your customer opens, and it moves no money.
GET Get what a new payment link can allocate/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment_link/get_create_template
Returns the order’s payments that still have money to allocate, each with transaction_id and unallocated_amount, to build the next call from.
/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment_link
curl https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/payment_link \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" \ -H "X-Yoprint-Decimal-Format: exact-v1" \ -H "Content-Type: application/json" \ -d '{ "note": "Split deposit", "unallocated_transactions": [ { "action": "create", "transaction_id": "hAwWd7vPrqjuHD", "invoice_id": "QRbvVd2ZKcvSTB", "total": { "dp": 3, "value": 50000 } } ] }'Needs at least one entry, each naming a payment and an invoice of the same order.
GET Show one payment link with allocations/v2/api/store/{team_slug}/v2/payment_link/{hash_id}
Returns the link’s own total (dp 4, the sum) and each allocation’s total and unallocated_amount (dp 3).
/v2/api/store/{team_slug}/v2/payment_link/{hash_id}
{ "note": "Deposit split across two invoices", "allocated_transactions": [ { "action": "update", "id": "SAo2jTR8BZUnyc", "total": { "dp": 3, "value": 12500 } } ], "unallocated_transactions": [ { "action": "create", "transaction_id": "tUq7cR8dTLKFPm", "invoice_id": "7ELS3Vmu6QfJxT", "total": { "dp": 3, "value": 5000 } } ]}How update applies the three actions
allocated_transactionschanges existing allocations byid(updateordelete).unallocated_transactionscreates new ones. Allocations you leave out stay as they are.- Deletes run first, then updates, then creates, so one call can move money from one invoice to another.
- An
updaterow’stotal.dpmust be exactly 3, or it’s refused with 422. Acreaterow’sdpisn’t checked. Either way,valueis read as thousandths.
/v2/api/store/{team_slug}/v2/payment_link/{hash_id}
Deletes the link and its allocations. The payments stay on the order, unallocated, and the invoices simply show less paid: no money moves.
Cards and the API
Section titled “Cards and the API”| You want to | Through the API |
|---|---|
| Record a card payment you took outside YoPrint, such as on your own terminal | Yes. Record it as in step 1, with a payment method such as Credit Card. No money moves. |
| Refund a card payment that went through the team’s gateway | Yes, with a card refund through the gateway. Real money goes back to the card. |
| Charge a card | Not from your own server. See below. |
| Delete a card payment | No. Refund it, or move its money to customer credit. |
The reference lists three card operations: Prepare a card payment, Charge a card through the payment gateway, and Start a Square Terminal checkout. They’re marked Internal because they’re built for YoPrint’s own payment screens:
- Prepare and Charge need a card token or a confirmed payment from the gateway’s own browser library (Stripe, Square, PayPal or Authorize.net), which only a card form in a web page produces.
- Start a Square Terminal checkout sends the charge to the shop’s Square Terminal, where the customer pays on the device.
Don’t build on them. They still work with any member’s key, and they charge real money, so don’t give a key to anyone you wouldn’t trust with that. See Roles and permissions.
POST Charge a card through the payment gateway/v2/api/store/{team_slug}/v2/sales_order/{hash_id}/payment/{payment_reference}
A card payment a customer makes in the Customer Portal, or that your team takes in the web app, shows up in the order’s payments like any other. Read it with List the payments of a sales order, and refund it through the gateway.
Pitfalls
Section titled “Pitfalls”- Recording a payment has no
operation_key. Unlike a shipment create, there’s nothing to make a retry safe: a retried create after a timeout can record the payment twice. List the order’s payments first. - A payment link entry can be silently skipped or capped. One asking for more than the payment has left, or targeting an invoice with nothing left to pay, is skipped without an error. One asking for more than an invoice still owes, with enough left on the payment, is capped to what the invoice owes. The link can be created even though nothing inside it was saved: read the response.
- “Note” is a different field depending on where you are. A payment’s, refund’s or credit move’s note is
reference_description. A payment link’s note isnote. - Update works on a draft order, but the operations around it don’t. Recording a payment, deleting one, and both kinds of refund need the order published. A card refund checks that only after the payment provider has refunded the card.
- A recorded refund’s
{id}must be a payment. A refund or a credit move in its place fails with HTTP 500, not a clean error. - A recorded refund returns no money. On a card payment, use Refund a card payment through the gateway, which does.
