Learn about the LoyaltyReward object and how to use the Square Loyalty API to create and manage loyalty rewards.
Loyalty API

Manage Loyalty Rewards

A loyalty program can have one or more reward tiers that define how buyers can redeem points for discounts. While building an order, you can offer discount options to the buyer for qualifying purchases based on the point balance of their loyalty account and reward tier requirements. For information about retrieving reward tier information, see Get discount details for a reward tier.

The Loyalty API supports the following operations for working with loyalty rewards:

The following is an example LoyaltyReward object:

This example loyalty reward requires 15 points and has a REDEEMED status. The following fields represent key attributes of a loyalty reward:

Field
Description
statusThe reward status: ISSUED, REDEEMED, or DELETED. Rewards with a REDEEMED status also include a redeemed_at field. Both REDEEMED and DELETED are terminal states.
loyalty_account_idThe ID of the loyalty account to which the reward belongs.
reward_tier_idThe ID of the reward tier that defines the reward details.
pointsThe number of points required to claim the reward discount.

Call CreateLoyaltyReward to issue a loyalty reward when a buyer chooses to redeem points for a discount. You provide the following information in the request:

  • The ID of the loyalty account associated with the buyer. To get the loyalty account ID, call SearchLoyaltyAccounts and search by phone number or search by customer ID.

  • The ID of the corresponding reward tier.

  • If the order was created with the Orders API, the ID of the order. Integrating with the Orders API can simplify loyalty workflows.

Create Loyalty Reward
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
curl https://connect.squareupsandbox.com/v2/loyalty/rewards \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{
    "reward": {
      "loyalty_account_id": "716cefbc-3d71-4d7c-bdc8-9c7f84c2d793",
      "reward_tier_id": "46c2716e-f559-4b75-c015-764897e3c4ae0",
      "order_id": "cb9LSpDgOH3rITBaZ6eIBb9ee4F"
    },
    "idempotency_key": "{UNIQUE_KEY}"
  }'

After receiving the request, Square does the following:

  • Removes the required points from the loyalty account balance and holds them in reserve until the reward is redeemed or deleted.

  • Generates a searchable loyalty event.

Did you know?

You can show buyers a preview of the discount before creating the reward. For more information, see Deferred reward creation.

The following is an example response, which includes the points required to redeem the reward:

The following considerations apply when creating loyalty rewards:

  • Your integration with the Orders API determines whether Square updates the order or whether it is your responsibility to do so:

    • If an order ID was specified in the CreateLoyaltyReward request, Square attaches the reward to the order, applies the corresponding discounts to qualifying line items, and adjusts the discount and total amounts accordingly.

    • If no order ID was specified, you must apply all appropriate discounts to the order.

  • The Orders API allows you to add items and rewards to an order in any sequence. If adding a reward first, you should verify that the discounted item is part of the order. For example, if the reward gives the buyer a free coffee, make sure the order includes a coffee.

  • If an order ID was specified when creating the reward but the item is not included in the order, Square deletes the reward after the order is paid and returns the points to the buyer's loyalty account.

  • The steps required to redeem the reward and manage the order also depend on whether you specified the order ID in your CreateLoyaltyReward request. If you use the Orders API to manage orders, Square handles most of the remaining workflow. For more information, see Managing the reward state.

If your application does not integrate with the Orders API, call RedeemLoyaltyReward to redeem the reward. The location_id provided in the request must reference a participating location in the loyalty program.

Note

If your application integrates with the Orders API, Square calls this endpoint automatically after the order is paid. For more information, see Managing the reward state.

Redeem Loyalty Reward
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
curl https://connect.squareupsandbox.com/v2/loyalty/rewards/{reward_id}/redeem \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{
    "location_id": "MK34ENDNWY03R",
    "idempotency_key": "{UNIQUE_KEY}"
  }'

After receiving the request, Square does the following:

  • Permanently removes the points from the loyalty account balance.

  • Sets the reward to the REDEEMED terminal state.

  • Generates a searchable loyalty event.

The following is an example response, which contains the generated loyalty event:

Call RetrieveLoyaltyReward to retrieve a loyalty reward by the reward ID.

Retrieve Loyalty Reward
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareupsandbox.com/v2/loyalty/rewards/{reward_id} \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json'

The following is an example response:

If the reward cannot be found, Square returns a 404 NOT_FOUND error.

Call SearchLoyaltyRewards to list loyalty rewards, optionally filtered for a loyalty account or reward status.

