Skip to main content
Use an asynchronous redemption when fulfillment happens after you accept the request. Authorization moves the exact amount from the participant’s AVAILABLE balance to HELD and returns a PENDING redemption. Your fulfillment service then completes, fails, or cancels that redemption. Instant redemptions suit flows that can deliver immediately. Both modes use the same amount and catalog redemption endpoints.

Choose a fulfillment mode

Set the default on the program:
fulfillment_mode defaults to INSTANT. pending_redemption_ttl is optional and accepts a duration from 60 seconds through 365 days. A create request can override the mode with capture:

Authorize a redemption

Set capture to false on an amount redemption:
Catalog item redemptions accept the same capture, expires_at, and ttl_seconds fields at POST /v1/participants/{id}/redemptions/items. The response includes the lifecycle and ledger anchors:
For a pending redemption, journal_entry_id identifies the authorization hold. capture_journal_entry_id, captured_at, and resolved_at appear after successful capture.

Track catalog inventory

For a UNIT_BASED catalog reward, authorization increments both committed_units and pending_units. Capture moves the quantity from pending_units to delivered_units while committed_units stays unchanged. Failure, cancellation, and timeout decrement pending_units and committed_units without changing delivered_units. Releasing pending inventory can return an OUT_OF_STOCK reward to ACTIVE. See Rewards catalog for the full inventory contract.

Use the returned deadline

You can send one request deadline:
  • expires_at: absolute RFC 3339 timestamp
  • ttl_seconds: lifetime relative to authorization
The two fields are mutually exclusive. A request or program deadline must be at least 60 seconds and no more than 365 days. If the request and program both set a deadline, the earlier one wins. If neither sets one, Scrip uses 90 days. For a LOT asset, the earliest selected lot expiration is a physical limit and can shorten that policy deadline. This shortening is valid. Always schedule fulfillment against the expires_at returned on the redemption instead of calculating a deadline from your request. If the resulting deadline is less than 60 seconds away, authorization returns 422 fulfillment_window_too_short. Capture is accepted only before the effective deadline. At or after the deadline, the complete endpoint returns 409 reservation_expired, even if the timeout worker has not resolved the row yet.

Resolve the redemption

Complete

Complete only after your fulfillment provider confirms delivery:
Completion moves the authorized amount from HELD to the redemption target and changes the redemption to COMPLETED. Capture is full-only. The amount cannot be changed during completion. An authorization can still complete while the participant is SUSPENDED because the spend was already approved. A CLOSED participant cannot be captured.

Fail

Use failure when fulfillment was attempted and could not be delivered:

Cancel

Use cancellation when your application or the participant stops fulfillment before delivery:
Fail and cancel return live reserved value from HELD to AVAILABLE. They do not recreate LOT value that already expired.

State transitions

Only COMPLETED and PARTIALLY_REVERSED redemptions can be reversed. See Redemptions. The first terminal request wins. Repeating the same outcome returns the stored redemption. A different terminal request returns 409 redemption_already_resolved.

Expiration and reserved lots

A reservation protects value from generic RELEASE, FORFEIT, and VOID_HOLD operations. It does not stop normal LOT expiration. Reserved lots keep their original expiration, maturity, and issuer lineage. The timeout worker changes an overdue PENDING redemption to FAILED with failure_reason: "expired". If all reserved LOT value already expired, no value returns to AVAILABLE. If part remains live, only that remainder is released.

Webhooks and balance mirrors

Authorization emits redemption.pending and balance.held. The pending webhook includes the reservation_id and effective expires_at. A fulfillment provider can identify the reservation and schedule capture without fetching the redemption first. Completion emits redemption.completed. Failure and timeout emit redemption.failed plus balance.released when live value is released. Cancellation emits redemption.cancelled plus balance.released when live value is released. Successful capture does not emit a balance.* event. If you maintain a balance mirror from webhooks, reconcile it with the participant balance and statement endpoints so HELD does not remain overstated.

Time windows

The participant redemption list filters from and to by creation time, which is the authorization time for a pending redemption. Reporting recognizes redeemed value when capture succeeds, using captured_at. A redemption authorized in June and captured in July appears in a June-filtered redemption list and in July reporting. Use each surface for its stated purpose.