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

# Gift Cards

Gift card payments are supported directly through the API with support for split
tender across traditional payment methods and gift cards, as well as automatic reversal.

## Setup

See the [Qwikcilver][qwikcilver] and [Value Link][valuelink] connector pages for setup instructions.

## Features

* **Balance checks** - Query the balance of one or more gift cards before checkout.
* **Gift card-only payments** - Accept payments funded entirely by gift cards.
* **Split tender** - Split a payment across one or more gift cards and a standard payment method.
* **Stored gift cards** - Vault gift cards against a buyer for reuse.
* **Automatic reversal** - Automatically revert all gift card charges if any single card fails.
* **Virtual card issuance** - Issue a new virtual gift card through a supported gift card service.
* **Physical card activation** - Activate a physical gift card, with the option to store it in the vault.

## API endpoints

The API for gift cards consists of the following endpoints and API features.

* [Manage gift card services](/reference/gift-card-services)
* [Check gift card balances](/reference/gift-cards/list-gift-card-balances)
* [Manage stored gift cards](/reference/gift-cards) and associate them with buyers
* [Issue a virtual gift card](/reference/gift-cards/issue-gift-card)
* [Activate a physical gift card](/reference/gift-cards/activate-gift-card)
* [Enhancements to the transaction endpoints](/reference/transactions/new-transaction) to allow for payments with one or more gift cards,
  including the ability to split a payment across gift cards and other payment methods.

## Integration

### Check a gift card balance

Before processing a payment, you can check the balance of one or more gift cards.
You can query by stored gift card ID or by raw card number and PIN.

<CodeGroup>
  ```csharp C# theme={"system"}
  var res = await sdk.GiftCards.Balances.ListAsync(giftCardBalanceRequest: new GiftCardBalanceRequest() {
      Items = new List<Item>() {
          Item.CreateGiftCardRequest(
              new GiftCardRequest() {
                  Number = "4123455541234561234",
                  Pin = "1234",
              }
          ),
      },
  });

  // handle response
  ```

  ```go Go theme={"system"}
  res, err := s.GiftCards.Balances.List(ctx, components.GiftCardBalanceRequest{
      Items: []components.Item{
          components.CreateItemGiftCardRequest(
              components.GiftCardRequest{
                  Number: "4123455541234561234",
                  Pin:    "1234",
              },
          ),
      },
  })
  if err != nil {
      log.Fatal(err)
  }
  if res != nil {
      // handle response
  }
  ```

  ```java Java theme={"system"}
  ListGiftCardBalancesResponse res = sdk.giftCards().balances().list()
          .giftCardBalanceRequest(GiftCardBalanceRequest.builder()
              .items(List.of(
                  Item.of(GiftCardRequest.builder()
                      .number("4123455541234561234")
                      .pin("1234")
                      .build())))
              .build())
          .call();

  if (res.giftCardSummaries().isPresent()) {
      System.out.println(res.giftCardSummaries().get());
  }
  ```

  ```php PHP theme={"system"}
  $giftCardBalanceRequest = new Gr4vy\GiftCardBalanceRequest(
      items: [
          new Gr4vy\GiftCardRequest(
              number: '4123455541234561234',
              pin: '1234',
          ),
      ],
  );

  $response = $sdk->giftCards->balances->list(
      giftCardBalanceRequest: $giftCardBalanceRequest
  );

  if ($response->giftCardSummaries !== null) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  res = g_client.gift_cards.balances.list(items=[
      {
          "number": "4123455541234561234",
          "pin": "1234",
      },
  ])

  # Handle response
  print(res)
  ```

  ```typescript TypeScript theme={"system"}
  const result = await gr4vy.giftCards.balances.list({
    items: [
      {
        number: "4123455541234561234",
        pin: "1234",
      },
    ],
  });

  console.log(result);
  ```
</CodeGroup>

See the [balance check API reference](/reference/gift-cards/list-gift-card-balances) for the full list of request and response fields.

### Store a gift card

You can store a gift card in the vault to use it in future transactions without
re-entering the card details. Optionally, associate the card with a buyer.