Search Loyalty Rewards
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
curl https://connect.squareupsandbox.com/v2/loyalty/rewards/search \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "loyalty_account_id": "716cefbc-3d71-4d7c-bdc8-9c7f84c2d793",
      "status": "REDEEMED"
    }
  }'

The following is an example response:

Results are sorted by the updated_at timestamp in descending order. If no results are found, the response contains an empty object:

Call DeleteLoyaltyReward to delete a reward that was issued but not redeemed.

Delete Loyalty Reward
  • 1
  • 2
  • 3
  • 4
  • 5
curl https://connect.squareupsandbox.com/v2/loyalty/rewards/{reward_id} \
  -X DELETE \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json'

After receiving the request, Square does the following:

  • If an order ID was specified when the reward was created, updates the order by removing the reward and related discounts.

  • Returns the reserved points to the loyalty account.

  • Sets the reward to the DELETED terminal state.

  • Generates a searchable loyalty event.

If successful, the response contains an empty object:

A deleted reward can still be retrieved.

A loyalty reward can be in one of the following states:

  • ISSUED. The initial state of a reward. When a reward is created, the points required to redeem the reward are removed from the loyalty account and held in reserve until the reward is redeemed or deleted.

  • REDEEMED. The reward was redeemed. When a reward is redeemed, the reserved points are permanently removed from the loyalty account.

  • DELETED. The reward was deleted. When a reward is deleted, the reserved points are returned to the loyalty account.

Note

REDEEMED and DELETED are terminal states. You cannot delete a redeemed reward in order to return points to a loyalty account. If you need to manually adjust the point balance of a loyalty account, call AdjustLoyaltyPoints.

The following common workflows can cause rewards to move from ISSUED to the REDEEMED or DELETED state. Your responsibility depends on whether a Square order ID was specified when creating the reward.

  • Order ID specified: Square sets the status to REDEEMED.

  • No order ID specified: You must call RedeemLoyaltyReward, which sets the status to REDEEMED.

  • Order ID specified: Square sets the status to DELETED.

  • No order ID specified: You must call DeleteLoyaltyReward, which sets the status to DELETED.

An example scenario for this workflow is when a buyer removes a discounted item from the order before paying for the order.

You must call DeleteLoyaltyReward, which sets the status to DELETED.

  • Order ID specified: Square removes the discount from the order and updates the order amount.

  • No order ID specified: You must also update the order appropriately.

For abandoned orders, you can determine the appropriate amount of time to wait before deleting dangling rewards, but it is your responsibility to clean them up. Otherwise, they remain in the ISSUED state and the reserved points cannot be used for other purchases.

Showing buyers a preview of the discount before creating the reward might help avoid creating dangling rewards. For more information, see Deferred reward creation.

Note

The operations involved in changing the reward state run asynchronously, so changes might not be immediately visible if you call RetrieveLoyaltyReward to retrieve the reward.

The following high-level steps describe how to get discount details and product information that correspond to the reward tiers in a loyalty program:

Step 1: Get the reward tiers for the loyalty program. Call RetrieveLoyaltyProgram in the Loyalty API. Then, check whether the loyalty account balance has enough points to qualify for a reward tier.

Step 2: Get the discount details for the reward tier. Call RetrieveCatalogObject in the Catalog API to get the PRICING_RULE, DISCOUNT, and PRODUCT_SET catalog objects that define the discount for each qualifying reward tier. You must retrieve these objects at a specific catalog version.

Step 3: Get current product information. Call BatchRetrieveCatalogObjects in the Catalog API to get the CATEGORY and ITEM_VARIATION catalog objects that the discount applies to. This step applies to CATEGORY and ITEM_VARIATION scopes only and ensures that you show the most recent category or item information to the buyer.

To get the reward tiers for a loyalty program, call the RetrieveLoyaltyProgram endpoint.

Retrieve Loyalty Program
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareupsandbox.com/v2/loyalty/programs/main \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json'

The following is an excerpt of a RetrieveLoyaltyProgram response. The reward_tiers field contains a list of LoyaltyProgramRewardTier objects that represent the reward tiers in the loyalty program.

Each reward tier in the response contains the following key fields:

  • id. The reward tier ID that you use to create a loyalty reward for a buyer.

  • points. The number of points that must be redeemed to claim the reward.

  • name. The seller-defined name for the reward tier.

  • pricing_rule_reference. The specific version of a PRICING_RULE catalog object that defines the discount details for the reward tier.

Note

The RetrieveLoyaltyProgram response currently includes the deprecated definition field, which is replaced by the pricing_rule_reference field. You should use pricing_rule_reference.

