Loyalty Integration Setup
Introduction
Third party Loyalty integrations use a combination of QR Codes and Real Time Notifications to manage rewards redemption in the Lightspeed Restaurant K-Series POS. For the moment, the Loyalty URLs, both QR Code and RTN, need to be set up manually by Lightspeed Support
Setup
In order to start testing, the integrator must provide an endpoint where the contents of the scanned QR Code can be sent. This QR code should contain the redemption information and other relevant details.
They should also set up a Real Time Notification endpoint to receive the final receipt.
Process
Step 1
Scan the foreign QR
Upon scanning, the Loyalty QR code will be decoded, and its value will be sent in a POST
request to the QR endpoint along with the following query string parameters:
Field | Description |
---|---|
Code | The QR Code contents |
businessId | The account's business identifier. A business can contain multiple Business Locations. See Business ID vs Business Location ID |
businessLocationId | The site identifier for this Business Location |
tillId | The ID of the POS which scanned the QR Code |
Example of the request sent from the POS:
Step 2
Respond
Once the information is sent to the endpoint, the system will need to process the request as quickly as possible and return a JSON response with the following structure.
{
"externalReference": {
"prefix": "REFERENCEPREFIX",
"reference": "REFERENCEID"
},
"displayMessage": "LOYALTY POINTS REDEEMED!",
"consumer": {
"firstName": "Documentation",
"lastName": "Test",
"companyName": "Test",
"phoneNumber1": 555-555-5555,
"emailAddress": "docs@lightspeedhq.com",
"consumerNotes": null,
"thirdPartyConsumerReference": 123456
},
"rewardBasket": {
"discountCode": "10PCT",
"productRewardList": [{
"sku": "CKE",
"price": null,
"discountCode": null,
"modifyItemIfFound": false
}, {
"sku": "SKU123",
"price": null,
"discountCode": "10PCT",
"modifyItemIfFound": true
}, {
"sku": "OD1",
"price": 0,
"discountCode": null,
"modifyItemIfFound": false
}]
}
}
This response would lead to something like the following being displayed in a modal within the POS:
Important Definitions
-
The
thirdPartyConsumerReference
field can be used to attach the customer account ID used by the integrator -
The optional
rewardBasket
field contains the rewards to be applied to the current transaction -
The
externalReference
data will be attached to the transaction once it is completed and sent to the RTN endpoint. This can be used by the integrator to identify the transaction -
The
displayMessage
will be shown on the POS display in a modal -
The
consumer
object contains customer details -
The top level
discountCode
inside therewardBasket
object is a discount applied to the entire sale -
The
productRewardList
is the list of items available for the reward -
The
modifyItemIfFound
field can either be set tofalse
, or contain the following format of object:
"modifyItemIfFound" {
"sku": "SKU123",
"price": null,
"discountCode": "10PCT",
"modifyItemIfFound": true
}
In the above example, if an item with SKU SKU123
is found in the basket, the discountCode
10PCT
will be applied to that item. If it is not found, it will be added and the discount will be applied.
If modifyItemIfFound
is set to false
then there will be no attempt to modify an existing item. A new item will be added to the basket, with the corresponding discountCode
applied.
Example accountClose payload
This is what the payload sent to the RTN endpoint will look like:
{
"notificationType": "UPDATE",
"account": {
"id": 85474144161502,
"uuid": null,
"businessLocationId": 9148280340482,
"name": "Order 2",
"accountNumber": "A4975.244",
"currencyCode": "EUR",
"deviceId": 4975,
"deviceName": "iPad84",
"deviceIp": null,
"staffId": 1251,
"staffName": "Manager",
"staffEmail": null,
"openDate": 1553609526916,
"closeDate": 1553609597693,
"paidAmount": 9.5,
"totalAmount": 9.5,
"coverCount": 0,
"gratuityAmount": 0,
"receiptNumber": "R4975.62",
"cancelled": false,
"accountProfileCode": "DIRECTE",
"transactionLines": [
{
"id": 85474144161503,
"parentLineId": null,
"accountId": 85474144161502,
"currencyCode": null,
"amount": 3.5,
"unitAmount": 3.5,
"quantity": 1,
"staffId": 1251,
"staffName": "Manager",
"staffEmail": null,
"nameOverride": "",
"itemDescription": "Expresso",
"accountingGroupId": "9148280340523",
"accountingGroupName": "Boissons",
"itemId": 9148280340801,
"itemSku": "44",
"date": 1553609576963,
"active": true,
"deviceId": 4975,
"deviceName": "iPad84",
"deviceIp": null,
"activeTax": {
"code": "TVAR10",
"description": "TVA 10%",
"rate": 1.1,
"taxIncluded": true
},
"subLines": [],
"discounts": [],
"tags": ""
},
{
"id": 85474144161504,
"parentLineId": null,
"accountId": 85474144161502,
"currencyCode": null,
"amount": 6,
"unitAmount": 6,
"quantity": 1,
"staffId": 1251,
"staffName": "Manager",
"staffEmail": null,
"nameOverride": "",
"itemDescription": "Chocolat chaud",
"accountingGroupId": "9148280340523",
"accountingGroupName": "Boissons",
"itemId": 9148280340797,
"itemSku": "43",
"date": 1553609596725,
"active": true,
"deviceId": 4975,
"deviceName": "iPad84",
"deviceIp": null,
"activeTax": {
"code": "TVAR10",
"description": "TVA 10%",
"rate": 1.1,
"taxIncluded": true
},
"subLines": [],
"discounts": [],
"tags": ""
}
],
"paymentLines": [
{
"id": 85474144161505,
"accountId": 85474144161502,
"currencyCode": "EUR",
"gratuityAmount": 0,
"amount": 9.5,
"staffId": 1251,
"staffName": "Manager",
"staffEmail": null,
"date": 1553609597681,
"active": true,
"paymentMethod": "CASH",
"paymentMethodDescription": "Espèces",
"deviceId": 4975,
"deviceName": "iPad84",
"deviceIp": null,
"externalReference": null
}
],
"discounts": [],
"externalReferences": [],
"deliveryInformation": {
"id": null,
"enabled": true,
"deliveryMode": "COLLECTION",
"deliveryState": "IN_PRODUCTION",
"collectionCode": "2",
"deliveryInfo": "",
"deliveryDueTime": null,
"deliveryTime": null,
"deliveredTime": null,
"productionDueTime": null,
"prepaid": false,
"deliveryOrigin": "POS",
"deviceName": "iPad84"
},
"consumerRecord": null,
"currentProductionPhase": 0,
"currentInsertionPhase": 0,
"accountObjectId": null,
"status": "closed"
},
"event": null,
"retryCounter": 0,
"businessLocationId": 9148280340482
}