The BrandWallet API uses a single standard payload structure for all transactions. Whether a customer has a stamp card, a point card, or a multi-tier program, the same body shape on POST /v1/transactions/process handles them all.
A single payload can do any combination of the following in one call:
- Campaign collection — applicable campaigns on the selected
card run; balances update and reward coupons are granted when thresholds are reached.
- Coupon redemption — coupons passed in
redeem.coupons are redeemed; a product coupon can carry the product it was used for (productOpaqueId), which is recorded and excluded from earning.
- Point spend —
redeem.points is deducted from the card’s point balance; the monetary value is calculated server-side and reflected in the response’s payableAmount.
- Order discounts —
apply_discount promotions configured by the brand (for example a student discount) reduce the amount to charge; the total comes back in discountAmount and is already deducted from payableAmount.
Example payload:
Key concepts
- A transaction payload represents a single basket — construct and submit one payload per customer interaction.
- Product, category, user, and branch ids are opaque ids, your external system identifiers; BrandWallet resolves them internally.
user and branch default to the authenticated API user and its branch when omitted.
amount is the single money truth: the register total with all of your own discounts (commercial + coupon) already deducted; BrandWallet-applied deductions (promotion discounts, points) not deducted — they come back in the response (discountAmount, redeemed.pointsValue) and are already reflected in payableAmount. Never send a discounted amount from a previous response back as amount.
items[].amount is the line unit amount and items[].productPrice is the product’s list price — the latter is used only by menu sync to keep your catalog current; neither enters payment math.
orderId is your idempotency key: a completed transaction with the same orderId is rejected with duplicate_transaction, making retries safe.
- Required fields:
customer (from GET /v1/customers/find), card (card id from find → cards[].id, not a campaign id — the campaigns run come from this card), and amount. Full field reference: POST /v1/transactions/process.
Payload flow
- Identify the customer — call GET /v1/customers/find with the customer’s phone, email, or card barcode. Save the returned
id (customer id) and cards[].id (customerpass id).
- Preview the discount (optional) — call POST /v1/transactions/validate with the basket and
redeem.points before committing.
- Commit the basket — call POST /v1/transactions/process with the same body, optionally echoing the previewed
payableAmount as expectedPayableAmount for a server-side consistency check. BrandWallet returns the updated loyalty state in executedActions, the amount to charge in payableAmount, and what was redeemed in redeemed.
Use BrandWallet as the single source of truth for all loyalty data. Do not cache points, stamps, or coupon balances locally — fetch fresh state before each transaction.
Last modified on October 8, 2026