To get the discount details for a reward tier, call the RetrieveCatalogObject endpoint in the Catalog API. You must retrieve these objects at a specific catalog version. The request must:

  • Include the object_id and catalog_version from the corresponding pricing_rule_reference field.

  • Set include_related_objects to true to return all catalog objects that are part of the discount definition.

Retrieve Catalog Object
  • 1
  • 2
  • 3
  • 4
curl https://connect.squareupsandbox.com/v2/catalog/object/74C4JSHESNLTB2A7ITO5HO6F?include_related_objects=true&catalog_version=1605486402527 \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json'

The following table describes where you can find discount details in the PRICING_RULE, DISCOUNT, and PRODUCT_SET catalog objects from the response:

Discount propertyCatalog API mapping
Type of discount offered by the reward tierThe discount_data.discount_type field of the DISCOUNT catalog object.

Valid values are FIXED_AMOUNT or FIXED_PERCENTAGE.
Fixed percentage of a FIXED_PERCENTAGE discountThe discount_data.percentage field of the DISCOUNT catalog object.

This value is a string representation of a decimal number. For example, a 7.25% discount is represented as "7.25".
Maximum money amount of a FIXED_PERCENTAGE discountThe discount_data.maximum_amount_money field of the DISCOUNT catalog object.

Optional. This field is a Money object, which specifies amount using the smallest denomination.
Fixed money amount of a FIXED_AMOUNT discountThe discount_data.amount_money field of the DISCOUNT catalog object.

This field is a Money object, which specifies amount using the smallest denomination.
Scope of the rewardThe discount_target_scope field of the PRICING_RULE catalog object and the product_set_data field of the PRODUCT_SET catalog object. You can determine which items the discount applies to, as follows:

If the discount applies to the entire order:
discount_target_scope is WHOLE_PURCHASE.
product_set_data contains "all_products": true.

If the discount applies to specific categories of items:
discount_target_scope is LINE_ITEM.
product_set_data contains a product_ids_any field that references one or more CATEGORY catalog objects.

If the discount applies to specific items:
discount_target_scope is LINE_ITEM.
product_set_data contains a product_ids_any field that references one or more ITEM_VARIATION catalog objects.

The following are example RetrieveCatalogObject responses for the different scopes.

Example response for the order scope (whole purchase)

The following example represents a "$10.00 Off Entire Order" reward. It specifies a FIXED_AMOUNT discount of $10.00.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
{
  "object": {
    "type": "PRICING_RULE",
    "id": "L63DXGEYPJJTAM5JBX32ZBR5",
    "updated_at": "2020-12-16T22:48:32.75Z",
    "version": 1602888512750,
    "is_deleted": false,
    "present_at_all_locations": true,
    "pricing_rule_data": {
      "discount_id": "ZSWOAGU2E75BO7OI33AFIUMU",
      "match_products_id": "UHB65AGFKMS2IYVA7KHXMDYU",
      "application_mode": "ATTACHED",
      "discount_target_scope": "WHOLE_PURCHASE"     // Discount scope
    }
  },
  "related_objects": [
    {
      "type": "DISCOUNT",
      "id": "ZSWOAGU2E75BO7OI33AFIUMU",
      "updated_at": "2020-12-16T22:48:32.75Z",
      "version": 1602888512750,
      "is_deleted": false,
      "present_at_all_locations": true,
      "discount_data": {
        "name": "$10.00 Off Entire Order",
        "discount_type": "FIXED_AMOUNT",             // Discount type
        "amount_money": {                          // Discount amount
          "amount": 1000,
          "currency": "USD"
        },
        "application_method": "MANUALLY_APPLIED"
      }
    },
    {
      "type": "PRODUCT_SET",
      "id": "UHB65AGFKMS2IYVA7KHXMDYU",
      "updated_at": "2020-12-16T22:48:32.75Z",
      "version": 1602888512750,
      "is_deleted": false,
      "present_at_all_locations": true,
      "product_set_data": {
        "all_products": true              // Discount is entire order
      }
    }
  ]
}

Example response for the category scope

