---
title: "Payment-linked loyalty program"
description: "Offer a loyalty program without a separate loyalty card or app."
url: "https://docs.adyen.com/unified-commerce/loyalty-program/payment-linked-loyalty"
source_url: "https://docs.adyen.com/unified-commerce/loyalty-program/payment-linked-loyalty.md"
canonical: "https://docs.adyen.com/unified-commerce/loyalty-program/payment-linked-loyalty"
last_modified: "2024-10-01T17:11:00+02:00"
language: "en"
---

# Payment-linked loyalty program

Offer a loyalty program without a separate loyalty card or app.

[View source](/unified-commerce/loyalty-program/payment-linked-loyalty.md)

You can use customer recognition to make your existing loyalty program more frictionless for your customers by removing the need for a traditional loyalty card or app. In this tutorial, we'll explain how you can link your loyalty system to their customer profile. When they make a payment in your online or physical store, you can automatically recognize them, and award them with points, discounts, or a reward.

When you offer a payment-linked loyalty, you also give your customers an extra incentive to provide you their contact details, which you can also use to [create a customer profile](/unified-commerce/loyalty-program/create-profiles).

## Requirements

To use payment-linked loyalty, make sure that:

1. You can already [create customer profiles](/unified-commerce/loyalty-program/create-profiles) and [recognize returning customers](/unified-commerce/loyalty-program/recognize-customers) across your sales channels.
2. You have a loyalty system that keeps track of customer registration, as well as other data such as points balance and rewards eligibility.

## Online loyalty

When your customer makes a purchase in your web or in-app store, attempt to recognize them, and check whether they have already enrolled in your loyalty program.

From here, you can either ask them to register for your loyalty program, or check whether they are eligible for a loyalty reward, before continuing with the transaction.

### Step 1: Recognize customer

Before making a purchase, your customer will provide you with their contact details, such as an email address or phone number (for example, when creating or signing in to their account, or through your guest checkout).

To recognize whether this is a returning customer:

