Two ways to run the purchase
Which route you take depends on what the Program enabled. The rest of this page describes the full API integration: your app renders every screen and calls the endpoints itself. The other route is the WebApp. Easy Vouchers (EVO) is a WebApp option that renders the purchase and the Voucher wallet for you, so your app opens a page URL and supplies the native capabilities the flow needs. The model below still applies in that mode: same order statuses, same discount modes, same refunds. What the WebApp renders across the whole journey is listed in What the WebApp handles.
Both routes share the prerequisites below, since enrollment and the debit account are yours either way.
Before you start
The
consumer_id is your own bank-side identifier. Paylead resolves it internally.
What a Voucher Offer carries
Voucher Offers are the entries typedVOUCHER in the catalog, and their perks.voucher block defines what the Consumer may buy. The fields are listed in What an Offer carries.
An Offer is either fixed amounts (pick from amounts) or a free amount (min_amount to max_amount, respecting amount_step). An order that breaks those constraints is rejected with PL-400-09 or PL-400-12.
The purchase flow
1
Create the order
Call The response returns the
POST /perks/consumers/{consumer_id}/offers/{offer_id}/vouchers/orders. The body carries amount_selections, one entry per face value and quantity, plus payin_account_id in delegated payment. One order buys one or more Vouchers from a single Offer.order_id. The order starts in CREATED and no Voucher exists yet.2
Pay the order
The payment model is a Program setting, not a per-call choice. Both models use
POST /perks/consumers/{consumer_id}/vouchers/orders/{order_id}/payments, with a different body and a different follow-up.- Paylead-hosted payment
- Delegated payment
Send
return_url, language (ISO 639-1) and card_type (CB_VISA_MASTERCARD, AMEX, MAESTRO or BCMC). The response carries a redirect_url: send the Consumer to that payment webview.3
Confirm the payment (Paylead-hosted only)
When the Consumer comes back from the webview, call
POST /perks/consumers/{consumer_id}/vouchers/orders/{order_id}/payments/confirm. Paylead checks the pay-in with the payment provider.A payin_psp_status of SUCCEEDED moves the order to CONFIRMED and returns the vouchers list. Any other status returns the provider status and an empty list. Calling confirm again on an order already confirmed is safe, which covers a Consumer refreshing the confirmation screen.4
Wait for the Vouchers to be issued
CONFIRMED does not mean usable. The supplier issues the Vouchers asynchronously, and the PDF and the codes stay empty until the order reaches READY. Show a waiting state and poll GET /perks/consumers/{consumer_id}/vouchers?order_id={order_id} until the status changes. Paylead chases the supplier in the background, so no action is needed on your side.5
Deliver the Vouchers
Once the order is
READY, display the face value, the expiry date, the Brand and the codes, and offer the PDF through GET /perks/consumers/{consumer_id}/vouchers/{voucher_id}/pdf.Order statuses
A Voucher reports the status of the order it came from, in its ownstatus field.
Two attributes live outside that flow:
archived_at, set when the Consumer archives the Voucher or when it expires, and refunded_at, set when the Voucher is refunded. A daily Paylead job archives expired Vouchers and settles orders left in CREATED: a successful pay-in confirms the order, a failed one moves it to PAYMENT_FAILED, and a pay-in that never lands moves it to CANCELLED.
How the discount is served
The Offer decides how the Consumer gets the discount, which changes what they pay.
In
CASHBACK mode, the Reward is created at CONFIRMED with the Consumer status VALIDATION, for the order amount times discount_rate. When the order reaches READY it is validated, moves to POOLED, and its amount is recomputed on the Vouchers actually delivered. A fully refunded order cancels it.
From there the Reward follows the standard pool route: it appears in GET /perks/consumers/{consumer_id}/rewards and is paid out through POST /perks/consumers/{consumer_id}/pools/me/payouts. Plan for the full Reward journey, including KYC and the payout account, or the discount stays in the pool. See Reward lifecycle.
After the purchase
GET /perks/consumers/{consumer_id}/voucher-orders gives the order history instead: total amount, Voucher count, Brand and date, filtered by Brand name and sorted by date. It lists READY orders only.
Partial deliveries and refunds
Refunds are driven by Paylead, not by your integration. When the supplier delivers an incomplete order, the missing Vouchers are refunded to the Consumer automatically: pro rata of the price paid, or in full when nothing was delivered.refunded_at is set on the Vouchers concerned.
Two consequences to handle on screen. A READY order can hold fewer Vouchers than were ordered, so build the list from the response rather than from the order. And a refunded Voucher stays readable through its ID while being excluded from the default lists by is_refunded=false.
Errors
Voucher endpoints return the standard error envelope. TreatPL-409-12, PL-409-15 and PL-400-10 as part of the normal flow rather than as technical failures: each one has a Consumer-facing way out. The full list is on Errors.
What’s next
Reward lifecycle
Track the Reward a discount in Cashback mode generates: the status tracks, and the list and detail endpoints.
Seamless Payment
The delegated payment contract: the endpoint you expose and the result callback.
Pool & payout
How a validated Reward reaches the Consumer’s pool and gets paid out.
Errors
The error envelope, the Paylead codes, and the retry strategy.