The following example represents a "50% Off One Hot Drink" reward. It specifies a FIXED_PERCENTAGE discount of 50.0 with a maximum discount amount of $2.75. It also specifies the category (hot drinks) to which the discount applies. Although this example applies to a single category, a CATEGORY reward tier can apply to multiple categories.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
{
  "object": {
    "type": "PRICING_RULE",
    "id": "74C4JSHESNLTB2A7ITO5HO6F",
    "updated_at": "2020-12-16T00:26:42.527Z",
    "version": 1605486402527,
    "is_deleted": false,
    "present_at_all_locations": true,
    "pricing_rule_data": {
      "discount_id": "ZLSTXZUW6BJED7ZZON4QZ4F5",
      "match_products_id": "RJM4MYXSBWZICCRS4N2B63QV",
      "application_mode": "ATTACHED",
      "discount_target_scope": "LINE_ITEM",         // Discount scope
      "max_applications_per_attachment": 1
    }
  },
  "related_objects": [
    {
      "type": "DISCOUNT",
      "id": "ZLSTXZUW6BJED7ZZON4QZ4F5",
      "updated_at": "2020-12-16T00:26:42.527Z",
      "version": 1605486402527,
      "is_deleted": false,
      "present_at_all_locations": true,
      "discount_data": {
        "name": "50% Off One Hot Drink",
        "discount_type": "FIXED_PERCENTAGE",         // Discount type
        "percentage": "50.0",                  // Discount percentage
        "application_method": "MANUALLY_APPLIED",
        "maximum_amount_money": {     // Optional max discount amount
          "amount": 275,
          "currency": "USD"
        }
      }
    },
    {
      "type": "PRODUCT_SET",
      "id": "RJM4MYXSBWZICCRS4N2B63QV",
      "updated_at": "2020-12-16T00:26:42.527Z",
      "version": 1605486402527,
      "is_deleted": false,
      "present_at_all_locations": true,
      "product_set_data": {
        "product_ids_any": [         // List of discounted categories
          "TWCJXQJZMIAJJ3MQJNCWLCQG"
        ],
        "quantity_exact": 1
      }
    },
    {
      "type": "CATEGORY",                      // Discounted category
      "id": "TWCJXQJZMIAJJ3MQJNCWLCQG",
      ...
    }
  ]
}

Example response for the item variation scope

The following example represents a "Free Latte or Cappuccino" reward. It specifies a FIXED_PERCENTAGE discount of 100.0, which represents a free item. It also specifies two item variations (latte and cappuccino) to which the discount applies.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
{
  "object": {
    "type": "PRICING_RULE",
    "id": "AZH2XITJVQQTYSWSOEXIW57Z",
    "updated_at": "2020-12-08T21:01:37.385Z",
    "version": 1607461297385,
    "is_deleted": false,
    "present_at_all_locations": true,
    "pricing_rule_data": {
      "discount_id": "2PS6ILT65FVO6UY227FZ4HGM",
      "match_products_id": "P35KAELYZUVV7YHR3DLCWRJN",
      "application_mode": "ATTACHED",
      "discount_target_scope": "LINE_ITEM",         // Discount scope
      "max_applications_per_attachment": 1
    }
  },
  "related_objects": [
    {
      "type": "DISCOUNT",
      "id": "2PS6ILT65FVO6UY227FZ4HGM",
      "updated_at": "2020-12-08T21:01:37.385Z",
      "version": 1607461297385,
      "is_deleted": false,
      "present_at_all_locations": true,
      "discount_data": {
        "name": "Free Latte or Cappuccino",
        "discount_type": "FIXED_PERCENTAGE",         // Discount type
        "percentage": "100.0",                 // Discount percentage
        "application_method": "MANUALLY_APPLIED"
      }
    },
    {
      "type": "PRODUCT_SET",
      "id": "P35KAELYZUVV7YHR3DLCWRJN",
      "updated_at": "2020-12-08T21:01:37.385Z",
      "version": 1607461297385,
      "is_deleted": false,
      "present_at_all_locations": true,
      "product_set_data": {
        "product_ids_any": [              // List of discounted items
          "QBIAVB2BWSPT2PYLPNAFJZ36",
          "MHXTR5VRKLXN767RCBTNB7YJ"
        ],
        "quantity_exact": 1
      }
    },
    {
      "type": "ITEM_VARIATION",                  // Discounted item 1
      "id": "QBIAVB2BWSPT2PYLPNAFJZ36",
      ...
    },
    {
      "type": "ITEM_VARIATION",                  // Discounted item 2
      "id": "MHXTR5VRKLXN767RCBTNB7YJ",
      ...
    }
  ]
} 

