Gift Cards
Gift cards in Saleor are digital codes that customers can redeem during checkout to reduce the total order amount. In Saleor, they can be created by staff or purchased directly at checkout.
Gift cards are not assigned to any channel and can be used in any channel whose currency matches the gift card’s currency.
Creating and Managing Gift Cards
Staff users with the MANAGE_GIFT_CARD permission can create gift cards directly in Saleor and send them to customers. Gift cards can be created individually or in bulk, and can have an expiry date set or be non-expiring.
Creating Gift Cards
Single Gift Card Creation
The following example shows how to create a single gift card. Once you provide the userEmail and configure the email plugin for the given channel, the gift card is sent to the customer, and the SENT_TO_CUSTOMER event is created. In this example, providing the expiryDate value will set the expiry date. If you want to create a non-expiring card, do not provide the expiryDate value.
mutation giftCardCreate($input: GiftCardCreateInput!) {
giftCardCreate(input: $input) {
giftCard {
id
code
last4CodeChars
isActive
expiryDate
initialBalance {
currency
amount
}
currentBalance {
currency
amount
}
events {
type
}
}
}
}{
"input": {
"balance": {
"amount": 100,
"currency": "USD"
},
"userEmail": "test@example.com",
"channel": "channel-USD",
"expiryDate": "2050-10-10",
"isActive": true
}
}{
"data": {
"giftCardCreate": {
"giftCard": {
"id": "R2lmdENhcmQ6MjQ1",
"code": "0A65-0A28-1347",
"last4CodeChars": "1347",
"isActive": true,
"expiryDate": "2050-10-10",
"initialBalance": {
"currency": "USD",
"amount": 100
},
"currentBalance": {
"currency": "USD",
"amount": 100
},
"events": [
{
"type": "ISSUED"
}
]
}
}
}
}Bulk Gift Card Creation
Creating gift cards in bulk is similar, but you need to specify the number of gift cards to create and the tag value which will be assigned to all created gift cards.
mutation giftCardBulkCreate($input: GiftCardBulkCreateInput!) {
giftCardBulkCreate(input: $input) {
giftCards {
id
code
isActive
}
}
}{
"input": {
"count": 5,
"tags": ["example-tag"],
"isActive": true,
"balance": {
"amount": 200,
"currency": "USD"
}
}
}{
"data": {
"giftCardBulkCreate": {
"giftCards": [
{
"id": "R2lmdENhcmQ6MjQ2",
"code": "F5A2-81C9-E289",
"isActive": true
},
{
"id": "R2lmdENhcmQ6MjQ3",
"code": "FA61-39FC-03DE",
"isActive": true
},
{
"id": "R2lmdENhcmQ6MjQ4",
"code": "0A7B-2E6F-06A8",
"isActive": true
},
{
"id": "R2lmdENhcmQ6MjQ5",
"code": "F7C9-7479-8AE6",
"isActive": true
},
{
"id": "R2lmdENhcmQ6MjUw",
"code": "60C5-10B9-DF19",
"isActive": true
}
]
}
}
}After creation, you can export the gift card codes to CSV. Read more about exporting gift cards.
Managing Gift Cards
Resending Gift Cards
You can resend the gift card to the customer at any time after creation. If the userEmail is not provided, the card is sent to the customer who already used the card. If the card hasn’t been used yet, it is sent to the customer who created it.
mutation giftCardResend($input: GiftCardResendInput!) {
giftCardResend(input: $input) {
giftCard {
id
code
events {
type
user {
email
}
app {
name
}
}
}
}
}{
"input": {
"id": "R2lmdENhcmQ6MjUw",
"channel": "default-channel",
"email": "saleor@example.com"
}
}{
"data": {
"giftCardResend": {
"giftCard": {
"id": "R2lmdENhcmQ6MjUw",
"code": "60C5-10B9-DF19",
"events": [
{
"type": "ISSUED",
"user": {
"email": "staff_user@saleor.io"
},
"app": null
}
]
}
}
},
"extensions": {
"cost": {
"requestedQueryCost": 1,
"maximumAvailable": 50000
}
}
}Updating Gift Cards
After creation, the tag, expiry date, and balance amount can be updated.
mutation giftCardUpdate($id: ID!, $input: GiftCardUpdateInput!) {
giftCardUpdate(id: $id, input: $input) {
giftCard {
id
expiryDate
initialBalance {
currency
amount
}
currentBalance {
currency
amount
}
events {
type
expiryDate
oldExpiryDate
oldTags
tags
balance {
initialBalance {
amount
currency
}
oldInitialBalance {
amount
currency
}
currentBalance {
amount
currency
}
oldCurrentBalance {
amount
currency
}
}
}
}
}
}{
"id": "R2lmdENhcmQ6MjUw",
"input": {
"balanceAmount": 70,
"expiryDate": "2040-10-10",
"addTags": [
"new-tag"
]
}
}{
"data": {
"giftCardUpdate": {
"giftCard": {
"id": "R2lmdENhcmQ6MjUw",
"expiryDate": "2040-10-10",
"initialBalance": {
"currency": "USD",
"amount": 70
},
"currentBalance": {
"currency": "USD",
"amount": 70
},
"events": [
{
"type": "ISSUED",
"expiryDate": null,
"oldExpiryDate": null,
"oldTags": null,
"tags": null,
"balance": {
"initialBalance": {
"amount": 200,
"currency": "USD"
},
"oldInitialBalance": null,
"currentBalance": {
"amount": 200,
"currency": "USD"
},
"oldCurrentBalance": null
}
},
{
"type": "RESENT",
"expiryDate": null,
"oldExpiryDate": null,
"oldTags": null,
"tags": null,
"balance": null
},
{
"type": "BALANCE_RESET",
"expiryDate": null,
"oldExpiryDate": null,
"oldTags": null,
"tags": null,
"balance": {
"initialBalance": {
"amount": 70,
"currency": "USD"
},
"oldInitialBalance": {
"amount": 200,
"currency": "USD"
},
"currentBalance": {
"amount": 70,
"currency": "USD"
},
"oldCurrentBalance": {
"amount": 200,
"currency": "USD"
}
}
},
{
"type": "EXPIRY_DATE_UPDATED",
"expiryDate": "2040-10-10",
"oldExpiryDate": null,
"oldTags": null,
"tags": null,
"balance": null
},
{
"type": "TAGS_UPDATED",
"expiryDate": null,
"oldExpiryDate": null,
"oldTags": [
"example-tag"
],
"tags": [
"example-tag",
"new-tag"
],
"balance": null
}
]
}
}
}
}Adjusting the Balance
Added in Saleor 3.23.
Use the giftCardBalanceAdjust mutation to change a card’s current balance by an amount instead of overwriting it. A positive amount tops the card up, and a negative amount deducts from it.
Unlike giftCardUpdate (which sets balanceAmount to an absolute value and records a BALANCE_RESET event), the adjustment is applied atomically at the database level. This makes it safe to run while a card is being charged in a concurrent checkout, so no update is silently lost. Each adjustment records a BALANCE_ADJUSTED event.
The mutation applies two clamping rules:
- A deduction that would take the balance below zero clamps the current balance to zero.
- A top-up above the current initial balance raises the initial balance to the new current balance.
The amount cannot be zero and must match the currency precision of the card. The staff member or app needs the MANAGE_GIFT_CARD permission.
mutation giftCardBalanceAdjust($id: ID!, $amount: Decimal!) {
giftCardBalanceAdjust(id: $id, amount: $amount) {
giftCard {
id
initialBalance {
currency
amount
}
currentBalance {
currency
amount
}
events {
type
balance {
currentBalance {
amount
currency
}
oldCurrentBalance {
amount
currency
}
}
}
}
errors {
field
code
message
}
}
}{
"id": "R2lmdENhcmQ6MjUw",
"amount": -20
}{
"data": {
"giftCardBalanceAdjust": {
"giftCard": {
"id": "R2lmdENhcmQ6MjUw",
"initialBalance": {
"currency": "USD",
"amount": 70
},
"currentBalance": {
"currency": "USD",
"amount": 50
},
"events": [
{
"type": "BALANCE_ADJUSTED",
"balance": {
"currentBalance": {
"amount": 50,
"currency": "USD"
},
"oldCurrentBalance": {
"amount": 70,
"currency": "USD"
}
}
}
],
"errors": []
}
}
}
}Activating and Deactivating Gift Cards
Cards can be activated and deactivated at any time, either individually or in bulk.
mutation giftCardDeactivate($id: ID!) {
giftCardDeactivate(id: $id) {
giftCard {
id
isActive
events {
type
}
}
}
}{
"id": "R2lmdENhcmQ6MjUw"
}{
"data": {
"giftCardDeactivate": {
"giftCard": {
"id": "R2lmdENhcmQ6MjUw",
"isActive": false,
"events": [
{
"type": "ISSUED"
},
{
"type": "RESENT"
},
{
"type": "BALANCE_RESET"
},
{
"type": "EXPIRY_DATE_UPDATED"
},
{
"type": "TAGS_UPDATED"
},
{
"type": "DEACTIVATED"
}
]
}
}
}
}For bulk operations, use giftCardBulkActivate and giftCardBulkDeactivate mutations.
Restricting Gift Cards to a Customer
Added in Saleor 3.23.
By default, a gift card is a bearer instrument: whoever holds the code can redeem it, including in guest checkout. Customer assignment is an opt-in restriction layered on top of this default. Once a card is restricted to a customer, only that customer’s account can use it, and the card can no longer be redeemed in guest checkout.
Assignment is distinct from usedBy:
assignedTois forward-looking — the customer who is allowed to spend the card. It is a restriction that staff set on purpose.usedByis historical — the last customer who spent the card. It is an audit record and is deprecated.
Assigning a Customer
You can restrict a card to a customer at creation time by passing assignedTo (a customer’s user ID) to giftCardCreate, or afterwards with the giftCardAssignUser mutation. Both require the MANAGE_GIFT_CARD permission and trigger the GIFT_CARD_UPDATED webhook.
Assigning a customer records an ASSIGNED_TO_USER event and stores the customer’s email on the card.
mutation giftCardAssignUser($id: ID!, $userId: ID!) {
giftCardAssignUser(id: $id, userId: $userId) {
giftCard {
id
assignedTo {
id
email
}
assignedToEmail
events {
type
assignedTo {
oldAssignedToEmail
currentAssignedToEmail
}
}
}
errors {
field
code
message
}
}
}{
"id": "R2lmdENhcmQ6MjUw",
"userId": "VXNlcjoyMg=="
}{
"data": {
"giftCardAssignUser": {
"giftCard": {
"id": "R2lmdENhcmQ6MjUw",
"assignedTo": {
"id": "VXNlcjoyMg==",
"email": "customer@example.com"
},
"assignedToEmail": "customer@example.com",
"events": [
{
"type": "ASSIGNED_TO_USER",
"assignedTo": {
"oldAssignedToEmail": null,
"currentAssignedToEmail": "customer@example.com"
}
}
],
"errors": []
}
}
}
}A card cannot be assigned when it has already been used in an order, when it is attached to a checkout that has payments, or when it has been used by a gift card payment transaction. In those cases the mutation returns a CANNOT_ASSIGN error. If the card is attached to a checkout that has no payments, the card is detached from that checkout as part of the assignment.
Unassigning a Customer
Use the giftCardUnassignUser mutation to remove the restriction and return the card to bearer behavior. It requires the MANAGE_GIFT_CARD permission, triggers the GIFT_CARD_UPDATED webhook, and records an UNASSIGNED_FROM_USER event.
mutation giftCardUnassignUser($id: ID!) {
giftCardUnassignUser(id: $id) {
giftCard {
id
assignedTo {
id
}
assignedToEmail
}
errors {
field
code
message
}
}
}
Filtering by Assigned Customer
The giftCards query accepts an assignedTo filter that returns the cards restricted to the given customers. This replaces the deprecated usedBy filter.
query {
giftCards(first: 10, filter: { assignedTo: ["VXNlcjoyMg=="] }) {
edges {
node {
id
assignedToEmail
}
}
}
}
Setting Up Gift Cards as Products
To allow customers to purchase gift cards, you need to:
- Create a product type with
GIFT_CARDkind - Create a product using this product type
- Configure stock settings
Gift Card Fulfillment Settings
The automaticallyFulfillNonShippableGiftCard order setting controls when bought gift cards will be created:
- If set to
True: Gift card is created during checkout completion - If set to
False: Gift card is created during order fulfillment
Gift Card Expiry Settings
Gift card settings can be configured to:
- Never expire
- Expire after a specific period
Example of setting expiry period to 1 year:
mutation giftCardSettingsUpdate($input: GiftCardSettingsUpdateInput!) {
giftCardSettingsUpdate(input: $input) {
giftCardSettings {
expiryType
expiryPeriod {
type
amount
}
}
}
}{
"input": {
"expiryType": "EXPIRY_PERIOD",
"expiryPeriod": {
"type": "YEAR",
"amount": 1
}
}
}{
"data": {
"giftCardSettingsUpdate": {
"giftCardSettings": {
"expiryType": "EXPIRY_PERIOD",
"expiryPeriod": {
"type": "YEAR",
"amount": 1
}
}
}
}Gift Cards as payment method
Transaction API allows you to use built-in payment gateway dedicated for consuming gift cards created in Saleor.
Using Gift Cards in Checkout
To use a gift card in a checkout, run the transactionInitialize mutation.
Following payment gateway details must be included in mutation variables:
"paymentGateway": {
"id": "saleor.io.gift-card-payment-gateway",
"data": {
"code": "valid-gift-card-code"
}
}
Restricted cards are rejected with the generic Gift card code is not valid. message, the same one returned for a code that does not exist, so the response never reveals whether a card exists or whom it belongs to. The check runs before the balance check, so a caller who is not the assignee never learns the card’s remaining balance.
Example of using gift card to in a checkout. Notice id of payment gateway being set to saleor.io.gift-card-payment-gateway.
mutation transactionInitialize($id: ID!, $amount: PositiveDecimal!, $paymentGateway: PaymentGatewayToInitialize!) {
transactionInitialize(id: $id, amount: $amount, paymentGateway: $paymentGateway) {
transactionEvent {
type
}
errors {
field
message
code
}
}
}{
"id": "Q2hlY2tvdXQ6MjcyYzYxOGItZGU3My00Zjc0LTllNzYtZDMzNGQ1ZThkMTk0",
"amount": "3",
"paymentGateway": {
"id": "saleor.io.gift-card-payment-gateway",
"data": {
"code": "8554-B58D-06B9"
}
}
}{
"data": {
"transactionInitialize": {
"transactionEvent": {
"type": "AUTHORIZATION_SUCCESS"
},
"errors": []
}
}
}Managing Gift Card payments
Creating Authorization Transactions
Successfully running transactionInitialization mutation results in creation of an authorization transaction.
Updating Authorization Transactions
If gift card is already authorized to a checkout but amount has to be updated run transactionInitialize with adjusted amount value.
Previous authorizations will be cancelled.
Cancelling Authorization Transactions
Authorization transactions can be cancelled by either calling transactionRequestAction with CANCEL action or by applying gift card to another checkout.
Charging Transactions
When order gets confirmed Saleor attempts to charge funds from gift cards. If gift card has less funds than authorization transaction was initialized for the charge attempt will fail.
Refunding Charge Transactions
For information about refunding charge transactions refer to Refunds.
Legacy using Gift Cards in Checkout
Applying Gift Cards
To use a gift card in checkout, run the checkoutAddPromoCode mutation with the gift card code.
Tax Handling
Gift cards are applied to the checkout total after tax calculation:
- First, Saleor calculates all taxes for the order
- Then, the gift card amount is subtracted from the gross total price
- The net amount and tax amount are adjusted proportionally
Multiple Gift Cards
When multiple gift cards are used:
- Saleor will always try to use the full amount from each gift card
- The system processes gift cards in the order they were added to the checkout
- If the checkout total is less than the gift card amount, only the necessary portion will be used
- The remaining balance stays on the gift card for future use
Balance Changes
Gift card balances are only updated after the order is completed:
- Adding card to the checkout does not modify the card balance
- Used amount will be deducted during checkout completion
- If an order is cancelled, the gift card balance is not restored
- You can restore current balance using
giftCardUpdate - If you used Transaction API for applying gift card you can also refund gift card transactions
- You can restore current balance using
Returns and Refunds
If a customer requests a return for a gift card product (i.e., the gift card code has not yet been used), you can handle the process manually:
- Refund the payment through your payment gateway
- Deactivate the associated gift card in the Saleor dashboard to prevent future use