<CodeGroup>
  ```csharp C# theme={"system"}
  var res = await sdk.GiftCards.CreateAsync(giftCardCreate: new GiftCardCreate() {
      Number = "4123455541234561234",
      Pin = "1234",
  });

  // handle response
  ```

  ```go Go theme={"system"}
  res, err := s.GiftCards.Create(ctx, components.GiftCardCreate{
      Number: "4123455541234561234",
      Pin:    "1234",
  })
  if err != nil {
      log.Fatal(err)
  }
  if res != nil {
      // handle response
  }
  ```

  ```java Java theme={"system"}
  CreateGiftCardResponse res = sdk.giftCards().create()
          .giftCardCreate(GiftCardCreate.builder()
              .number("4123455541234561234")
              .pin("1234")
              .build())
          .call();

  if (res.giftCard().isPresent()) {
      System.out.println(res.giftCard().get());
  }
  ```

  ```php PHP theme={"system"}
  $giftCardCreate = new Gr4vy\GiftCardCreate(
      number: '4123455541234561234',
      pin: '1234',
  );

  $response = $sdk->giftCards->create(
      giftCardCreate: $giftCardCreate
  );

  if ($response->giftCard !== null) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  res = g_client.gift_cards.create(
      number="4123455541234561234",
      pin="1234",
  )

  # Handle response
  print(res)
  ```

  ```typescript TypeScript theme={"system"}
  const result = await gr4vy.giftCards.create({
    number: "4123455541234561234",
    pin: "1234",
  });

  console.log(result);
  ```
</CodeGroup>

See the [stored gift cards API reference](/reference/gift-cards) for managing and listing vaulted gift cards.

### Issue a virtual gift card

You can issue a new virtual gift card through the primary gift card service configured
on the merchant account.

<CodeGroup>
  ```csharp C# theme={"system"}
  var res = await sdk.GiftCards.Issuances.CreateAsync(giftCardIssuanceCreate: new GiftCardIssuanceCreate() {
      Theme = "031111372",
      Amount = 5000,
      Currency = "EUR",
  });

  // handle response
  ```

  ```go Go theme={"system"}
  res, err := s.GiftCards.Issuances.Create(ctx, components.GiftCardIssuanceCreate{
      Theme:    "031111372",
      Amount:   5000,
      Currency: "EUR",
  })
  if err != nil {
      log.Fatal(err)
  }
  if res != nil {
      // handle response
  }
  ```

  ```java Java theme={"system"}
  IssueGiftCardResponse res = sdk.giftCards().issuances().create()
          .giftCardIssuanceCreate(GiftCardIssuanceCreate.builder()
              .theme("031111372")
              .amount(5000L)
              .currency("EUR")
              .build())
          .call();

  if (res.giftCardIssuance().isPresent()) {
      System.out.println(res.giftCardIssuance().get());
  }
  ```

  ```php PHP theme={"system"}
  $giftCardIssuanceCreate = new Gr4vy\GiftCardIssuanceCreate(
      theme: '031111372',
      amount: 5000,
      currency: 'EUR',
  );

  $response = $sdk->giftCards->issuances->create(
      giftCardIssuanceCreate: $giftCardIssuanceCreate
  );

  if ($response->giftCardIssuance !== null) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  res = g_client.gift_cards.issuances.create(theme="031111372", amount=5000, currency="EUR")

  # Handle response
  print(res)
  ```

  ```typescript TypeScript theme={"system"}
  const result = await gr4vy.giftCards.issuances.create({
    theme: "031111372",
    amount: 5000,
    currency: "EUR",
  });

  console.log(result);
  ```
</CodeGroup>