The following considerations apply to reward tier discount integrations:

  • Developers cannot use Square APIs to manage loyalty programs or reward tiers. To ensure that the discount details for a reward tier cannot be changed using the Catalog API, Square pins the corresponding pricing rule to a PRICING_RULE catalog object at a specific catalog version.

    When a seller updates the reward tier in the Seller Dashboard or Point of Sale application, a new pricing rule is created.

  • The Loyalty API does not use all fields in the PRICING_RULE, DISCOUNT, and PRODUCT_SET catalog objects. You can ignore fields that are not listed in the Catalog API mapping table, such as application_mode, max_applications_per_attachment, and application_method.

  • You should use the RetrieveCatalogObject endpoint to get discount details for a reward tier. Although the BatchRetrieveCatalogObject endpoint can also return catalog objects at a specific version, a single call might not return all pricing rules for a loyalty program because the corresponding PRICING_RULE catalog objects might belong to different versions.

To get the current product information for the catalog objects that are eligible for the discount, call the BatchRetrieveCatalogObjects or RetrieveCatalogObject endpoint in the Catalog API. This step ensures that you retrieve all updates made since the catalog version specified in the previous request, such as changes to an item's price.

Note

This step applies to CATEGORY and ITEM_VARIATION scopes; it does not apply to ORDER scopes. Depending on your application flow, you might have already retrieved the most current category or item information and can skip this step.

For this call, the request should:

  • Include the IDs from the product_set_data.product_ids_any field of the PRODUCT_SET catalog object from the previous request.

  • Not include the catalog_version field.

Batch Retrieve Catalog Objects
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
curl https://connect.squareupsandbox.com/v2/catalog/batch-retrieve \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{
    "object_ids": [
      "QBIAVB2BWSPT2PYLPNAFJZ36",
      "MHXTR5VRKLXN767RCBTNB7YJ"
    ]
  }'

In your application flow, you can show buyers a preview of how a loyalty reward would affect a purchase before you create the reward. Buyers can use this preview to decide whether they want to redeem the points.

By deferring reward creation until the buyer completes the order, you can avoid locking reward points prematurely. When a reward is created, the required points are removed from the loyalty account. The points are held in reserve and cannot be used for discounts on other purchases. For more information, see Managing the reward state.

For example, consider the following eCommerce checkout scenarios.

  • Window shopping. Buyers can add items to the cart and apply available discounts to see the effect on purchase price. They might keep the cart open for a long time without paying for it.

  • Abandoned carts. Buyers might never pay for items they added to the cart.

Both scenarios illustrate the benefit of deferring reward creation until the buyer completes the order. In such scenarios, you can call CalculateOrder in the Orders API to create a copy of an order with the specific rewards applied. Then, you can show the buyer the effect of applying the discounts. Later, when the buyer is ready to make a purchase, you can call CreateLoyaltyReward to create a reward.

The following example CalculateOrder request calculates the amounts for a non-catalog item order.

Calculate Order
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
curl https://connect.squareupsandbox.com/v2/orders/calculate \
  -X POST \
  -H 'Square-Version: 2023-05-17' \
  -H 'Authorization: Bearer {ACCESS_TOKEN}' \
  -H 'Content-Type: application/json' \
  -d '{
    "order": {
      "line_items": [
        {
          "name": "Unisex Poncho",
          "quantity": "1",
          "base_price_money": {
            "amount": 4200,
            "currency": "USD"
          }
        }
      ],
      "location_id": "S8GWD5R9QB376"
    },
    "proposed_rewards": [
      {
        "id": "some-random-id",
        "reward_tier_id": "b525f003-47ea-43aa-bb18-6d12Ca04c73b"
      }
    ]
  }'

For the order object in the request body, you can provide an existing order or a preview order that is not yet created:

  • Existing order. If you know the order ID, you can call RetrieveOrder to retrieve the order and pass the entire Order object.

  • Preview order. While you are building an order, you can pass an Order object that does not contain an order ID, as shown in the preceding example. Use the same object that you would send to the CreateOrder endpoint.

For the proposed_rewards field, provide the following:

  • reward_tier_id. The ID of the reward tier from the loyalty program.

  • id. A random string that serves as the ID for the simulated reward.

