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

> ## Agent Instructions
> Before planning an integration, read https://docs.scrip.dev/which-endpoints-you-need.md. It lists the calls an app makes as users earn and redeem, such as sending and reversing events, reading balances, and redeeming rewards. Every other endpoint creates or changes the program itself, and the dashboard at https://app.scrip.dev is the usual place for that work.
> Gift cards are rewards in the program's rewards catalog, next to custom rewards. Redeem one with `POST /v1/participants/{id}/redemptions/items` and a `fulfillment` object. When the order succeeds, show the participant the claim link from `fulfillment.claim_url` in the redemption response or from `POST /v1/redemptions/{id}/claim-link`. An order can finish after the request returns, so handle the `redemption.fulfillment_succeeded` and `redemption.fulfillment_failed` webhooks. See https://docs.scrip.dev/guides/gift-cards.md.
> Give every event, redemption, and transfer an `idempotency_key` built from your own data, such as an order ID, so retries are safe. Keep API keys on your server.
> Request and response schemas are in https://docs.scrip.dev/openapi.json. Add `.md` to any docs URL to get the page as Markdown.

# Gift cards

> Let participants spend their rewards balance on gift cards

Gift cards let participants exchange their balance for value they can spend with a merchant. You choose the cards to offer and their prices in your program's asset. Scrip orders each card and returns a claim link for the participant to open.

Gift cards appear alongside your custom rewards in the [rewards catalog](/guides/rewards-catalog). This guide follows a participant redeeming 100 stars for a USD 100.00 gift card. You can use any linked asset and set your own prices.

