The model
The method types mean:
CASH: collected by staff at the counter or at the door.CARD: card not present (web or app checkout).PIN_PAD: card present, on a terminal next to the kiosk or till.WALLET: QR or app wallets.BANK_TRANSFER: the customer pays from their bank and the channel verifies it.FINANCING: buy now, pay later. It covers part of the order; the rest is paid with another method.REDEMPTION: vouchers, rewards or stored balance. It is not a method the customer picks at checkout. It comes from a redeem that names the merchant’sREDEMPTIONpayment.
REDEMPTION is not a real method. Real methods are everything else. is_mixed is true when an intent has two or more real tenders. A redemption next to one card does not make the intent mixed. primary_tender_id is the first real tender. It is null only when every tender is REDEMPTION.
An order has at most one DRAFT or LOCKED intent. Older intents stay on payment_intents as COMPLETED or ABANDONED.
Where a tender is collected
collect_at is DEVICE, KIOSK, COUNTER, DOOR, or OTHER.
A fulfillment
PAYING node can set payment_scope to digital or in_person. With no scope, the node waits for every live tender. The node advances to PAID when every tender in that scope is settled. An empty scope is paid as soon as the order enters it. A redemption-only scope is paid once those rewards are reserved (PENDING with a reservation counts as settled).
Intent statuses
Tender statuses
These are also the order’spayment_status, derived from the live tenders of the active intent.
Derivation: no tenders is
IDLE. Any FAILED is FAILED. All CANCELLED is CANCELLED. All REFUNDED or CANCELLED is REFUNDED. All settled is PAID. All IDLE is IDLE. Anything else is PENDING.
Every tender has an attempt_reference. Retries use a new one. The same reference never creates a second charge.
Mixed payments and allocation
Send tenders before place. The server computes each tender’samount and allocation.amounts. You send allocation without amounts.
allocation is { lines: [{ line_uid, units? }], fees: [line_uid] } or null.
- One real tender may send
allocation: null. That tender covers whatever no other tender covers. - A
REDEMPTIONtender always sendsallocation: null. It covers an amount, not lines. - With more than one real tender, a real tender that omits allocation is rejected (
PAYMENT_UNALLOCATED_LINES). - Tip and delivery sit only on the primary real tender.
- At most one tender is
CASH.
Redemptions
A redeem is a voucher, reward or balance. Every redeem needspayment_id (an active REDEMPTION payment of the merchant) and amount (the money it covers for the whole entry, not per unit). quantity is informational. A redeem without payment_id is rejected with REDEEM_PAYMENT_REQUIRED.
The redeem shows as a discount on its line (lines[].redeem) or on the order (redeem), but line and order money never change: group_total, the taxes and totals.total stay full. The REDEMPTION tender pays the redeemed amount, and the customer’s method pays the rest.
before_taxes (default true) caps a redeem at the pre-tax value of its line or order, so the taxes stay for the customer’s method. With before_taxes: false the redeem may also cover the taxes. Every redeem is also capped at the order total minus tip and delivery.
Redeems that share a
payment_id become one REDEMPTION tender. details.rewards lists each reward. Each reward has its capped amount, and details.amount is their sum. The tender amount is that sum. A tender that does not match the grouped redeems is PAYMENT_REDEMPTION_MISMATCH.
Each redeem also has a step in redemption_steps, in application order: root-line redeems in line order, then order redeems. A step carries payment_id, before_taxes, target (LINE with target_id, or ORDER) and discount_amount, the capped amount. before and after hold value (what the customer’s method still pays), discount_amount (covered so far) and discount_rate (covered / total); LINE steps also have target_before and target_after. So the steps of a payment_id add up to its REDEMPTION tender, and the line steps add up to the discount shown on the line. The server recomputes and stores the steps. Validate and place reject client steps that list other redeems or another order (REDEMPTION_STEPS_MISMATCH) or other money (REDEMPTION_MISMATCH). redemptionSteps(order) in the SDK gives the same steps.
amount is { currency, total }: what that tender pays. A REDEMPTION tender adds only what void and refund need: payment_id and details (rewards[] with reward_id, quantity and amount, plus details.amount).
services.payments.list hides REDEMPTION payments. Pass { includeRedemptions: true } when a redeem flow needs them. That flag is not a query parameter: the API still returns those payments, and the SDK filters them.
Reopen
Reopen order voids unpaid tenders (reserved redemptions are released), cancels the source asVOIDED, and returns a new OPEN order. The link is metadata.reopen: { as_order_id } on the source and { from_order_id } on the new order. The new order can carry both once it is reopened again. A live real tender that is already PAID or REFUNDED returns 400 ORDER_PAYMENT_CAPTURED. An order already VOIDED / REVERSED / legacy CANCELLED and never fulfilled is reopened as-is once every real tender is CANCELLED, FAILED, or fully REFUNDED (for example after a failed injection reversed on the device); a PAID tender there is still 400 and an IDLE / PENDING one is 422. Optional order_id can be any id genId builds (isGenId: [A-Za-z0-9-], a run of at least 8 [0-9a-z], up to 64 characters; genOrderId is one option). Example: BB2192100000001. A bad format is 400 ORDER_ID_INVALID and a taken id is 409 ORDER_ID_EXISTS. Omit order_id and behavior stays the same. REDEMPTION does not block reopen. On a kiosk, the Cancel button during the checkout-release wait calls this endpoint.
Related
Supported payment methods
What is available today and what is coming
Use payments in the SDK
Install a package and charge an order
Orders
What a payment intent belongs to
Payment errors
Provider codes, retries, and what to show the customer