> ## Documentation Index
> Fetch the complete documentation index at: https://docs.renaiss.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Redeem

> Check card eligibility, quote shipping, submit checkout and track delivery.

Redeem lets an EOA owner request physical delivery of vaulted cards. Use `createRedemptionClient`; private requests require your builder key and a wallet access token for that same wallet. See [authentication](/authentication#verify-a-wallet-for-shipping) for setup.

## Vault regions and redemption batches

Renaiss stores cards in vaults across regions including Hong Kong (`HK`), Malaysia (`MY`) and the United States (`US`). Each redeemable card belongs to the region of its current vault. The card response exposes this as `regionCountryCode`, with `vaultDisplayName` identifying the vault.

**One redemption batch can contain cards from only one vault region.** A Hong Kong card and a Malaysia card cannot be redeemed in the same batch, even when both are going to the same recipient and delivery address.

| Selected cards | Required batches |
| - | - |
| Two HK cards | One HK batch |
| Two HK cards and one MY card | One HK batch and one MY batch |
| One MY card and one US card | One MY batch and one US batch |

Call `fetchRedemptionRegions()` for the verified wallet's current card counts by region. Use `listRedeemableCards({ countryCode: 'HK' }).firstPage()` to browse one region, and group selections by each card's `regionCountryCode`. Keep each batch within the 50-card limit.

For each regional batch, request its own shipping quote, review its fees and complete its checkout. The API resolves the cards' current vault locations and rejects a mixed-region selection with `Choose cards from a single region`. Refresh the selection if a card's vault or eligibility has changed.

The delivery country is supplied separately as `address.countryCode`. The API validates the route from the vault region to that destination and returns the available courier options. Vault regions are determined by card custody; changing the delivery address does not combine cards from different regions into one batch.

## From card to delivery

<Steps>
  <Step title="Verify the wallet">
    Ask the user to verify when they open shipping data. Call `connectRedemptionWallet({ origin })` with your registered frontend origin. This signs an access message, not a payment.
  </Step>

  <Step title="Select eligible cards">
    Call `listRedeemableCards().firstPage()` and use `fetchRedemptionRegions()` to show available regions. A cart may contain up to 50 cards from the same vault country/region.

    The API checks current on-chain ownership, vault readiness and shipping eligibility. A card displayed elsewhere in a collection is not necessarily ready to ship.
  </Step>

  <Step title="Validate the address and quote shipping">
    Use `REDEMPTION_COUNTRIES` for country choices and state-field requirements. Call `validateRedemptionAddress({ address })`, then `fetchRedemptionQuote({ tokenIds, address })` for current courier options and fees.

    Country metadata is a form aid; it does not guarantee that a card or destination is serviceable. The API decides eligibility and prices.
  </Step>

  <Step title="Prepare the selected courier">
    Call `prepareRedemption({ quoteId, courierId, recipient, insurance })`. Show the selected cards, destination, recipient and total fee for review. Duties are estimates shown separately from the charged shipping checkout total.
  </Step>

  <Step title="Sign and submit">
    Check the chain, wallet balance and USDT allowance to Permit2. If needed, approve the reviewed amount with your wallet library and wait for confirmation.

    Pass the reviewed selection to `signRedemption({ prepared, expected })`, then call `submitRedemption({ signed })` once. The SDK validates the contracts, token, spender, amount, address, recipient and expiry before signing.
  </Step>

  <Step title="Track the request">
    Save the `preparationId` before submission and the returned `requestId`. Use `fetchRedemptionCheckout` for checkout status, then the order and tracking methods below.

    Successful checkout starts the Redeem request. It does not mean a shipment has been created or dispatched.
  </Step>
</Steps>

## Keep the reviewed intent

`expected` must contain the card IDs, total, address and recipient the user approved. Pass money and token IDs as bigint values in SDK requests.

```ts theme={null}
import {
  getError,
  getValue,
  isFailed,
  type PreparedRedemption,
  type RedemptionClient,
  type RedemptionExpectation,
} from '@renaiss-protocol/client';

export async function signReviewedCheckout(
  shipping: RedemptionClient,
  prepared: PreparedRedemption,
  reviewed: RedemptionExpectation,
) {
  const result = await shipping.signRedemption({
    prepared,
    expected: reviewed,
  });
  if (isFailed(result)) throw new Error(getError(result).detail);
  return getValue(result);
}
```

Do not reconstruct `expected` from an unexpected preparation to bypass a mismatch. Return to review if the quote, recipient or destination changes.

## Expiry and recovery

Shipping quotes expire after 10 minutes. A preparation inherits its quote's deadline, so preparing near expiry does not start a fresh 10-minute window. Use the returned expiry timestamp and keep the device clock accurate.

| Situation | Next step |
| - | - |
| Quote or preparation expired before submission | Request a new quote and review its price before signing |
| User cancelled signing | Keep the selection; retry only on the user's next action |
| Response lost after submission | Call `fetchRedemptionCheckout({ preparationId })` to reconcile the existing checkout |
| Wallet session expired | Verify again, then resume reading the existing checkout or order |

Checkout status is retained for 24 hours. Do not create and pay for a new checkout merely because the first response was lost or the order list has not caught up. Keep pending IDs per wallet and chain; do not persist signatures, session tokens or contact details in a recovery record.

## Orders and tracking

| Method | Purpose |
| - | - |
| `listRedemptionOrders().firstPage()` | The verified wallet's order summaries |
| `fetchRedemptionOrder({ requestId })` | Cards, fees, status and delivery details |
| `syncRedemptionTracking({ requestId })` | Refresh shipment tracking from the provider |

Use `shipmentStatus`, `trackingNumber`, `trackingUrl` and `trackingLastSyncedAt` to describe delivery. Order `createdAt` and `updatedAt` are record timestamps; neither proves dispatch or delivery.

See the [API reference](/api-reference) for address and recipient fields, courier responses and error codes. The SDK keeps its `Redemption*` method/type names and the API keeps its existing JSON fields; **Redeem** is the documentation section name.