| What you want to do                       | Where to start                                                 |
| ----------------------------------------- | -------------------------------------------------------------- |
| Choose cards and set their prices         | [Set up](#set-up) and [Reward sources](/guides/reward-sources) |
| Show cards in your application            | [List active rewards](#list-active-rewards)                    |
| Order a card for a participant            | [Redeem](#redeem)                                              |
| Give the participant access to their card | [Deliver the claim link](#deliver-the-claim-link)              |

## Set up

Connect a fulfillment account in the Scrip dashboard. This is the account you use to buy the gift cards. Complete the account's setup and funding steps, then choose which cards to add to your program and how much they cost in your asset.

There are two balances involved in a redemption. The participant spends their asset balance in Scrip, while your fulfillment account pays for the card. For our example, the participant spends 100 stars and your account funds a USD 100.00 card. Scrip records the asset charge in the ledger; it never holds or transfers the money that pays for the card.

Your fulfillment account must be `ACTIVE` and have enough funds to cover orders. The participant must also have enough available asset balance. To configure the cards and prices through the API, follow [Reward sources](/guides/reward-sources).

## List active rewards

Fetch your program's catalog to show participants what they can redeem:

```bash theme={null}
GET /v1/programs/{programId}/rewards?status=ACTIVE
```

The response includes custom rewards and gift cards. Each gift card includes its supported values and currencies in `fulfillment`, plus any available images and descriptions in `display`. You can build the selection screen from this response without fetching each product separately.

This excerpt shows a card that lets the participant choose a value between USD 5.00 and USD 100.00:

```json theme={null}
{
  "data": [
    {
      "id": "2b7a9c4e-1f3d-4a8b-9e6c-5a1d3f7b8c02",
      "name": "Example Gift Card",
      "category": "GIFT_CARD",
      "status": "ACTIVE",
      "asset_id": "a3bb189e-8bf9-4c8b-9be0-6b5d2f4e7a02",
      "redemption_type": "AMOUNT_BASED",
      "face_currency": "USD",
      "display": {
        "image_url": "https://images.example.com/gift-card.png",
        "description_html": "<p>Use this gift card online or in store.</p>"
      },
      "fulfillment": {
        "delivery_method": "claim_link",
        "asset_scale": 0,
        "countries": ["US"],
        "currencies": ["USD"],
        "value_min_minor": 500,
        "value_max_minor": 10000,
        "denominations_minor": [],
        "rate": "0.01"
      }
    }
  ]
}
```

Keep the reward's `id` for the redemption request. Follow `pagination.next_cursor` if the catalog has more pages. When rendering content from `display`, handle missing fields and sanitize HTML.

An active reward can still be unavailable to a particular participant, for example because they have too little balance or have reached a redemption limit. Scrip checks those conditions when they redeem.

## Choose a value and show the price

The card's face value is the amount the participant can spend with the merchant. The API expresses it in currency minor units, such as cents for USD. A USD 100.00 card has a `face_value_minor` of `10000`.

For an `AMOUNT_BASED` gift card, let the participant choose a supported value and a currency from `fulfillment.currencies`. A product can offer a list of values in `denominations_minor`, an inclusive minimum-to-maximum range, or both. A value is valid if it appears in the list or falls within the range.

Multiply the chosen face value by `fulfillment.rate` to show the asset price. In this example, `10000 × 0.01 = 100` stars. Round up to the decimal precision in `fulfillment.asset_scale` using decimal arithmetic. See [Pricing](/guides/reward-sources#pricing) to set the rate and [Price fractional assets](/guides/reward-sources#price-fractional-assets) for rounding examples.

For a `UNIT_BASED` gift card, you have already chosen a fixed value and currency during setup. Show that value and use `unit_cost` as the asset price. The participant does not need to choose a value.

## Redeem

When the participant confirms their choice, submit the reward ID and card value:

```bash theme={null}
POST /v1/participants/{id}/redemptions/items
```

```json theme={null}
{
  "program_id": "8f14e45f-ceea-4e70-9df8-2a7d1b3c9f01",
  "reward_id": "2b7a9c4e-1f3d-4a8b-9e6c-5a1d3f7b8c02",
  "idempotency_key": "gift-card-order-4471",
  "expected_amount": "100",
  "fulfillment": {
    "face_value_minor": 10000,
    "currency": "USD"
  }
}
```

Scrip calculates the asset charge from the reward's price. Send the card value in `fulfillment`; omit the custom-reward `amount` field. Each redemption orders one card, so omit `quantity` or set it to `1`.

Send the price the participant reviewed as `expected_amount`, in asset units. If the current cost differs, Scrip returns `409 reward_price_changed` without creating an order or reserving assets. Fetch the catalog again and ask the participant to confirm the updated price. This field is optional, but recommended whenever you show a price before redeeming.

For fixed-value cards, also send the value and currency the participant reviewed. Scrip rejects the request if either has changed. You can omit them with `fulfillment: {}` when you want to use the card's current settings without this check.

Use a unique `idempotency_key` for each purchase. If a request times out, retry the same request with the same key to retrieve the existing redemption. Its original charge is preserved even if the catalog price changes later.

Scrip first reserves the cost in the participant's `HELD` balance, then orders the card. Once the order succeeds, it captures that balance to the program's redemption target (`SYSTEM_REDEMPTION` by default). If fulfillment fails, it releases the remaining reserved balance. Scrip handles completion automatically; omit `capture` from the request.

The request waits up to about 30 seconds for the result. A successful response can include the claim link immediately. Relevant fields are shown below:

```json theme={null}
{
  "id": "7f422b43-4ba2-41c7-b05d-e4e90b68e978",
  "status": "COMPLETED",
  "amount": "100",
  "fulfillment": {
    "status": "SUCCEEDED",
    "claim_url": "https://claim.example.com/abc123"
  }
}
```

Read the redemption's `status` to decide what to show:

| Status      | What to do                                                                                |
| ----------- | ----------------------------------------------------------------------------------------- |
| `COMPLETED` | Show the claim link. If the response has no link, retrieve it with the endpoint below.    |
| `PENDING`   | Show that the card is being prepared. Keep the redemption ID and wait for the outcome.    |
| `FAILED`    | Show that the card could not be ordered. Use `fulfillment.failure_reason` to investigate. |

A new redemption returns HTTP `201`, including when it is still pending. A retry with the same idempotency key returns the existing redemption with `200`.

## Deliver the claim link

A claim link opens the page where the participant accesses their gift card. Show `fulfillment.claim_url` from the redemption response when it is present.

To retrieve a link after the order finishes, or when the participant returns later, use the same redemption ID:

```bash theme={null}
POST /v1/redemptions/{id}/claim-link
```

Send no request body. The response includes the URL:

```json theme={null}
{
  "claim_url": "https://claim.example.com/abc123",
  "status": "SUCCEEDED",
  "expires_at": "2026-12-01T10:30:00Z"
}
```

`expires_at` appears only when a link expiry is available. The endpoint can return the same URL on later requests. Reading a redemption or receiving a webhook does not return a claim link.

A missing link does not mean the purchase failed. Retrieve it for the existing redemption so the participant is not charged for another card. See [Create a claim link](/api-reference/redemptions/create-a-claim-link) for error handling.

## Handle a pending order

Subscribe to `redemption.fulfillment_succeeded` and `redemption.fulfillment_failed` to receive the outcome. On success, retrieve the claim link for that redemption. You can also check its status with `GET /v1/redemptions/{id}`. To return immediately when creating a redemption, send the `Prefer: respond-async` header.

If `fulfillment.status` is `AWAITING_FUNDS`, add funds to your fulfillment account in the dashboard. Scrip retries the order automatically and sends `fulfillment_account.funds_low` once for that fulfillment.

The participant's reserved balance stays held while the order waits. If the funding window expires, the order fails and the remaining reserved balance is released. The default window is 24 hours; the redemption's reservation deadline can end the wait sooner.

Scrip controls the order's completion. Cancellation is available only before an order is placed, and a delivered gift card cannot be reversed through Scrip. See [Get redemption](/api-reference/redemptions/get-redemption#gift-card-fulfillment) for status and failure details, and [Redemption lifecycle](/guides/redemption-lifecycle) for reservation deadlines and ledger entries.

## Set redemption limits

You can limit each card's value and how many cards a participant redeems over a rolling period. For example, allow cards worth up to USD 100.00 each, with at most three cards totaling USD 250.00 per participant over 24 hours. Configure these limits on the program; Scrip checks them before reserving any balance.

See [Update a program](/api-reference/programs/update-a-program#gift-card-limits) for the fields and validation rules. To stop new gift-card redemptions for an account, disable it in the dashboard.

<CardGroup cols={3}>
  <Card title="Choose cards and prices" icon="gift" href="/guides/reward-sources">
    Configure the gift cards in your program's catalog.
  </Card>

  <Card title="Receive order updates" icon="webhook" href="/guides/webhooks#gift-card-events">
    Handle completed orders, failures, and low account balances.
  </Card>

  <Card title="Track gift-card costs" icon="chart-line" href="/guides/reporting#fulfillment-cost">
    Review orders by program, status, and currency.
  </Card>
</CardGroup>
