pointsPrice from the member’s wallet; canceling one refunds those points.
This guide covers creating, fetching, and listing redemptions.
These are member-mode calls: they use the member token, not the
Org-API-Key. See Authentication. Whether the redemption
lands in sandbox or live is selected by the key the token was minted from - see
Environments.
Create a redemption
createRedemption(input, options/idempotencyKey?) calls
POST /v1/redemptions and returns 201 with the created Redemption. The body
is a CreateRedemptionRequest:
| Field | Type | Description |
|---|---|---|
offer | string, required | The id of the offer to redeem (from listOffers). |
externalUserID | string | Names the member when a machine token acts on their behalf. Optional otherwise. |
pointsPrice from the member’s balance. If the
balance is below the price, the call fails with INSUFFICIENT_POINTS rather than
going negative.
curl
Safe retries with an idempotency key
Because creating a redemption spends points, always send anIdempotency-Key
header (the SDK accepts it via idempotencyKey). If a network blip makes you
retry, the server returns the original redemption instead of charging twice.
Reusing a key with a different body is rejected with IDEMPOTENCY_KEY_REUSED.
Fetch a redemption
getRedemption(id) calls GET /v1/redemptions/{id} and returns a single
Redemption:
| Field | Type | Description |
|---|---|---|
id | string | The redemption id. |
offer | Offer | The redeemed offer (see Offers). |
status | string | The current lifecycle status (see below). |
createdAt | string | ISO-8601 creation time. |
startAt | string | null | When the experience starts, if scheduled. |
endAt | string | null | When the experience ends, if scheduled. |
curl
List redemptions
listRedemptions(...) calls GET /v1/redemptions and returns a
ListRedemptionsResponse with redemptions and a nextCursor. It accepts
limit, cursor, externalUserID, and a status filter. The snippet below
pages through a member’s OPEN redemptions:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Maximum redemptions per page. |
cursor | string | The nextCursor from the previous page. Omit on the first call. |
externalUserID | string | Filter to a specific member (when a machine token acts on their behalf). |
status | string | Filter to one lifecycle status (see below). |
ListRedemptionsResponse is cursor-paginated: follow nextCursor until it is
null. Treat the cursor as an opaque token.Status lifecycle
A redemption moves through these statuses as the experience is booked and fulfilled:| Status | Meaning |
|---|---|
SUBMITTED | The redemption was just created. |
OPEN | It is open and being processed. |
AWAITING_VENDOR | Waiting on the vendor. |
AWAITING_CUSTOMER | Waiting on the customer. |
PURCHASED | The booking is purchased. |
COMPLETED | The experience completed. |
CANCELED | The redemption was canceled; the points are refunded. |
Canceling a redemption refunds the debited points back to the member’s
wallet. See Points and wallet for how the balance
reflects debits and refunds.
Errors
Branch on the errorcode, never on message. The redemption-specific codes
are:
| Code | Status | Meaning |
|---|---|---|
INSUFFICIENT_POINTS | 422 | The member’s balance is below the offer’s pointsPrice. |
REDEMPTION_ALREADY_EXISTS | 409 | The member already redeemed this offer. |
OFFER_UNAVAILABLE | 422 | The offer is expired or otherwise not redeemable. |
requestId you quote to support.
Next steps
Points and wallet
How debits and refunds move the member’s balance.
Retries and idempotency
The idempotency-key contract and automatic retry behavior.
Errors
Stable codes, the error shape, and the request id.