create-consumer-redemptions (API keys can hold it); reading redemptions needs view-consumer-redemptions.
Redeem a voucher
SendPOST /consumer/v1/redemptions with an Idempotency-Key:
Location header pointing at the new redemption:
active or deactivation-scheduled, both Catalog Toggles are on, you have accepted its current Price Terms and it has stock.
Choosing a set or a provider
Name exactly one target:voucherSetId: redeem from this voucher set. Use it when your customer picked a specific offer.providerId: let the platform pick the provider’s best redeemable set. Candidates are the provider’s visible, switched-on sets in your effectivepositionorder (unset positions last), then by activation time. Sets without a redeemable Price Acceptance are skipped; a set that is depleted or whose entity limit is reached is skipped and the next one is tried.
data-failed-validation with the constraint mutually-exclusive or required. In providerId mode, when every candidate is depleted you get 409 provider-depleted; when every candidate was skipped for its entity limit, 409 entity-limit-reached.
Attaching a redemption entity
A Redemption Entity is your record of who redeems: an end customer, an employee or a device, identified by your own opaquerefId. Attach one in either of two ways (at most one per request):
redemptionEntityId: an existing entity of yours.redemptionEntity:{ "refId": "customer:42", "displayName": "…", "metadata": {} }. The platform finds the entity with thisrefIdor creates it in the same transaction.metadata, when sent and different, updates the entity.
setting.entityLimit (for example {"max": 1, "period": "calendar-month"}) caps how often one entity can redeem that set; the next attempt answers 409 entity-limit-reached. A blocked entity answers 409 redemption-entity-blocked, an erased one 409 redemption-entity-erased.
You can also send your own metadata (a JSON object up to 16 KiB). It is stored on the redemption and included in the redemption-created webhook. Never put personal data in refId, metadata or the Idempotency-Key: redemptions are kept for accounting after an entity is erased.
Batch redemptions
POST /consumer/v1/redemptions:batch redeems up to 10 vouchers in one all-or-nothing request, for example a welcome bonus of three ride credits:
itemsholds 1-10 items, each withvoucherSetIdorproviderIdand aquantityfrom 1 to 10. The sum of all quantities must not exceed 10, else 422batch-too-large.- The entity and
metadataapply to every redemption of the batch. - The 201 response is a
redemption-batchwhoseitemsare full redemptions in request order; an item withquantity: 2becomes two consecutive redemptions. Read it again withGET /consumer/v1/redemption-batches/{redemptionBatchId}. - If any item fails, nothing is redeemed. The error names the failing item in
more.validationErrorswith the propertyitems[<index>]. - Every redemption of the batch stores the batch’s
Idempotency-Key, soGET /consumer/v1/redemptions?filter[idempotencyKey]=<key>returns the whole batch.
What you receive
issued:kindiscodeorlink. For code sets,codeholds the voucher code andlinkthe link rendered from the set’s Link Template (ornullwhen the set has no Link Template); for link sets,linkholds the link. Show it only to the entitled customer.validFrom/validUntil: when the voucher can be used at the provider. Allocation only picks vouchers that are still valid.voucherSet: the set’s name and provider name as they were at redemption time, so historical redemptions stay readable after a set is renamed or ends.redemptionEntity,metadata,actor,idempotencyKeyandredeemedAt.
GET /consumer/v1/redemptions/{redemptionId} or list redemptions, for example filtered by redemptionEntity.refId or redeemedAt. Files downloaded from the dashboard show them masked.
You also receive the webhook redemption-created with the same representation. The provider receives its own reduced projection that contains no consumer data, entity, metadata or issued value.
Errors
Errors use the standard error body; branch onerrorCode:
A suspended partner gets 403
partner-suspended. See Errors for the common codes and the retry table.
Best practices
- Always send an
Idempotency-Keyand reuse it for every retry of the same intent, for exampleorder-8812:line-1. A retry after a timeout then replays the original 201 with the identicalissuedobject instead of redeeming twice. See Idempotency. - A stored 409 is final for its key. After
voucher-set-depletedorprice-acceptance-required, a retry with the same key replays the 409 even if stock was added or prices were accepted. Use a new key for a new attempt. - Retry only transient failures with the same key: network errors, 409
idempotency-key-in-use, 409concurrent-updateand 5xx. - Reconcile instead of guessing. If you lost track of an intent,
GET /consumer/v1/redemptions?filter[idempotencyKey]=<key>: a non-empty page means it ran. - Treat issued codes as secrets. Show them only to the customer they belong to, never log them, and keep them out of analytics tools.
- Keep your catalog fresh with the
catalog-*webhooks and hide entries whosepriceAcceptance.statusis not redeemable. - Sync your ledger incrementally with
filter[redeemedAt][gte]=<last seen minus 60 seconds>&sort=redeemedAtand de-duplicate byid.