Skip to main content
Redemptions debit a participant’s balance via the API. They come in two forms: an amount-based redemption for open-ended cashouts (statement credits, charitable donations), and a catalog item redemption for purchasing a specific reward. Both are triggered by your application, not by rules.

Amount Redemption

Debit a specific amount from a participant’s balance:
POST /v1/participants/{id}/redemptions
{
  "program_id": "program-uuid",
  "asset_id": "asset-uuid",
  "amount": "1000",
  "description": "Cash out request #12345",
  "idempotency_key": "cashout-12345"
}
FieldRequiredDescription
program_idYesProgram context
asset_idYesWhich asset to debit
amountYesPositive decimal amount
descriptionYesReason for the redemption (1-500 characters)
idempotency_keyNoPrevents duplicate redemptions on retry. Same key + different payload returns 409.
The amount is debited from the participant’s AVAILABLE balance and credited to the program’s configured redemption target.

Catalog Item Redemption

Redeem a specific item from the reward catalog:
POST /v1/participants/{id}/redemptions/items
{
  "program_id": "program-uuid",
  "reward_id": "reward-uuid",
  "quantity": 2,
  "idempotency_key": "order-789"
}
For UNIT_BASED rewards, specify quantity (defaults to 1 if omitted). For AMOUNT_BASED rewards, specify amount instead. For UNIT_BASED rewards, the cost is quantity * unit_cost. For AMOUNT_BASED rewards, the redeemed amount itself is the cost. Either way, the cost is stored on the redemption record. For UNIT_BASED rewards, inventory is tracked: redeemed_count increments globally and per participant, and the reward status changes to OUT_OF_STOCK when max_total is reached. See Rewards Catalog for setting up catalog items.

Redemption Targets

Each program configures where redeemed funds flow via redemption_target_type. Most programs use SYSTEM_REDEMPTION to keep redeemed value separate from breakage.
TargetDescription
SYSTEM_REDEMPTIONDefault. Tracks redeemed value in a dedicated system account.
SYSTEM_BREAKAGECombines with forfeited value in the breakage account.
LEDGER_ENTITYRoutes to a specific ledger entity. Requires redemption_target_entity_id on the program.
The target is captured on the redemption record at creation time. If you change the program’s target configuration later, existing redemptions and their reversals still use the original target. This keeps the ledger consistent. Change a program’s target with Update a program. The program must not be archived when you change target configuration:
PATCH /v1/programs/{id}
{
  "redemption_target_type": "LEDGER_ENTITY",
  "redemption_target_entity_id": "entity-uuid"
}
LEDGER_ENTITY requires redemption_target_entity_id in the same request. Switching to SYSTEM_REDEMPTION or SYSTEM_BREAKAGE must omit redemption_target_entity_id and clears any existing reference. New programs default to SYSTEM_REDEMPTION; the target cannot be set at creation time. Archived programs reject redemption target changes with 409 program_archived. Reactivate the program before changing redemption_target_type or redemption_target_entity_id.

Reversals

Reverse a redemption to return funds to the participant:
# Full reversal
POST /v1/redemptions/{id}/reverse
{
  "reason": "Order cancelled by customer",
  "idempotency_key": "refund-123"
}

# Partial reversal (amount-based)
POST /v1/redemptions/{id}/reverse
{
  "amount": "500",
  "reason": "Partial refund for damaged item",
  "idempotency_key": "refund-456"
}

# Partial reversal (unit-based, whole units only)
POST /v1/redemptions/{id}/reverse
{
  "quantity": 1,
  "reason": "Customer returned 1 gift card",
  "idempotency_key": "refund-789"
}
Omit amount or quantity for a full reversal. Include it for a partial reversal. The field must match the original redemption type: UNIT_BASED catalog redemptions accept quantity, AMOUNT_BASED and amount redemptions accept amount. reason is required (1-500 characters). Reversals are often reviewed during disputes or audits, so every reversal needs a human-readable explanation on record.

Reversal Status

Each reversal updates the redemption’s status:
StatusMeaning
COMPLETEDNo reversals applied
PARTIALLY_REVERSEDSome amount or quantity reversed, more can follow
FULLY_REVERSEDEntire redemption reversed, no further reversals allowed
The redemption tracks cumulative totals in reversed_amount and, for catalog items, reversed_quantity.

Inventory Restoration

For UNIT_BASED catalog items, reversals decrement redeemed_count and the per-participant redemption_count. If a reward was OUT_OF_STOCK and the reversal brings inventory below max_total, the reward status returns to ACTIVE.

Lot Restoration

For LOT-mode assets, reversals restore the specific lots spent by the original redemption. Lots are restored in reverse spend order and retain their original metadata including expires_at and matures_at.

Viewing Redemptions

You can list redemptions per participant, fetch a single redemption by ID, or list the reversals attached to a redemption.
# List participant redemptions
GET /v1/participants/{id}/redemptions

# Get redemption details
GET /v1/redemptions/{id}

# List reversals for a redemption
GET /v1/redemptions/{id}/reversals

Requirements

Redemptions enforce these checks:
  • Participant must be ACTIVE
  • Program must be ACTIVE (not SUSPENDED or ARCHIVED)
  • Asset must not be archived
  • Sufficient AVAILABLE balance for the requested amount
  • For catalog items: reward must be ACTIVE and within its availability window
Reversals enforce a shorter list:
  • Participant must be ACTIVE
  • The redemption must not already be FULLY_REVERSED
  • A partial amount or quantity must not exceed the remaining unreversed amount or quantity
Idempotency keys are scoped per program. Replaying a request with the same key returns the original record without creating a duplicate.