Redeem Voucher via Points Exchange
POST/client/users/:correlation_id/voucher/voucher-exchange/redeem
POST /voucher/voucher-exchange/redeem — Redeem Points for Voucher
Debits the member's point balance and issues a new voucher instance from the specified definition, via the Voucher Exchange flow. The debit + issuance is atomic — either both succeed, or neither does.
Request Body
{
"voucherDefinitionId": "def-10off",
"businessUnit": "DEFAULT"
}
| Field | Type | Required | Description |
|---|---|---|---|
voucherDefinitionId | string | Yes | Definition to redeem — must appear in the eligible list |
businessUnit | string | Yes | BU scope — must match the definition's BU |
Preconditions
-
Definition exists and is in the active exchange pool → else
404 VOUCHER_DEFINITION_NOT_FOUND -
member.availablePointBalance >= definition.pointValue→ else409 INSUFFICIENT_POINTS(response includesrequiredPoints+availablePointBalance) -
Daily/lifetime redemption limits not yet reached for this definition → else
409 REDEMPTION_LIMIT_EXCEEDED -
Member's tier (if gated) eligible
Redemption Flow
-
Validate body + preconditions
-
Atomic transaction:
-
Debit
pointValuefrom point balance (writes Voucher Burn transaction part) -
Issue new voucher instance —
status=AVAILABLE, all definition-derived fields hydrated
-
-
On step 2 failure → full rollback (no orphan issuance, no silent point loss)
-
Return the issued voucher + remaining balance
Response — 200
| Field | Type | Description |
|---|---|---|
advice.voucher.applied[] | array | Issued voucher(s) — each item is a minimal voucher view |
transactionId | string | Unique ID for this exchange transaction |
pointsRedeemed | number | Points debited (= definition.pointValue) |
remainingPointBalance | number | Member balance after debit |
Idempotency
This endpoint is NOT idempotent. Duplicate POSTs will double-debit if both succeed. Client responsibilities:
-
Disable the redeem button immediately on first submission
-
On network error / timeout → do not auto-retry. Instead, re-query
GET /issuances?type=VOUCHERand the points balance to reconcile state before prompting the user -
Display a confirmation modal before the first submission
Error Responses
| Status | errorCode | When |
|---|---|---|
| 400 | INVALID_REQUEST | Missing body, missing voucherDefinitionId, malformed fields |
| 401 | — | Missing/expired OAuth token |
| 404 | VOUCHER_DEFINITION_NOT_FOUND | Definition doesn't exist or is not in the exchange pool |
| 409 | INSUFFICIENT_POINTS | Balance below pointValue — response includes requiredPoints + availablePointBalance |
| 409 | REDEMPTION_LIMIT_EXCEEDED | Daily/lifetime cap reached |
| 500 | — | Unexpected server error |
Related
-
GET .../voucher/voucher-exchange/eligible— check eligibility before calling this -
GET .../issuances?type=VOUCHER— confirm the new voucher landed in inventory
Request
Responses
- 200
- 400
- 401
- 403
- 404
- 409
200 - Redemption Successful
400 - Missing voucherDefinitionId
401 - Unauthorized
403 - Ghost Member Not Allowed
404 - Definition Not Found
409 - Insufficient Balance