The response includes a `url` for the issued gift card. The raw card number and PIN are not
returned directly in the API response. If you want to store the card for future use, retrieve
the card details from that URL and pass them to the [store a gift card](#store-a-gift-card)
endpoint.

See the [issue a gift card API reference](/reference/gift-cards/issue-gift-card) for the full list of request and response fields.

### Activate a physical gift card

You can activate a physical gift card through the primary gift card service. The `pin` is
optional, but if provided, it must be the correct PIN for the card. Set `store` to `true` to
also store the activated gift card in the vault, optionally associating it with a buyer using
`buyer_id` or `buyer_external_identifier`. A `pin` is required when `store` is `true`.

<CodeGroup>
  ```csharp C# theme={"system"}
  var res = await sdk.GiftCards.Activations.CreateAsync(giftCardActivationCreate: new GiftCardActivationCreate() {
      Number = "4123455541234561234",
  });

  // handle response
  ```

  ```go Go theme={"system"}
  res, err := s.GiftCards.Activations.Create(ctx, components.GiftCardActivationCreate{
      Number: "4123455541234561234",
  })
  if err != nil {
      log.Fatal(err)
  }
  if res != nil {
      // handle response
  }
  ```

  ```java Java theme={"system"}
  ActivateGiftCardResponse res = sdk.giftCards().activations().create()
          .giftCardActivationCreate(GiftCardActivationCreate.builder()
              .number("4123455541234561234")
              .build())
          .call();

  if (res.giftCard().isPresent()) {
      System.out.println(res.giftCard().get());
  }
  ```

  ```php PHP theme={"system"}
  $giftCardActivationCreate = new Gr4vy\GiftCardActivationCreate(
      number: '4123455541234561234',
  );

  $response = $sdk->giftCards->activations->create(
      giftCardActivationCreate: $giftCardActivationCreate
  );

  if ($response->giftCard !== null) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  res = g_client.gift_cards.activations.create(number="4123455541234561234", store=False)

  # Handle response
  print(res)
  ```

  ```typescript TypeScript theme={"system"}
  const result = await gr4vy.giftCards.activations.create({
    number: "4123455541234561234",
  });

  console.log(result);
  ```
</CodeGroup>

When `store` is `true`, a `gift-card.created` [webhook](/guides/features/webhooks/events) is sent once the
card has been stored.

See the [activate a gift card API reference](/reference/gift-cards/activate-gift-card) for the full list of request and response fields.

## Reversals

As part of processing gift cards, the ability to automatically revert an authorized payment method or redeemed gift card before it is reverted is supported.

The logic for this feature is as follows.

* When a transaction occurs, regular payment methods are authorized (or captured)
  first, depending on their support for delayed capture.
* Gift cards are only redeemed after the (optional) regular payment method has
  succeeded to authorize/capture.
  * When no regular payment method is present, gift cards are always redeemed.
* In the case that any of the gift cards failed to redeem, any redemptions of other gift cards
  and regular payments are reverted, so that no charges remain at the end.
  * In the case of an authorized or captured regular payment method, the transaction is
    reverted by either voiding the authorization or refunding a capture.

<Warning>
  In some cases, gift card redemptions are not reverted. Please see the anti-fraud section below.
</Warning>

### Outcome

There are two fields returned by the transaction API which allows you to
quickly understand if the original intent of a transaction was met.

* The `multi_tender` (boolean) field indicates if the
  transaction included more than one tender.
* The `intent_outcome` (enum) field indicates if the
  original intent (`authorize` / `capture`) was met. This field is set
  to either `pending` if the transaction has not completed yet, `succeeded` in the case
  all tenders were processed successfully, and `failed` if any of them failed.

  This field does not change value after the `succeeded` or `failed` status has been achieved,
  even if the transaction is subsequently captured, voided, or refunded in any way.

```json theme={"system"}
{
    "type": "transaction",
    "id": "89bdaeeb-4be8-4ab7-a9e2-6f2c3da5f2d0",
    "intent": "capture",
    "multi_tender": true,
    "intent_outcome": "succeeded",
    ...
}
```

### Reversals and anti-fraud reviews

There is a key difference in how reversals are handled when a transaction encounters
any kind of halt in processing. This happens when the transaction is held in
anti-fraud review.

In these situations, if the approval fails, or if the transaction is rejected,
the gift cards are **not refunded**. The reason for this is that because of the
time delay between the redemption and refund the user may no longer have the gift card
at hand anymore.

## Gift card usage data

Each stored gift card tracks usage statistics that help you determine which card to preselect at checkout or prioritize in your UI.

| Field              | Description                                                                                                                                                     |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `last_used_at`     | The date and time when this gift card was most recently used in any transaction. `null` if the gift card has not been used yet.                                 |
| `usage_count`      | The number of times this gift card has been used in any transaction.                                                                                            |
| `cit_last_used_at` | The date and time when this gift card was most recently used in a customer-initiated transaction (CIT). `null` if the gift card has not been used in a CIT yet. |
| `cit_usage_count`  | The number of times this gift card has been used in a customer-initiated transaction (CIT).                                                                     |

<Note>
  Usage data is not back-filled. Only transactions processed after this feature was enabled are counted.
</Note>

### Sorting by usage

The [list buyer gift cards](/reference/gift-cards/list-buyer-gift-cards) endpoint supports a `sort_by` query parameter to order results by any of the four usage fields.

```
GET /buyers/gift-cards?sort_by=last_used_at
GET /buyers/gift-cards?sort_by=cit_last_used_at
```

Results are returned in descending order by default, so the most recently used or most frequently used gift card appears first. To sort in ascending order, set `order_by=asc`.

## Stored gift card filtering

The API automatically removes any gift cards stored for a buyer with a zero balance
or an expiry date in the past. When you add a new card, you may receive an error informing
you that you've hit the limit of the number of stored cards (defaults to 10).

<Note>
  You need to actively call the [`GET /buyers/gift-cards`](/reference/gift-cards/list-buyer-gift-cards) to clear out any expired
  and zero balance gift cards.
</Note>

## Limits

By default, the number of gift cards that can be used at the same time is limited to 10. This limit
applies to the APIs for querying gift card balances, processing gift cards, as well as the
number of gift cards that can be stored on a buyer.

To change this limit, reach out to the support team.

In the event of the limit being exceeded, a `HTTP 400` response with an error message
`The buyer's gift card count has already reached the maximum limit of 10 gift cards` is returned.

## Testing

Use the [gift card simulator](/guides/features/gift-cards/simulator) to test balance checks,
redemptions, and error codes in your sandbox environment without a live connector.

[qwikcilver]: /connections/payments/qwikcilver-gift-card

[valuelink]: /connections/payments/valuelink-gift-card
