Applies to: Loyalty API | Orders API | Catalog API | Payments API
Learn how to use the Loyalty API to redeem points on a purchase.
A loyalty program includes one or more reward tiers that define the available discounts. If a buyer qualifies for a reward tier and chooses to redeem points for the discount, you create a reward.
This step follows the typical application flow that enables buyers to redeem points for a discount on a purchase. In this scenario, the buyer redeems points for a discount on their purchase and also accumulates points.
Did you know?
Check out the Sandbox 101: Loyalty API video, which shows how to set up a loyalty program in the Sandbox, create a loyalty account, and then add and redeem loyalty points using steps that are similar to this walkthrough.
The following is a high-level application flow that enables buyers to redeem loyalty points for a discount:
- Place an order for the buyer.
- Show reward tier options to the buyer. Your application uses client-side logic to determine whether the buyer qualifies for any discounts based on the loyalty point balance, the reward tier, and the order.
- If the buyer chooses to redeem points for a discount, create a reward. The Loyalty API removes the points from the loyalty account and holds them in reserve. It also applies the discount to the order.
- Take a payment for the order. The Loyalty API sets the reward status to
REDEEMED
and permanently removes the points from the loyalty account. - If the buyer earned more points from the order, add the points to the buyer's account.
Note
This application flow assumes that you use the Orders API to create and manage orders, which simplifies loyalty workflows. For more information, see Integration with the Orders API.
Call CreateOrder in the Orders API to create an order for one $10 item.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token and{UNIQUE_KEY}
with a unique idempotency key. - Replace the example value for
location_id
with your actual location ID.
Create order
The following is an example response. Note that
total_money
for the order is $10.{ "order":{ "id":"Dwirgyyg2GjIc5dBoX5rRexample", "location_id":"S8GWD5example", "line_items":[ { "uid":"to4gxMoxYW3ERQYexample", "quantity":"1", "name":"a non-catalog item #2", "base_price_money":{ "amount":1000, "currency":"USD" }, "gross_sales_money":{ "amount":1000, "currency":"USD" }, "total_tax_money":{ "amount":0, "currency":"USD" }, "total_discount_money":{ "amount":0, "currency":"USD" }, "total_money":{ "amount":1000, "currency":"USD" }, "variation_total_price_money":{ "amount":1000, "currency":"USD" } } ], "created_at":"2020-04-01T03:37:26.446Z", "updated_at":"2020-04-01T03:37:26.446Z", "state":"OPEN", "version":1, "total_tax_money":{ "amount":0, "currency":"USD" }, "total_discount_money":{ "amount":0, "currency":"USD" }, "total_tip_money":{ "amount":0, "currency":"USD" }, "total_money":{ "amount":1000, "currency":"USD" }, "total_service_charge_money":{ "amount":0, "currency":"USD" }, "net_amounts":{ "total_money":{ "amount":1000, "currency":"USD" }, "tax_money":{ "amount":0, "currency":"USD" }, "discount_money":{ "amount":0, "currency":"USD" }, "tip_money":{ "amount":0, "currency":"USD" }, "service_charge_money":{ "amount":0, "currency":"USD" } }, "source":{ "name":"Sandbox for sq0idp-MJ1Sr5Iim0hGGvAexample" } } }- Replace
Copy the order ID from the response.
To determine whether the buyer qualifies for a discount, your application does the following:
- Retrieve the loyalty account to check the point balance.
- Retrieve the loyalty program to get the available reward tiers. A reward tier defines the number of points required to claim the reward, the discount value, and what the discount applies to.
- Determine qualifying reward tiers based on the loyalty point balance, the reward tier requirements, and the order.
If the buyer qualifies for a discount, your application can offer the reward tier option to the buyer.
Call RetrieveLoyaltyAccount in the Loyalty API to retrieve the loyalty account.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token. - Replace the example account ID in the path with the loyalty account ID.
Retrieve loyalty account
The following is an example response.
{ "loyalty_account":{ "id":"716cefbc-3d71-4d7c-bdc8-9c78fexample", "mapping":{ "id":"6377d589-3f09-4f00-a0e8-56d70example", "phone_number":"+14255551111", "created_at":"2020-01-30T00:11:58Z" }, "program_id":"ba293138-8fbd-425d-860b-18ab3example", "balance":12, "lifetime_points":12, "customer_id":"REK96J96AS5AN2Y8Z4Hexample", "created_at":"2020-01-30T00:11:58Z", "updated_at":"2020-01-30T03:27:11Z", "enrolled_at":"2020-01-30T03:27:11Z" } }- Replace
From the response:
- Check the
balance
field to find the point balance for the account. This example has 12 points. - Copy the loyalty account ID.
- Check the
Call RetrieveLoyaltyProgram to retrieve the loyalty program in the seller's account. You can use the
main
keyword (as shown in the example) or provide the program ID.Replace
{ACCESS_TOKEN}
with your Sandbox access token.Retrieve loyalty program
The following is an example response, which lists the reward tiers in the loyalty program. The loyalty program used in this walkthrough offers one reward tier.
{ "program": { "id": "ba293138-8fbd-425d-860b-18ab3example", "status": "ACTIVE", "reward_tiers": [ { "id": "681fbe5c-64c6-4417-9860-a6b56example", "points": 10, "name": "10% off entire sale", "definition": { "scope": "ORDER", "discount_type": "FIXED_PERCENTAGE", "percentage_discount": "10" }, "created_at": "2020-03-29T20:23:17Z", "pricing_rule_reference": { "object_id": "NJD4FBM6LYUSPOFQDexample", "catalog_version": "08732example" } } ], "terminology": { "one": "Point", "other": "Points" }, "location_ids": [ "S8GWD5example" ], "created_at": "2020-01-28T04:32:01Z", "updated_at": "2020-03-29T20:23:18Z", "accrual_rules": [ { "accrual_type": "SPEND", "points": 1, "spend_data": { "amount_money": { "amount": 100, "currency": "USD" }, "tax_mode": "BEFORE_TAX" } } ] } }Note the number of points required to claim the reward, which is specified in the
points
field of the reward tier. This reward tier requires 10 points.Copy the following values:
- The reward tier ID.
- The object ID and catalog version from the
pricing_rule_reference
field.pricing_rule_reference
references the specific version of aPRICING_RULE
catalog object that defines the discount details for the reward tier.
Note
The RetrieveLoyaltyProgram
response currently also includes the deprecated definition
field, which is replaced by the pricing_rule_reference
field. When possible, you should use pricing_rule_reference
.
Your application can now determine whether the buyer qualifies for any discounts based on the point balance of the loyalty account, the order, and the reward tier.
Check whether the loyalty account has enough points to claim the reward. In this example, the loyalty account has a balance of 12 points, so the buyer qualifies for the reward tier. Therefore, you need to get the discount details for the reward tier.
Call RetrieveCatalogObject in the Catalog API to retrieve the
PRICING_RULE
and other catalog objects that define the discount details for the reward tier.- Replace
{ACCESS_TOKEN}
with your Sandbox access token. - Replace the example object ID and catalog version in the path with the actual values. The pricing rule is pinned to a specific catalog version, so you must specify the catalog version in the request. The request must also set the
include_related_objects
parameter totrue
.
Retrieve catalog object
Note
The
?
or&
in the endpoint URL can cause issues when running the cURL command from a terminal window. If you encounter issues, try wrapping the endpoint URL in quotation marks and resending the request.The following is an example response.
{ "object": { "type": "PRICING_RULE", "id": "NJD4FBM6LYUSPOFQDexample", "updated_at": "2020-12-16T22:48:32.75Z", "version": 08732example, "is_deleted": false, "present_at_all_locations": true, "pricing_rule_data": { "discount_id": "DE6EOJ2H7E62Q4BZVexample", "match_products_id": "AWD37UK4SHTA42NK7example", "application_mode": "ATTACHED", "discount_target_scope": "WHOLE_PURCHASE" } }, "related_objects": [ { "type": "DISCOUNT", "id": "DE6EOJ2H7E62Q4BZVexample", "updated_at": "2020-12-16T22:48:32.75Z", "version": 08732example, "is_deleted": false, "present_at_all_locations": true, "discount_data": { "name": "10% off entire sale", "discount_type": "FIXED_PERCENTAGE", "percentage": "10.0", "application_method": "MANUALLY_APPLIED" } }, { "type": "PRODUCT_SET", "id": "AWD37UK4SHTA42NK7example", "updated_at": "2020-12-16T22:48:32.75Z", "version": 08732example, "is_deleted": false, "present_at_all_locations": true, "product_set_data": { "all_products": true } } ] }- Replace
Determine the discount scope and value. The reward tier in this walkthrough offers 10% off the entire sale. You can find this information in the
PRICING_RULE
,DISCOUNT
, andPRODUCT_SET
objects.The following settings indicate that the scope is the entire sale:
- In the
PRICING_RULE
object, thepricing_rule_data.discount_target_scope
field isWHOLE_PURCHASE
. - In the
PRODUCT_SET
object, theproduct_set_data.all_products
field is present and set totrue
.
The following settings indicate that the value is 10%:
- In the
DISCOUNT
object, thediscount_data.discount_type
field isFIXED_PERCENTAGE
. - In the
DISCOUNT
object, thediscount_data.percentage
is10.0
. Note thatdiscount_data.maximum_amount_money
isn't present, so no maximum discount amount is defined.
Because the discount scope is
WHOLE_PURCHASE
, you have all the discount details you need for this reward. For more information, see Getting discount details for a reward tier.- In the
Your application can show the reward tier option to the buyer. For this walkthrough, assume that the buyer chooses to claim the reward.
Call CreateLoyaltyReward in the Loyalty API to create a reward and apply the discount to the order.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token and{UNIQUE_KEY}
with a unique idempotency key. - Replace the example values for
loyalty_account_id
,reward_tier_id
, andorder_id
with the actual values.
Create loyalty reward
The following is an example response.
{ "reward":{ "id":"45d8d201-50b9-3dc8-97f3-ff5d0example", "status":"ISSUED", "loyalty_account_id":"716cefbc-3d71-4d7c-bdc8-9c78fexample", "reward_tier_id":"681fbe5c-64c6-4417-9860-a6b56example", "points":10, "order_id":"Dwirgyyg2GjIc5dBoX5rRexample", "created_at":"2020-05-07T23:32:19Z", "updated_at":"2020-05-07T23:32:19Z" } }When a reward is created, the Loyalty API does the following:
Removes the points required by the reward tier from the buyer's loyalty account. These points are held in reserve and cannot be redeemed for any other reward unless this reward is deleted. For more information, see Redeem a loyalty reward.
Updates the order with reward and discount information. You can see these updates in the next step. The Loyalty API performs this step only if the order was created using the Orders API and the order ID was specified in the
CreateLoyaltyReward
request.
- Replace
Did you know?
You might prefer to show the buyer a preview of the discounted order before you create a reward. For more information, see Deferred reward creation.
Call RetrieveOrder to retrieve the updated order amounts to show to the buyer.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token. - Replace the example order ID with the actual value.
Retrieve order
The following in an example response:
{ "order": { "id": "Dwirgyyg2GjIc5dBoX5rRexample", "location_id": "S8GWD5example", "line_items": [ { "uid": "to4gxMoxYW3ERQYexample", "quantity": "1", "name": "a non-catalog item #2", "base_price_money": { "amount": 1000, "currency": "USD" }, "gross_sales_money": { "amount": 1000, "currency": "USD" }, "total_tax_money": { "amount": 0, "currency": "USD" }, "total_discount_money": { "amount": 100, "currency": "USD" }, "total_money": { "amount": 900, "currency": "USD" }, "variation_total_price_money": { "amount": 1000, "currency": "USD" }, "applied_discounts": [ { "uid": "eOdEOTVqcLD1ab3example", "discount_uid": "pFv6PyLSsBkLiGVexample", "applied_money": { "amount": 100, "currency": "USD" } } ] } ], "discounts": [ { "uid": "pFv6PyLSsBkLiGVexample", "catalog_object_id": "DE6EOJ2H7E62Q4BZVexample", "name": "10% off entire sale", "percentage": "10.0", "applied_money": { "amount": 100, "currency": "USD" }, "type": "FIXED_PERCENTAGE", "scope": "LINE_ITEM", "reward_ids": [ "45d8d201-50b9-3dc8-97f3-ff5d0example" ], "pricing_rule_id": "NJD4FBM6LYUSPOFQDexample" } ], "created_at": "2020-05-12T22:41:08.475Z", "updated_at": "2020-05-12T22:48:39.118Z", "state": "OPEN", "version": 2, "total_tax_money": { "amount": 0, "currency": "USD" }, "total_discount_money": { "amount": 100, "currency": "USD" }, "total_tip_money": { "amount": 0, "currency": "USD" }, "total_money": { "amount": 900, "currency": "USD" }, "total_service_charge_money": { "amount": 0, "currency": "USD" }, "net_amounts": { "total_money": { "amount": 900, "currency": "USD" }, "tax_money": { "amount": 0, "currency": "USD" }, "discount_money": { "amount": 100, "currency": "USD" }, "tip_money": { "amount": 0, "currency": "USD" }, "service_charge_money": { "amount": 0, "currency": "USD" } }, "source": { "name": "Sandbox for sq0idp-MJ1Sr5Iim0hGGvAexample" }, "rewards": [ { "id": "45d8d201-50b9-3dc8-97f3-ff5d0example", "reward_tier_id": "681fbe5c-64c6-4417-9860-a6b56example" } ] } }The Loyalty API updates the order with reward and discount fields and amounts, as follows:
- Adds the
discounts
andrewards
fields to the order. In this example, the order contains one discount and one reward.- The discount maps to the
PRICING_RULE
andDISCOUNT
objects for the reward tier and the loyalty reward you created. - The reward maps to the reward tier and the loyalty reward you created.
- The discount maps to the
- Adds the
applied_discounts
field to qualifying line items. In this example, the line item has one applied discount, which maps to the order-level discount. - Updates the following amounts for the order and line item:
total_discount_money
shows a $1 discount amount that equals 10% of the total sale.total_money
shows a decrease from $10 to $9.
- Replace
Note
The presence of the discount indicates the reward was applied to the order. It's possible to create a reward that cannot be applied to the order. For example, you might create a reward for a free coffee, but the coffee isn't in the order and the discount cannot be applied. In this case, Square deletes the reward and returns the points to the buyer's loyalty account after the order reaches a terminal state (for example, the order is paid or canceled).
Call CreatePayment in the Payments API to take a payment of $9 for the preceding order. In this walkthrough, you provide a Sandbox payment token for the source_id
of the payment source.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token and{UNIQUE_KEY}
with a unique idempotency key. - Replace the example value for
order_id
with the order ID.
Create payment
After you pay for the order, the Loyalty API sets the loyalty reward status to REDEEMED
and permanently removes the points from the loyalty account.
Did you know?
A searchable loyalty event is generated when a reward is created, redeemed, or deleted. For more information, see Search for Balance-Changing Loyalty Events.
The buyer paid for the order and therefore qualifies for loyalty points. Call AccumulateLoyaltyPoints in the Loyalty API to add the points to the buyer's loyalty account.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token and{UNIQUE_KEY}
with a unique idempotency key. - Replace the example account ID in the path with the actual loyalty account ID.
- Replace the example values for
order_id
andlocation_id
with the actual order ID and location ID.
Accumulate loyalty points
The buyer received a 10% discount and paid $9 for the order. The loyalty program's accrual rule is "Earn one point for each dollar spent," so the buyer earns 9 points for this purchase. Because you're using the Orders API to create manage orders, you don't have to do any calculations. You provide the order ID in the AccumulateLoyaltyPoints
request and the Loyalty API computes the loyalty points using the purchase amount.
{
"event":{
"id":"efc9fc89-60e5-360a-9002-d3904example",
"type":"ACCUMULATE_POINTS",
"created_at":"2020-05-12T00:05:29Z",
"accumulate_points":{
"loyalty_program_id":"ba293138-8fbd-425d-860b-18ab3example",
"points":9,
"order_id":"Dwirgyyg2GjIc5dBoX5rRexample"
},
"loyalty_account_id":"716cefbc-3d71-4d7c-bdc8-9c78fexample",
"location_id":"S8GWD5example",
"source":"LOYALTY_API"
}
}
You can optionally call RetrieveLoyaltyAccount to see that the points were added.
- Replace
{ACCESS_TOKEN}
with your Sandbox access token. - Replace the example account ID in the path with the actual loyalty account ID.
Retrieve loyalty account