Vouchers

The customer gets a cash reference at checkout — a barcode, a slip, or a number pair — and pays it in physical cash at a store, bank, or ATM. The payment succeeds when the scheme registers the cash, hours or days later. Essential in markets where a large share of customers have no card at all.

The voucher methods

Methodpayment_methodRegionCurrencyThe reference
OXXOoxxoMexicoMXNBarcode, paid at any OXXO convenience store
BoletoboletoBrazilBRLNumbered slip (linha digitável), paid at banks, ATMs, lottery agents, or bank apps
KonbinikonbiniJapanJPYPayment code / barcode, paid at convenience-store kiosks
MultibancomultibancoPortugalEUREntity + reference pair, paid at ATMs or via home banking

The cash flow

POST /v1/payments voucher issued barcode · slip · reference customer pays cash store · bank · ATM succeeded hours–days status: requires_action while unpaid failed voucher expires unpaid — payment.failed Webhook on cash registration: payment.succeeded. The expiry deadline is printed on the voucher and shown on the hosted page.

The flow is maximally asynchronous: after checkout, nothing happens until a human walks to a counter. The payment sits in requires_action the whole time — that's normal and can last days. Two consequences:

  • Never fulfill from the return redirect. The customer coming back to your return_url means they saw the voucher, not that they paid it. Fulfillment gates on payment.succeeded, full stop.
  • Hold inventory deliberately. Decide how long you'll reserve stock for an unpaid voucher — the voucher's expiry (shown on the hosted page and printed on the reference) is the natural bound.

Creating a voucher payment

POST /v1/payments — OXXO
curl https://api.finscale.dev/v1/payments \
  -H "Authorization: Bearer sk_test_51FinscaleDemo…" \
  -H "Idempotency-Key: idem_ord_9f21_0716" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 89900,
    "currency": "MXN",
    "payment_method": "oxxo",
    "reference": "ord_9f21_0716",
    "customer": { "email": "anna@example.com" },
    "return_url": "https://shop.example.com/checkout/return"
  }'
201 Created — voucher issued behind next_action.url
{
  "id": "pay_8Q2mX4nT1cVb",
  "object": "payment",
  "amount": 89900,
  "currency": "MXN",
  "status": "requires_action",
  "payment_method": "oxxo",
  "reference": "ord_9f21_0716",
  "next_action": {
    "type": "redirect",
    "url": "https://pay.finscale.dev/r/8Q2mX4nT"
  },
  "created_at": "2026-07-16T09:24:31Z",
  "livemode": false
}

The hosted page behind next_action.url renders the reference itself — barcode for OXXO and Konbini, the slip for Boleto, the entity + reference pair for Multibanco — with the amount, your reference, and the expiry deadline. Customers can save or print it; the page keeps working after checkout ends.

Living with the delay

  • Conversion tails are long. Most vouchers that get paid are paid within a day; the rest trickle in until expiry. Don't alarm on requires_action ages that would be pathological for any other family.
  • Exact amounts only. The reference is bound to the amount — cashiers and ATMs collect exactly it. There are no partial or over-payments to handle.
  • Idempotent order state. A customer who lost the voucher will often re-checkout, producing a second payment for the same order. Cancel the abandoned one with POST /v1/payments/{id}/cancel when the replacement succeeds, and key fulfillment on your reference.

Refunds — no chargebacks

Cash rails have no reverse gear, so refunds travel as bank credit transfers instead: after POST /v1/refunds, Finscale collects the customer's account details through a secure hosted claim page (linked from the refund notification) and pushes the transfer once they're in. The refund stays pending until then — expect the extra step to add a day or two versus card refunds. Details in Refunds.

No chargeback rail Cash is cash: once registered, a voucher payment cannot be disputed or pulled back. Voucher volume never appears in your dispute queue.

Settlement timing

The scheme registers the cash and confirms to Finscale — that's your succeeded. Funds then join the unified payout on the standard T+2 schedule in the voucher's currency. The settlement report line carries the payment id as usual, so reconciliation doesn't care that the customer paid in physical cash.

Error scenarios

ScenarioWhat the API does
Voucher expires unpaidThe payment moves to failed and payment.failed fires. Expired references are rejected at the counter — a customer who still wants to pay needs a fresh checkout.
Customer pays after expiry anywayThe scheme refuses the cash at registration; nothing reaches the API. (Store systems reject expired barcodes at scan time.)
Amount above the scheme's cash ceilingCash schemes cap single transactions: creation fails with a 400 invalid_request_error rather than issuing an unpayable voucher.
Currency mismatch400 invalid_request_error with currency_not_supported — each voucher scheme is single-currency (see the table above).
Duplicate checkout for the same orderTwo live payments with the same reference — cancel the stale one; see Living with the delay.