* Check whether their contact details match a `shopperEmail` that you have [stored in your customer database](/unified-commerce/loyalty-program/create-profiles#store-customer-data).

  * *If the email matches*, they are a returning customer. Proceed to the next step to get their loyalty rewards points.
  * *If the email is not your database*, proceed to step 3 to [continue the payment](#step-3-continue-with-payment). In the payment request, you might want to include other parameters to [create a customer profile for them](/unified-commerce/loyalty-program/create-profiles#create-profile-from-online-payment).

### Step 2: Request customer input

After you have determined if they are a returning customer, query your loyalty system database using the `shopperEmail` and check their loyalty program status. Next, present a relevant message in your UI:

* If they *are not* a member of your loyalty program, this message should ask them to register.
* If they *are* already a member, you could inform them how close they are to receiving a reward or, if they have enough points, ask them whether they want to redeem their reward.

### Step 3: Continue with payment

Continue with the purchase by initiating a payment. Here is how you can make a payment for a customer `shopperEmail` **john\_smith\@example.com** with a corresponding`shopperReference` **ShopperID-A16729**.

1. Make a POST [/payments](https://docs.adyen.com/api-explorer/Checkout/latest/post/payments) request.

   **Payments request**

   ```json
   {
       "amount": {
       "currency": "EUR",
       "value": 500
       },
       "reference": "YOUR_ORDER_NUMBER",
       "paymentMethod": {
           "type": "scheme",
           "encryptedCardNumber": "test_4111111111111111",
           "encryptedExpiryMonth": "test_03",
           "encryptedExpiryYear": "test_2030",
           "encryptedSecurityCode": "test_737"
       },
       "shopperReference": "ShopperID-A16729",
       "returnUrl": "https://your-company.example.com/...",
       "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
   }
   ```

   The response includes:

   * `pspReference`: our unique identifier for this payment.
   * `resultCode`: **Authorised**

   The following example shows a successful response with a PSP reference of **881468919096134D**.

   ```json
   {
       "pspReference": "881468919096134D",
       "resultCode": "Authorised"
   }
   ```

2. In your loyalty system database, update the loyalty points in your record for`shopperEmail` **john\_smith\@example.com**.

When you have set up a loyalty system for your online transactions you can do the same for in-person transactions.

## In-person loyalty

There are two flows you can use to perform payment-linked loyalty using your point-of-sale integration.

* **Synchronous**: using data you receive from Adyen before the payment is initiated.

  With this flow, you use the data that you receive from Adyen to query your loyalty system database. You then present loyalty information, such as a points balance or a personalized message, to your customer while they are making their purchase.

* **Asynchronous**: using data you receive from a webhook after the payment has been processed.

  This flow requires less integration work, but you will not be able to present real-time loyalty information to your customer. You update your loyalty system at a later time with the information that you receive from webhooks.

To implement any of these flows, select a tab below:

### Tab: Synchronous

### Synchronous in-person loyalty

By using a synchronous loyalty flow, you'll be able to present your loyal customers with information such as points balance and redeemable rewards while they are making a purchase.

We'll explain how you can use your terminal's built-in touchscreen to interact with your customers. We'll cover how you can ask them to register in your loyalty program, present customized messaging, and inform them when they are due to receive a loyalty reward.

When your customer makes a purchase at the point of sale, check whether they are registered in your loyalty program. From here, you can either ask them to register, or check whether they are eligible for a loyalty reward, before continuing with the transaction.

#### Step 1: Recognize customer

To determine whether your customer is a member of your loyalty program, attempt to recognize them with a card acquisition request.

When the customer makes a purchase at the point of sale:

1. Make a card acquisition request to [recognize the customer](/unified-commerce/loyalty-program/recognize-customers#recognize-returning-customers-in-store).

   The example below shows a card acquisition request for a customer who is making a **EUR 10.99** purchase.

   **Card acquisition request**

   ```json
   {
       "SaleToPOIRequest": {
           "MessageHeader":{
               "ProtocolVersion":"3.0",
               "MessageClass":"Service",
               "MessageCategory":"CardAcquisition",
               "MessageType":"Request",
               "SaleID":"POSSystemID12345",
               "ServiceID":"0207111104",
               "POIID":"V400m-324688179"
           },
           "CardAcquisitionRequest": {
               "SaleData": {
                   "SaleTransactionID": {
                       "TransactionID": "15890",
                       "TimeStamp": "2019-12-04T12:02:49.000Z"
                   },
               },
               "CardAcquisitionTransaction": {
                   "TotalAmount": 10.99
               }
           }
       }
   }
   ```

   You receive a response that includes an `AdditionalResponse` object, with a base64-encoded string that you need to decode to get a JSON object, or a string of form-encoded key-value pairs. In our examples, we use form-encoded key-value pairs.

   **Card acquisition response**

   ```json
   {
       "SaleToPOIResponse": {
           "CardAcquisitionResponse": {
               "POIData": {
                   "POITransactionID": {
                       "TimeStamp": "2019-12-04T12:02:49.000Z",
                       "TransactionID": "4rVu001575460969123"
                   },
                   "POIReconciliationID": "1000"
               },
               "SaleData": {
                   "SaleTransactionID": {
                       "TimeStamp": "2019-12-04T12:02:49.000Z",
                       "TransactionID": "15890"
                   }
               },
               "PaymentInstrumentData": {...},
               "Response": {
                   "Result": "Success",
                   "AdditionalResponse":"...alias=M469509594859802..."
               }
           },
           "MessageHeader": {...}
       }
   }
   ```

2. Check if the `AdditionalResponse` object contains the `alias` of the shopper's card. You need the `alias` to identify the shopper in your database.

3. Query your loyalty system database using the `alias` to identify the shopper in your database. Get information about whether the customer has already registered in your loyalty program, how many points they have, and if they are eligible for a reward.

#### Step 2: Request customer input

After you have determined if they are a new or returning customer, present a relevant message on the terminal screen:

* If the customer *is not* a member of your loyalty program, you can [ask them to register](#register-loyalty-member), and collect their email address if you do not have it yet.
* If the customer *is* a member, and is eligible for a reward, you can [ask them whether they want to redeem this reward](#redeem-loyalty-reward).
* If the customer *is* a loyalty member but *is not yet* eligible for a reward, [continue with the payment](#continue-payment-sync).

##### Register loyalty member

If your customer is not a member of your loyalty program, you can register them directly from your Adyen-supplied payment terminal.

When you register a new loyalty member, we recommend collecting their email address. This makes it easier for you to link their online and in-person loyalty, as well as send them email updates. You can also use this email address to [send them an e-receipt](/unified-commerce/digital-receipts) for their in-store transaction. If collecting an email address is not possible, you can collect their phone number, or another unique identifier for the customer instead.

To register a customer into your loyalty scheme:

1. Make a **GetConfirmation** [input request](/point-of-sale/shopper-engagement/shopper-input) from your POS app, asking whether the customer wants to register for your loyalty program.

   The following example shows how to present **Would you like to join our loyalty program?** on the terminal display, as well as the options **Yes** and **No**.

   **GetConfirmation input request**

   ```json
   {
      "SaleToPOIRequest":{
         "MessageHeader":{
            "ProtocolVersion":"3.0",
            "MessageClass":"Service",
            "MessageCategory":"Payment",
            "MessageType":"Request",
            "ServiceID":"0207112304",
            "SaleID":"POSSystemID12345",
            "POIID":"V400m-324688179"
         },
         "InputRequest":{
            "DisplayOutput":{
               "Device":"CustomerDisplay",
               "InfoQualify":"Display",
               "OutputContent":{
                  "OutputFormat":"Text",
                  "PredefinedContent":{
                     "ReferenceID":"GetConfirmation"
                  },
                  "OutputText":[
                     {"Text":"Welcome stranger!"},
                     {"Text":"Would you like to join our loyalty program?"},
                     {"Text":"No"},
                     {"Text":"Yes"}
                  ]
               }
            },
            "InputData":{
               "Device":"CustomerInput",
               "InfoQualify":"Input",
               "InputCommand":"GetConfirmation",
               "MaxInputTime":30
            }
         }
      }
   }
   ```

   Your message is shown on the terminal display. The customer indicates whether they would like to register.

   When they are done selecting their option, you receive the input response that contains an `Input.ConfirmedFlag`. If this is **true**, proceed to the next step to register your customer to your loyalty program. Otherwise, you can continue [processing the transaction](#step-3-continue-with-payment).

**GetConfirmation input response**

```json
{
   "SaleToPOIRequest":{
	      "InputResponse": {
	         "InputResult": {
	            "Device": "CustomerInput",
	            "InfoQualify": "Input",
	            "Response": {
	               "Result": "Success",
	               "AdditionalResponse": "..."
	            },
	            "Input": {
	               "ConfirmedFlag": true,
	               "InputCommand": "GetConfirmation"
	            }
	         },
	         "OutputResult": {
	            "Device": "CustomerDisplay",
	            "InfoQualify": "Display",
	            "Response": {
	               "Result": "Success"
	            }
	         }
      },
	      "MessageHeader": {...}
   }
}
```

3. If the customer indicated that they would like to register, and you do not already have their email address, make a **GetText** [input request](/point-of-sale/shopper-engagement/shopper-input) from your POS app. This should ask the customer to enter their email address.

   The example **GetText** request below would present the message **Enter your email address** on the terminal display. An on-screen keyboard also appears on the terminal.

   **GetText input request**

   ```json
   	{
   	   "SaleToPOIRequest": {
   	      "MessageHeader": {
   			 "ProtocolVersion":"3.0",
   			 "MessageClass":"Service",
   			 "MessageCategory":"Payment",
   			 "MessageType":"Request",
   			 "SaleID":"POSSystemID12345",
   			 "ServiceID":"0207112311",
   			 "POIID":"V400m-324688179"
   		  },
   	      "InputRequest": {
   	         "DisplayOutput": {
   	            "Device": "CustomerDisplay",
   	            "InfoQualify": "Display",
   	            "OutputContent": {
   	               "OutputFormat": "Text",
   	               "PredefinedContent": {
   	                  "ReferenceID": "GetText"
   	               },
   	            "OutputText": [
   	               {"Text": "Enter your email address"}
   	            ]
   	         }
   	      },
   	         "InputData": {
   	            "Device": "CustomerInput",
   	            "InfoQualify": "Input",
   	            "InputCommand": "TextString",
   	            "MaxInputTime": 120,
   	            "DefaultInputString": "name@domain.com"
   	         }
   	      }
   	   }
   	}
   ```

   The customer enters their email address on the terminal. When they are done typing in their email address, you receive an input response, with the customer's email address provided in the `Input.TextInput`.

   The example below shows what this response would look like if the customer entered the email address **john.smith\@example.com**.

   **GetText input response**

   ```json
   	{
   	  "SaleToPOIResponse": {
   	    "InputResponse": {
   	      "InputResult": {
   	        "Device":"CustomerInput",
   	        "InfoQualify":"Input",
   	        ...
   	        },
   	        "Input": {
   	          "TextInput":"john.smith@example.com",
   	          "InputCommand":"TextString"
   	        }
   	      },
   	      "OutputResult": {
   	        "Device":"CustomerDisplay",
   	        "InfoQualify":"Display",
   	        "Response": {
   	          "Result":"Success"
   	        }
   	      }
   	    },
   	  "MessageHeader": {...}
   	  }
   	}
   ```

4. Get the email address and include it when you [continue with the payment](#step-3-continue-with-payment).

   As a courtesy, you may want to send an email to your customer, confirming their registration in your loyalty program and explaining how it works.

##### Redeem loyalty reward

If your customer has earned a loyalty reward, you can use your Adyen-supplied payment terminal to inform them and give them the option to redeem their reward. If the customer agrees to redeem their reward, you can then adjust the value of the transaction before you make a payment.

To ask if a customer wants to redeem their loyalty points:

1. Make a **GetConfirmation** [input request](/point-of-sale/shopper-engagement/shopper-input), to ask your customer whether they would like to redeem their loyalty points with this transaction.

   The following example shows how to present a prompt for a free coffee on the terminal display, asking the customer whether they would like to redeem it now.

   **GetConfirmation input request**

   ```json
   {
      "SaleToPOIRequest":{
         "MessageHeader":{
            "ProtocolVersion":"3.0",
            "MessageClass":"Service",
            "MessageCategory":"Payment",
            "MessageType":"Request",
            "ServiceID":"0207112311",
            "SaleID":"POSSystemID12345",
            "POIID":"V400m-324688179"
         },
         "InputRequest":{
            "DisplayOutput":{
               "Device":"CustomerDisplay",
               "InfoQualify":"Display",
               "OutputContent":{
                  "OutputFormat":"Text",
                  "PredefinedContent":{
                     "ReferenceID":"GetConfirmation"
                  },
                  "OutputText":[
                     {"Text":"You've earned a free coffee!"},
                     {"Text":"Would you like to have it now?"},
                     {"Text":"No"},
                     {"Text":"Yes"}
                  ]
               }
            },
            "InputData":{
               "Device":"CustomerInput",
               "InfoQualify":"Input",
               "InputCommand":"GetConfirmation",
               "MaxInputTime":30
            }
         }
      }
   }
   ```

   Your message is shown on the terminal display. The customer indicates whether they would like to redeem their loyalty points for a reward.

   When they are done selecting their option, you receive the input response that contains an `Input.ConfirmedFlag`. If this is **true**, proceed to the next step to give the reward to your customer. Otherwise, continue [processing the transaction](#step-3-continue-with-payment).

   **GetConfirmation input response**

   ```json
   {
     "SaleToPOIResponse": {
       "InputResponse": {
         "InputResult": {
           "Device": "CustomerInput",
           "InfoQualify": "Input",
           "Response": {
             "Result": "Success",
             "AdditionalResponse": "..."
           },
           "Input": {
             "ConfirmedFlag": true,
             "InputCommand": "GetConfirmation"
           }
         },
         "OutputResult": {
           "Device": "CustomerDisplay",
           "InfoQualify": "Display",
           "Response": {
             "Result": "Success"
           }
         }
       },
       "MessageHeader": {...}
     }
   }
   ```

2. When a customer indicates they want to redeem their points, your POS app should calculate the redemption as a discount or partial payment. Continue to the next step to continue with the payment for the outstanding balance.

#### Step 3: Continue with payment

Continue with the purchase by making a payment request:

1. Make a POST request from your POS app to [initiate the payment](/point-of-sale/basic-tapi-integration/make-a-payment). If you are registering a new customer for your loyalty program, also include parameters described in the [Create customer profiles](/unified-commerce/loyalty-program/create-profiles#create-profile-from-point-of-sale-payment) documentation.

   Here is how you can make a **EUR 10.99** payment for a *known* customer.

   **Terminal API request**

   ```json
   	{
   		"SaleToPOIRequest":{
   			"MessageHeader":{
   				"ProtocolVersion":"3.0",
   				"MessageClass":"Service",
   				"MessageCategory":"Payment",
   				"MessageType":"Request",
   				"SaleID":"POSSystemID12345",
   				"ServiceID":"0207111105",
   				"POIID":"V400m-324688179"
   			},
   			"PaymentRequest":{
   				"SaleData":{
   					"SaleTransactionID":{
   						"TransactionID":"15887",
   						"TimeStamp":"2019-12-04T12:02:49.000Z"
   					}
   				},
   				"PaymentTransaction":{
   					"AmountsReq":{
   						"Currency":"EUR",
   						"RequestedAmount":10.99
   					}
   				},
   				"PaymentData":{
   					"CardAcquisitionReference":{
   						"TransactionID":"oLkO001528797935000",
   						"TimeStamp":"2019-12-04T12:02:49.000Z"
   					}
   				}
   			}
   		}
   	}
   ```

   You receive a response that includes an `AdditionalResponse` object, with a base64-encoded string that you need to decode to get a JSON object, or a string of form-encoded key-value pairs. In our examples, we use form-encoded key-value pairs.

   **Payment response**

   ```json
   	{
   	  "SaleToPOIResponse":{
   	    "MessageHeader":{...},
   	    "PaymentResponse":{
   	      "POIData":{
   	        "POITransactionID":{
   	          "TransactionID": "oLkO0012498220087567.991517998212382C"
   	        },
   	        ...
   	      },
   	      "Response":{
   	        "Result":"Success",
              "AdditionalResponse":"...alias=M469509594859802..."
   	      },
   	      ...
   	    },
   	    "PaymentReceipt":{...}
   	  }
   	}
   ```

2. If the transaction is successful, update the customer's loyalty balance in your database to reflect their purchase.

You may also want to use a [`DisplayRequest` ](/point-of-sale/shopper-engagement/display-data/display-receipt/)to present a message on the terminal screen, welcoming them to your loyalty program, informing them of their points balance, or congratulating them on their loyalty reward.

### Tab: Asynchronous

### Asynchronous in-person loyalty

As a simpler way of integrating payment-linked loyalty, you may prefer to use the data you receive in webhooks. You then make all loyalty adjustments retrospectively. This is done by receiving a webhook event, plugged directly into your CRM.

This requires less integration work, but this means that you will not be able to present real-time information to your customer while they are in your store (for example, to inform them of their loyalty balance, or let them know they are due for a reward). By using this flow, you will need to figure out a way of giving the customer a way of registering for your loyalty program, and recording this in your customer database.

You need to [enable receiving the `alias`](/development-resources/webhooks/webhook-types/additional-settings) of the shopper's card in the `additionalData` of your webhook. You need the `alias` to update the loyalty points in your system for the shopper's loyalty account.

To implement an asynchronous flow:

1. Make a POST request from your POS app to [initiate the payment](/point-of-sale/basic-tapi-integration/make-a-payment). If you are creating a profile for a new customer, also include parameters described in the [Create customer profiles](/unified-commerce/loyalty-program/create-profiles#create-profile-from-point-of-sale-payment)) documentation.

   Here is how you can make a **EUR 10.99** payment for a *known* customer.

   **Terminal API request**

   ```json
   	{
   		"SaleToPOIRequest":{
   			"MessageHeader":{
   				"ProtocolVersion":"3.0",
   				"MessageClass":"Service",
   				"MessageCategory":"Payment",
   				"MessageType":"Request",
   				"SaleID":"POSSystemID12345",
   				"ServiceID":"0207111105",
   				"POIID":"V400m-324688179"
   			},
   			"PaymentRequest":{
   				"SaleData":{
   					"SaleTransactionID":{
   						"TransactionID":"15887",
   						"TimeStamp":"2019-12-04T12:02:49.000Z"
   					}
   				},
   				"PaymentTransaction":{
   					"AmountsReq":{
   						"Currency":"EUR",
   						"RequestedAmount":10.99
   					}
   				}
   			}
   		}
   	}
   ```

   If the payment was successful, you receive a payment response containing `Result` **Success**.

   **Payment response**

   ```json
   	{
   	  "SaleToPOIResponse":{
   	    "MessageHeader":{...},
   	    "PaymentResponse":{
   	      "POIData":{
   	        "POITransactionID":{
   	          "TransactionID": "oLkO0012498220087567.991517998212382C"
   	        },
   	        ...
   	      },
   	      "Response":{
   	        "Result":"Success",
   	        "AdditionalResponse":"...aliasA37317672402294..."
   	      },
   	      ...
   	    },
   	    "PaymentReceipt":{...}
   	  }
   	}
   ```

2. After the payment has been processed, Adyen sends a [webhook event](/point-of-sale/design-your-integration/notifications/standard-notifications/#standard-webhook) to your server.

   **AUTHORISATION webhook**

   ```json
   {
   "notificationItems":[
      {
         "NotificationRequestItem":{
            "additionalData":{
               ...
               "shopperInteraction":"POS",
               "alias":"A37317672402294",
            },
            "amount":{
               "currency":"EUR",
               "value":10.99
            },
             ...
            "eventCode":"AUTHORISATION",
            "merchantAccountCode":"YOUR_MERCHANT_ACCOUNT",
            "merchantReference":"YOUR_REFERENCE",
            "pspReference":"882589522806623K",
            "success":"true"
         }
      }
   ]}
   ```

3. In your loyalty system database, update the loyalty points in your record for the shopper with the `alias` from the webhook.

After you have adjusted their loyalty points, you may want to reach out to the customer (using an app, email, or other communication) to let them know their new points balance, or if they are eligible to redeem a reward.
