Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Redemption Widget · Boson Protocol
Skip to content

Redemption Widget

The Redemption Widget lets a buyer act on the vouchers (rNFTs) they already hold. It shows their exchanges in the protocol, lets them redeem, cancel before redemption, raise disputes after redemption, and (for sellers) revoke or complete exchanges. The widget detects what state each exchange is in and surfaces only the actions that make sense.

Where it shines: when you sell vouchers on a different surface (your own storefront, the Boson dApp, an NFT marketplace, a metaverse, an in-game shop) but want one canonical place buyers come back to redeem. Drop the widget on your domain and your customers redeem there.

The hosted build is at widgets.bosonprotocol.io — under the hood it's a React app over @bosonprotocol/react-kit's <RedemptionWidget />.

Quickest embed: script + button

<script async type="text/javascript" src="https://widgets.bosonprotocol.io/scripts/boson-widgets.js"></script>
 
<button id="boson-redeem" data-config-id="production-137-0">Redeem</button>

The loader script finds the button by its id, mounts the modal, and handles wallet connect. The buyer signs in with whatever EIP-1193 wallet they prefer; the widget filters to their committed exchanges automatically.

Optional Boson-branded styling

<head>
  <link rel="stylesheet" href="https://widgets.bosonprotocol.io/styles.css">
</head>
<body>
  <button id="boson-redeem" class="bosonButton" data-config-id="production-137-0">Show Redeem</button>
</body>

Filtering and deep-linking

AttributeEffect
data-config-id (required)Deployment to query — see Networks → ConfigIds matrix.
data-accountRestrict to a single buyer wallet (otherwise uses the connected wallet).
data-exchange-idOpen directly to one exchange — buyer skips the selection screen.
data-seller-ids (comma-list) or data-seller-idFilter to exchanges from one or more sellers.
data-signatures (comma-list)Multi-seller domain-binding signatures — see WooCommerce → connect.
data-look-and-feel"modal" (default) or "regular" for inline rendering.
data-widget-actionForce a starting screen — SELECT_EXCHANGE (default), EXCHANGE_DETAILS, REDEEM_FORM, CANCEL_FORM, CONFIRM_REDEEM.
data-exchange-statePre-filter to COMMITTED / REDEEMED / DISPUTED / COMPLETED.
data-show-redemption-overview"true" (default) shows the overview pane on entry; "false" jumps straight to the action.

Iframe form (no JS loader)

For sites that block third-party scripts:

<iframe
  src="https://widgets.bosonprotocol.io/#/redeem?configId=production-137-0&exchangeId=80"
  width="100%" height="800"
  allow="clipboard-write; web-share">
</iframe>

Every data-* attribute above maps 1:1 to a URL query param of the same name (without the data- prefix; camelCase: exchangeId, widgetAction, lookAndFeel, etc.).

Programmatic open

window.boson.openRedeem({
  configId: "production-137-0",
  exchangeId: "80",
  widgetAction: "REDEEM_FORM",
})

Capturing delivery info on your server

When a buyer redeems a physical product, the widget collects the delivery info. You have three options for where it goes:

1. XMTP to the seller (default)

The widget posts the info as an XMTP message keyed to the seller's wallet. The seller's fulfilment system reads it from their XMTP inbox. Zero infrastructure on your end.

Enable: data-send-delivery-info-through-xmtp="true".

2. POST to your endpoint

Your server receives the delivery info as a POST. Useful when you have an existing OMS / WMS / CRM.

<button id="boson-redeem"
  data-config-id="production-137-0"
  data-post-delivery-info-url="https://yourshop.example.com/api/boson/delivery"
  data-post-delivery-info-headers='{"Authorization": "Bearer …"}'>
  Redeem
</button>

The widget POSTs { exchangeId, deliveryInfo, signature, … }. Validate the signature server-side before processing.

3. postMessage to the parent window

If the widget is embedded in your dApp and you want to handle delivery info entirely in the parent page:

data-target-origin="https://yourshop.example.com"

The widget calls window.parent.postMessage({ exchangeId, deliveryInfo, eventTag }, targetOrigin). Useful for fully-custom checkout-style integrations.

Lifecycle callbacks (backend)

Three optional server endpoints fire at the redemption lifecycle:

AttributeWhen it fires
data-post-redemption-submitted-urlBuyer's redeem transaction broadcast (not yet confirmed).
data-post-redemption-confirmed-urlRedemption transaction confirmed on-chain.
data-post-delivery-info-urlDelivery info collected (see above).

Each has a paired *-headers attribute (JSON-encoded) for auth headers. Treat these as fire-and-forget — the widget doesn't retry, so handlers must be idempotent (key on exchangeId).

React Kit — when you want full control

If you'd rather skip the hosted build:

import { RedemptionWidget } from "@bosonprotocol/react-kit"
 
<RedemptionWidget
  configId="production-137-0"
  envName="production"
  withReduxProvider
  withWeb3React
  withGlobalStyle
  exchangeId="80"
  widgetAction="REDEEM_FORM"
  closeWidgetClick={() => { /* … */ }}
  deliveryInfoHandler={(info) => { /* … */ }}
  redemptionSubmittedHandler={(tx) => { /* … */ }}
  redemptionConfirmedHandler={(tx) => { /* … */ }}
  // … same props as the URL query params, plus a few extras …
/>

See the widgets repo for the full prop catalogue.

Common gotchas

  • Wrong chain. The buyer's wallet must be on the chain that matches configId. The widget prompts a switch but some wallets reject silently.
  • CSP. Allow widgets.bosonprotocol.io in script-src, frame-src, and connect-src (the latter for postback URLs and XMTP).
  • Multi-seller storefronts need per-seller signatures to prove origin-binding — otherwise the widget refuses to render to protect buyers from spoofed sellers.
  • Delivery info handlers are not retried by the widget — your endpoint must be idempotent (dedupe on exchangeId). Pair with on-chain event listeners (Build → Marketplace operators → Webhooks & events) as the backstop.

Next