The following is an example response that provides a preview of the order with the applied discount.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
{
  "order": {
    "location_id": "S8GWD5R9QB376",
    "line_items": [
      {
        "uid": "HFROFMx2MckcvMe7pkU23",
        "quantity": "1",
        "name": "Unisex Poncho",
        "base_price_money": {
          "amount": 4200,
          "currency": "USD"
        },
        "gross_sales_money": {
          "amount": 4200,
          "currency": "USD"
        },
        "total_tax_money": {
          "amount": 0,
          "currency": "USD"
        },
        "total_discount_money": {
          "amount": 420,
          "currency": "USD"
        },
        "total_money": {
          "amount": 3780,
          "currency": "USD"
        },
        "variation_total_price_money": {
          "amount": 4200,
          "currency": "USD"
        },
        "applied_discounts": [
          {
            "uid": "QcKsxjGUDfNWZT8oi80ncK",
            "discount_uid": "XOzfxZ6LaeTjL66knISe4F",
            "applied_money": {
              "amount": 420,
              "currency": "USD"
            }
          }
        ]
      }
    ],
    "discounts": [
      {
        "uid": "XOzfxZ6LaeTjL66eaK4Ile",
        "catalog_object_id": "RU4L3FVPCAZ5WR2SKVPS4IZE",
        "name": "10% off entire sale (up to $50.00 off)",
        "percentage": "10.0",
        "applied_money": {
          "amount": 420,
          "currency": "USD"
        },
        "type": "FIXED_PERCENTAGE",
        "scope": "LINE_ITEM",
        "reward_ids": [
          "random-reward-id"
        ],
        "pricing_rule_id": "JNKW5IZGLA6JI2EFW2GMWTHX"
      }
    ],
    "created_at": "2021-02-27T00:12:52.857Z",
    "updated_at": "2021-02-27T00:12:52.857Z",
    "state": "OPEN",
    "version": 1,
    "total_tax_money": {
      "amount": 0,
      "currency": "USD"
    },
    "total_discount_money": {
      "amount": 420,
      "currency": "USD"
    },
    "total_tip_money": {
      "amount": 0,
      "currency": "USD"
    },
    "total_money": {
      "amount": 3780,
      "currency": "USD"
    },
    "total_service_charge_money": {
      "amount": 0,
      "currency": "USD"
    },
    "net_amounts": {
      "total_money": {
        "amount": 3780,
        "currency": "USD"
      },
      "tax_money": {
        "amount": 0,
        "currency": "USD"
      },
      "discount_money": {
        "amount": 420,
        "currency": "USD"
      },
      "tip_money": {
        "amount": 0,
        "currency": "USD"
      },
      "service_charge_money": {
        "amount": 0,
        "currency": "USD"
      }
    },
    "rewards": [
      {
        "id": "some-random-id",
        "reward_tier_id": "b525f003-47ea-43aa-bb18-6d12Ca04c73b"
      }
    ]
  }
}

Note the following fields in the response:

  • The total_discount_money, total_money, and discount_money amounts for the order and line item are updated with the applied discount.

  • The discounts field is added to the order. The discount contains information about the applied discount.

  • The applied_discounts field is added to the line item. The discount maps to the order-level discount.

  • The rewards field is added to the order. This simulated reward contains the reward and reward tier IDs you provided in the proposed_rewards field of the request.

In a simple scenario, applications might allow a buyer to redeem only one reward per order. The application flow is simple: show the rewards the buyer qualifies for (for example, a free coffee for 10 points and a free sandwich for 15 points) and let the buyer make the choice. After the buyer chooses a reward, the point balance is adjusted accordingly.

Alternatively, applications (such as Square Point of Sale) can allow buyers to redeem multiple rewards per order. To provide a consistent experience, your application can also allow multiple redemptions. In this scenario, your application must track changes to the loyalty point balance when buyers add or remove rewards, as follows:

  • If your application immediately calls CreateLoyaltyReward each time the buyer adds a reward or DeleteLoyaltyReward each time the buyer removes a reward, the loyalty account reflects the latest point balance. You can call RetrieveLoyaltyAccount to fetch the updated balance.

  • If your application uses the deferred reward creation approach as buyers add and remove rewards, the buyer's loyalty account does not accurately reflect the available point balance. In this case, your application must keep track of the available point balance on the client side. You can use the following logic to track the available point balance on the client side:

When you apply multiple rewards to an order, the Square pricing engine applies discounts so that they maximize the reward value in the buyer's favor. Therefore, discounts might be rearranged as more rewards are added to the order. For example, consider the following scenario:

  • Your cart contains one tea for $4 and one coffee for $2.

  • You offer two rewards: a Free Drink and a Free Tea.

If you first add the Free Drink reward to the order, Square discounts the tea because it is more expensive. If you then add the Free Tea reward, the Free Drink discount is moved from the tea to the coffee, so the Free Tea reward can be applied to the tea.

Note

For other considerations related to multiple redemptions, see Requirements and limitations.

We've made improvements to our docs.
Prefer the old format?