Applying Vouchers to Orders
Applying vouchers is the process of redeeming a voucher code during checkout or when creating a draft order.
Once applied, the discount is reflected in product line prices or order subtotal.
Vouchers can be combined with catalog promotions, but their behavior depends on how they were configured.
If you’re looking for details on voucher types, settings, or how to create them, see the Vouchers guide.
Apply a Voucher Code​
To apply the voucher on checkout use checkoutAddPromoCode
mutation. The discount will be visible both in the line prices and in the checkout.discount
field.
To apply the voucher on draft order use draftOrderCreate
or draftOrderUpdate
and pass voucherCode
as an argument.
Entire Order Voucher​
In the example below, the entire order voucher with a fixed discount of $5 is applied at checkout. The order consists of two lines: the first for $4 and the second for $45.
mutation {
checkoutAddPromoCode(
token: 7303902b-dda8-4357-95a0-64b83b59e2e2, promoCode: "DISCOUNT"
) {
errors {
field
message
code
}
checkout {
id
token
voucherCode
discountName
discount {
amount
}
subtotalPrice {
tax {
amount
}
gross {
amount
}
net {
amount
}
}
lines {
quantity
totalPrice {
net {
amount
}
gross {
amount
}
}
undiscountedTotalPrice {
amount
}
unitPrice {
net {
amount
}
gross {
amount
}
}
undiscountedUnitPrice {
amount
}
}
}
}
}
Here is the response:
{
"data": {
"checkoutAddPromoCode": {
"errors": [],
"checkout": {
"id": "Q2hlY2tvdXQ6OTNmMWQxZjItMjBjNC00ZWMyLTkwYzgtOThjYmEzY2YyNTU1",
"token": "93f1d1f2-20c4-4ec2-90c8-98cba3cf2555",
"voucherCode": "DISCOUNT",
"discountName": "Big order discount",
"discount": {
"amount": 5.0
},
"subtotalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 44.0
},
"net": {
"amount": 44.0
}
},
"lines": [
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 3.59
},
"gross": {
"amount": 3.59
}
},
"undiscountedTotalPrice": {
"amount": 4.0
},
"unitPrice": {
"net": {
"amount": 3.59
},
"gross": {
"amount": 3.59
}
},
"undiscountedUnitPrice": {
"amount": 4.0
}
},
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 40.41
},
"gross": {
"amount": 40.41
}
},
"undiscountedTotalPrice": {
"amount": 45.0
},
"unitPrice": {
"net": {
"amount": 40.41
},
"gross": {
"amount": 40.41
}
},
"undiscountedUnitPrice": {
"amount": 45.0
}
}
]
}
}
}
}
The discount is visible on both the checkout.discount
field and the prices in checkout.lines
.
In the first line, the totalPrice
is $0.41 less than the undiscountedTotalPrice
,
while the difference in the second line is $4.59.
The checkout.discount
is the sum of the differences between totalPrice
and undiscountedTotalPrice
of the lines.
For more complex cases, please check Examples section.
If the user applied a fixed-amount order voucher during checkout, and the order contains multiple lines, the discount will be distributed evenly in proportion to the total price of each line.
Once-Per-Order Entire Order Voucher​
If a voucher with the applyOncePerOrder
flag set to True
is used in a similar scenario,
the discount will only apply to the cheapest eligible product. In this checkout,
the cheapest eligible product is priced at $4.
Therefore, the discount will be $4 and will only appear on one line.
Refer to the response from running the same mutation as before.
The checkout.discount
is 4.0. The cheapest line's totalPrice
is 0.0,
and the undiscountedTotalPrice
is 4.0.
{
"data":{
"checkoutAddPromoCode":{
"errors":[],
"checkout":{
"id":"Q2hlY2tvdXQ6OTNmMWQxZjItMjBjNC00ZWMyLTkwYzgtOThjYmEzY2YyNTU1",
"token":"93f1d1f2-20c4-4ec2-90c8-98cba3cf2555",
"voucherCode":"DISCOUNT",
"discountName":"Big order discount",
"discount":{
"amount":4.0
},
"subtotalPrice":{
"tax":{
"amount":0.0
},
"gross":{
"amount":45.0
},
"net":{
"amount":45.0
}
},
"lines":[
{
"quantity":1,
"totalPrice":{
"net":{
"amount":0.0
},
"gross":{
"amount":0.0
}
},
"undiscountedTotalPrice":{
"amount":4.0
},
"unitPrice":{
"net":{
"amount":0.0
},
"gross":{
"amount":0.0
}
},
"undiscountedUnitPrice":{
"amount":4.0
}
},
{
"quantity":1,
"totalPrice":{
"net":{
"amount":45.0
},
"gross":{
"amount":45.0
}
},
"undiscountedTotalPrice":{
"amount":45.0
},
"unitPrice":{
"net":{
"amount":45.0
},
"gross":{
"amount":45.0
}
},
"undiscountedUnitPrice":{
"amount":45.0
}
}
]
}
}
}
}
Specific Product Voucher​
In the following example, a 10% voucher for a specific product is applied during checkout.
The discount applies to the first two lines, one for $45 and the other for $20, but not to the third line for $1.99.
The response of running the checkoutAddPromoCode
mutation with the voucher code for this discount is shown below:
{
"data": {
"checkoutAddPromoCode": {
"errors": [],
"checkout": {
"id": "Q2hlY2tvdXQ6YWJlZTQzNTEtMGZjMS00MWYzLTk1YzEtMTIyMTc4NWMwYzY2",
"token": "abee4351-0fc1-41f3-95c1-1221785c0c66",
"voucherCode": "SPECIFIC PRODUCT",
"discountName": null,
"discount": {
"amount": 6.5
},
"subtotalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 60.49
},
"net": {
"amount": 60.49
}
},
"lines": [
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 40.5
},
"gross": {
"amount": 40.5
}
},
"undiscountedTotalPrice": {
"amount": 45.0
},
"unitPrice": {
"net": {
"amount": 40.5
},
"gross": {
"amount": 40.5
}
},
"undiscountedUnitPrice": {
"amount": 45.0
}
},
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 18.0
},
"gross": {
"amount": 18.0
}
},
"undiscountedTotalPrice": {
"amount": 20.0
},
"unitPrice": {
"net": {
"amount": 18.0
},
"gross": {
"amount": 18.0
}
},
"undiscountedUnitPrice": {
"amount": 20.0
}
},
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 1.99
},
"gross": {
"amount": 1.99
}
},
"undiscountedTotalPrice": {
"amount": 1.99
},
"unitPrice": {
"net": {
"amount": 1.99
},
"gross": {
"amount": 1.99
}
},
"undiscountedUnitPrice": {
"amount": 1.99
}
}
]
}
}
}
}
As we can see, the 10% discount has been applied to the first two lines.
The total discount amount is visible in the checkout.discount
field, which is equal to
the sum of the differences between the undiscountedTotalPrice
and totalPrice
of all lines.
Once-Per-Order Specific Product Voucher​
If the voucher has the applyOncePerOrder
flag set to True
, the discount will only be applied to
the single cheapest product eligible for the discount. In the scenario described,
the discount would only be applied to the product with a price of $20, and would be visible on only one line of the order.
{
"data": {
"checkoutAddPromoCode": {
"errors": [],
"checkout": {
"id": "Q2hlY2tvdXQ6YWJlZTQzNTEtMGZjMS00MWYzLTk1YzEtMTIyMTc4NWMwYzY2",
"token": "abee4351-0fc1-41f3-95c1-1221785c0c66",
"voucherCode": "SPECIFIC PRODUCT",
"discountName": null,
"discount": {
"amount": 2.0
},
"subtotalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 64.99
},
"net": {
"amount": 64.99
}
},
"lines": [
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 45.0
},
"gross": {
"amount": 45.0
}
},
"undiscountedTotalPrice": {
"amount": 45.0
},
"unitPrice": {
"net": {
"amount": 45.0
},
"gross": {
"amount": 45.0
}
},
"undiscountedUnitPrice": {
"amount": 45.0
}
},
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 18.0
},
"gross": {
"amount": 18.0
}
},
"undiscountedTotalPrice": {
"amount": 20.0
},
"unitPrice": {
"net": {
"amount": 18.0
},
"gross": {
"amount": 18.0
}
},
"undiscountedUnitPrice": {
"amount": 20.0
}
},
{
"quantity": 1,
"totalPrice": {
"net": {
"amount": 1.99
},
"gross": {
"amount": 1.99
}
},
"undiscountedTotalPrice": {
"amount": 1.99
},
"unitPrice": {
"net": {
"amount": 1.99
},
"gross": {
"amount": 1.99
}
},
"undiscountedUnitPrice": {
"amount": 1.99
}
}
]
}
}
}
}
Here, we can see that the discount was only applied to the cheapest line included in the voucher discount.
The total checkout.discount
is $2.0 in this case. The difference between
totalPrice
and undiscountedTotalPrice
is only visible on the second line.
Shipping Voucher​
To apply a shipping voucher, the checkout must include shippable products, a provided shipping address, and a shipping method assigned.
In this example the checkout consists of one line for $100, shipping price for $20 and 50% shipping voucher. The discount affects shipping price only.
Request:
mutation AddCheckoutPromoCode($checkoutId: ID!, $promoCode: String!) {
checkoutAddPromoCode(id: $checkoutId, promoCode: $promoCode) {
checkout {
id
token
voucherCode
discountName
discount {
amount
}
totalPrice {
net {
amount
}
}
subtotalPrice {
net {
amount
}
}
shippingPrice {
net {
amount
}
}
}
}
}
{
"checkoutId": "Q2hlY2tvdXQ6ZDgwMWI3MjUtNzBmMC00NGNiLWFmNjctMmNmYjc4YmY5MTU4",
"promoCode": "code-123"
}
Response:
{
"data":{
"checkoutAddPromoCode": {
"checkout": {
"id": "Q2hlY2tvdXQ6ZDgwMWI3MjUtNzBmMC00NGNiLWFmNjctMmNmYjc4YmY5MTU4",
"token": "d801b725-70f0-44cb-af67-2cfb78bf9158",
"voucherCode": "code-123",
"discountName": "half-shipping",
"discount": {
"amount": 10.0
},
"totalPrice": {
"net": {
"amount": 110.0
}
},
"subtotalPrice": {
"net": {
"amount": 100.0
}
},
"shippingPrice": {
"net": {
"amount": 10.0
}
}
}
}
}
}
For more complex cases, please check Examples section.
Automatic Voucher Invalidation​
Vouchers applied to a checkout can be automatically removed when conditions for their validity are no longer met. This ensures that discounts are only applied when all required criteria are satisfied.
Below are examples of scenarios that trigger voucher removal.
Shipping method removal invalidates shipping voucher​
Scenario:
- Checkout has 2 lines and a shipping method assigned.
- A shipping voucher is applied.
- One checkout line is removed.
- The assigned shipping method is no longer valid for the updated checkout (e.g., weight, location, or product eligibility changes).
- The shipping method is automatically removed from the checkout.
Since the shipping method is removed, the shipping voucher is also automatically unassigned.
Before removing a line:
"checkout": {
"isShippingRequired": true,
"voucherCode": "shipping",
"deliveryMethod": {
"id": "U2hpcHBpbmdNZXRob2Q6MzE=",
"name": "ups",
},
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOmE4NWJjNDkwLTEwMjAtNDU5Zi1iYmMzLWNmZTYyYmI4Y2I1Ng==",
"quantity": 1,
"requiresShipping": true,
},
{
"id": "Q2hlY2tvdXRMaW5lOmVkMDE2YzY0LTdhZjctNGI0Ny1hYjJjLWJmMDc2NWM3MzQxNg==",
"quantity": 2,
"requiresShipping": false,
}
],
"totalPrice": {
"gross": {
"amount": 120.0
}
}
}
After removing one line (shipping method becomes invalid):
"checkout": {
"isShippingRequired": false,
"voucherCode": null, // voucher removed
"deliveryMethod": null, // shipping method removed
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOmVkMDE2YzY0LTdhZjctNGI0Ny1hYjJjLWJmMDc2NWM3MzQxNg==",
"quantity": 2,
"requiresShipping": false,
}
],
"totalPrice": {
"gross": {
"amount": 80.0
}
}
}
Subtotal change invalidates minimum spent voucher​
Scenario:
- Checkout has 2 lines and a valid shipping method assigned.
- A voucher with a minimum spent amount condition is applied.
- One line is removed from the checkout.
- The checkout subtotal drops below the voucher’s minimum requirement.
The voucher is automatically removed, but the shipping method remains assigned.
Before removing a line:
"checkout": {
"voucherCode": "minus15",
"deliveryMethod": {
"id": "U2hpcHBpbmdNZXRob2Q6MzE=",
"name": "ups",
"active": true
},
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOjBiNTQyOGUwLTY0YmQtNGZkZS05MDExLWY2ODYzZDI2MjIzYQ==",
"quantity": 1
},
{
"id": "Q2hlY2tvdXRMaW5lOjQyOWNhMzZkLTIwZTMtNDc4OS1hN2JhLTcxOTFjZDAwOGFjZg==",
"quantity": 2
}
],
"totalPrice": {
"gross": {
"amount": 112.0
}
}
}
After removing one line (subtotal below requirement):
"checkout": {
"voucherCode": null,
"deliveryMethod": {
"id": "U2hpcHBpbmdNZXRob2Q6MzE=",
"name": "ups",
"active": true
},
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOjBiNTQyOGUwLTY0YmQtNGZkZS05MDExLWY2ODYzZDI2MjIzYQ==",
"quantity": 1
}
],
"totalPrice": {
"gross": {
"amount": 50.0
}
}
}
Combining Promotions and Vouchers​
Catalogue promotions and vouchers can be combined. In this case, the voucher discount is applied to the price after the promotion discount. Let's consider an example: the checkout has two items, and the first item is on $5 fixed promotion. A percentage discount of 50% is being applied to the entire order.
Here is the checkout data before applying the voucher code (only the promotion is included in the price).
{
"data": {
"checkout": {
"id": "Q2hlY2tvdXQ6ZDdjMjY5M2MtOTU0ZS00YTM4LWJkMjQtMzM1Y2NiODk0YWMy",
"email": "admin@example.com",
"token": "d7c2693c-954e-4a38-bd24-335ccb894ac2",
"channel": {
"slug": "default-channel"
},
"voucherCode": null,
"discount": {
"amount": 0.0
},
"discountName": null,
"giftCards": [],
"totalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 65.0,
"currency": "USD",
"__typename": "Money"
},
"net": {
"amount": 65.0,
"currency": "USD",
"__typename": "Money"
},
"__typename": "TaxedMoney"
},
"subtotalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 65.0,
"currency": "USD",
"__typename": "Money"
},
"net": {
"amount": 65.0,
"currency": "USD",
"__typename": "Money"
},
"__typename": "TaxedMoney"
},
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOmNlNzJiY2IyLWJjZjYtNGQxZS04MDRmLWMwZDdjZWI2NWM3OQ==",
"quantity": 2,
"undiscountedTotalPrice": {
"amount": 40.0
},
"totalPrice": {
"gross": {
"amount": 30.0
},
"net": {
"amount": 30.0
}
},
"unitPrice": {
"net": {
"amount": 15.0
}
},
"undiscountedUnitPrice": {
"amount": 20.0
},
"variant": {
"id": "UHJvZHVjdFZhcmlhbnQ6MzQ4",
"name": "S",
"pricing": {
"price": {
"gross": {
"amount": 15.0
}
}
},
"product": {
"name": "Monospace Tee",
"chargeTaxes": false
}
}
},
{
"id": "Q2hlY2tvdXRMaW5lOjI5ZDA4Zjc2LTdlMTItNGE5OC05ZWFkLThhNzFjMDMyNGQyOQ==",
"quantity": 1,
"undiscountedTotalPrice": {
"amount": 35.0
},
"totalPrice": {
"gross": {
"amount": 35.0
},
"net": {
"amount": 35.0
}
},
"unitPrice": {
"net": {
"amount": 35.0
}
},
"undiscountedUnitPrice": {
"amount": 35.0
},
"variant": {
"id": "UHJvZHVjdFZhcmlhbnQ6MzQ2",
"name": "UHJvZHVjdFZhcmlhbnQ6MzQ2",
"pricing": {
"price": {
"gross": {
"amount": 35.0
}
}
},
"product": {
"name": "Blue Hoodie",
"chargeTaxes": false
}
}
}
]
}
}
}
As we can see the price of the first line is reduced by the promotion discount. The $5 discount is applied on each line so we have $10 total discount on the fist line.
Below is the checkout data after applying the 50% entire order voucher.
{
"data": {
"checkout": {
"id": "Q2hlY2tvdXQ6ZDdjMjY5M2MtOTU0ZS00YTM4LWJkMjQtMzM1Y2NiODk0YWMy",
"email": "admin@example.com",
"token": "d7c2693c-954e-4a38-bd24-335ccb894ac2",
"channel": {
"slug": "default-channel"
},
"voucherCode": "DISCOUNT",
"discount": {
"amount": 32.5
},
"discountName": "Big order discount",
"giftCards": [],
"totalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 32.5,
"currency": "USD",
"__typename": "Money"
},
"net": {
"amount": 32.5,
"currency": "USD",
"__typename": "Money"
},
"__typename": "TaxedMoney"
},
"subtotalPrice": {
"tax": {
"amount": 0.0
},
"gross": {
"amount": 32.5,
"currency": "USD",
"__typename": "Money"
},
"net": {
"amount": 32.5,
"currency": "USD",
"__typename": "Money"
},
"__typename": "TaxedMoney"
},
"lines": [
{
"id": "Q2hlY2tvdXRMaW5lOmNlNzJiY2IyLWJjZjYtNGQxZS04MDRmLWMwZDdjZWI2NWM3OQ==",
"quantity": 2,
"undiscountedTotalPrice": {
"amount": 40.0
},
"totalPrice": {
"gross": {
"amount": 15.0
},
"net": {
"amount": 15.0
}
},
"unitPrice": {
"net": {
"amount": 7.5
}
},
"undiscountedUnitPrice": {
"amount": 20.0
},
"variant": {
"id": "UHJvZHVjdFZhcmlhbnQ6MzQ4",
"name": "S",
"pricing": {
"price": {
"gross": {
"amount": 15.0
}
}
},
"product": {
"name": "Monospace Tee",
"chargeTaxes": false
}
}
},
{
"id": "Q2hlY2tvdXRMaW5lOjI5ZDA4Zjc2LTdlMTItNGE5OC05ZWFkLThhNzFjMDMyNGQyOQ==",
"quantity": 1,
"undiscountedTotalPrice": {
"amount": 35.0
},
"totalPrice": {
"gross": {
"amount": 17.5
},
"net": {
"amount": 17.5
}
},
"unitPrice": {
"net": {
"amount": 17.5
}
},
"undiscountedUnitPrice": {
"amount": 35.0
},
"variant": {
"id": "UHJvZHVjdFZhcmlhbnQ6MzQ2",
"name": "UHJvZHVjdFZhcmlhbnQ6MzQ2",
"pricing": {
"price": {
"gross": {
"amount": 35.0
}
}
},
"product": {
"name": "Blue Hoodie",
"chargeTaxes": false
}
}
}
]
}
}
}
As we can see, the total discount is $32.5.0.
In the first line, the difference between totalPrice
and undiscountedTotalPrice
($25)
is the total discount applied to this line, which includes both promotion and voucher discounts.
However, in the second line, the difference between those values ($17.5) comes from
the voucher discount.
To calculate the value of the applied promotion, we can sum up the line discounts and subtract
checkout.discount
. In this example, the calculation would be: ($25 + $17.5) - $32.5 = $10.
Therefore, we end up with the same value as before applying the voucher.
Completing Checkout with Vouchers​
When completing the checkout with an assigned voucher, the applied voucher discount
will be visible on the order and order line prices. Additionally, the sum of voucher
discounts will be reflected in the order.discounts
field. This behavior is consistent
across all voucher types.
The following example shows the response from the checkoutComplete
mutation for a checkout that includes two items of the same variant with a 10% voucher discount applied.
{
"data": {
"checkoutComplete": {
"order": {
"id": "T3JkZXI6NmM1MjhkNGYtZjc5YS00OGM1LTk2ZWUtYjI0M2U2ZjdmMDBm",
"status": "UNFULFILLED",
"totalCaptured": {
"amount": 113.51
},
"subtotal": {
"net": {
"amount": 33.96
},
"gross": {
"amount": 36.0
}
},
"total": {
"currency": "USD",
"net": {
"amount": 107.08
},
"gross": {
"amount": 113.51
}
},
"undiscountedTotal": {
"currency": "USD",
"net": {
"amount": 113.12
},
"gross": {
"amount": 117.51
}
},
"discounts": [
{
"name": null,
"type": "VOUCHER",
"valueType": "FIXED",
"amount": {
"amount": 4.0
}
}
],
"lines": [
{
"quantity": 2,
"totalPrice": {
"gross": {
"amount": 36.0
},
"net": {
"amount": 33.96
}
},
"unitPrice": {
"gross": {
"amount": 18.0
},
"net": {
"amount": 16.98
}
},
"undiscountedUnitPrice": {
"gross": {
"amount": 20.0
},
"net": {
"amount": 20.0
}
},
"unitDiscount": {
"amount": 2.0
}
}
]
},
"errors": []
}
}
}
The discount amount can be found in order.discounts.amount
, the value is equal to the
order.lines.unitDiscount
multiplied by the line quantity.
The discount can also be seen in the line prices - compare the undiscountedUnitPrice
and the unitPrice
.