Skip to main content

Loyalty Integration

Overview

The AiFi Loyalty Bridge API allows external loyalty systems to integrate with AiFi-powered autonomous stores. It enables stores to offer personalized rewards like points, balances, or product-based discounts using a small set of REST API endpoints and webhooks.


Shopper Journey – No Registration Flow

  1. Shopper taps credit card at the store entrance (via AiFi terminal).
  2. Shopper enters and selects some items.
  3. (Optional) Shopper scans a loyalty QR code or gift card inside the store.
  4. AiFi uses the loyalty code to link the session ID or customer ID.
  5. Shopper leaves the store.
  6. AiFi triggers the cart-mutator webhook, containing the added customer/session metadata, so the client can respond with the relevant discounts.
  7. AiFi processes the final payment.
  8. Shopper receives their receipt from the WebReceipt Portal.

Developer Integration Flow

The following sequence outlines how shopper actions map to AiFi webhook calls.

  1. Shopper enters the store.

  2. (Optional) Shopper scans a loyalty QR code.

    POST /api/v1/loyalty/code-scan webhook is triggered immediately after the QR code scan. AiFi sends this webhook to attach customer or session metadata to the active session.

  3. Shopper shops and exits.

  4. Before checkout, AiFi triggers the cart mutation process.

    POST /api/cart-mutate webhook is sent before checkout. Your system receives the cart and may respond in two ways:

    • Return a modified cart with discounts or adjustments (HTTP 201)
    • Return the original payload unchanged (HTTP 201)
info

The cart-mutate webhook is mandatory for all integrations.

(Optional) A checkout webhook exists but is not required for loyalty integration.

API Endpoints

To integrate with the AiFi Loyalty Bridge API, your system must support the following three endpoints.


1. Discovery Endpoint

Method: PUT /api/v1/loyalty/auto-discovery

Used to register your system with AiFi’s Loyalty Bridge. This tells AiFi where your API lives and how to authenticate with it.

📋 View Example Request
PUT /api/v1/loyalty/auto-discovery
{
"providerName": "string",
"url": "https://api.url.com/",
"authorization": {
"type": "bearer",
"token": "1234"
}
}
Notes
  • Only Bearer authentication is currently supported.
  • You should call this once when your service starts or whenever your configuration changes (e.g., rotating an API key).

2. Loyalty Code Scan Webhook

Method: POST /api/v1/loyalty/code-scan

Triggered when a shopper scans a loyalty QR code in the store. AiFi sends this request to your system so you can validate the code and return customer or session metadata.

The loyaltyCode and any additionalProps you return will later appear in the cart-mutate webhook payload.

📤 Request Format
POST /api/v1/loyalty/code-scan - Request Body
{
"code": "string",
"transactionReference": "string"
}
✅ Valid Code Response (200)
HTTP 200 - Valid loyalty code
{
"customer": {
"loyaltyCode": "1234",
"additionalProp1": "value",
"additionalProp2": "value"
},
"session": {
"loyaltyCode": "1234",
"additionalProp1": "value"
}
}
❌ Invalid Code Response (404)
HTTP 404 - Invalid loyalty code
{}

3. Cart Mutator Webhook

Method: POST /api/cart-mutate

Triggered before checkout. This allows your system to apply loyalty rewards or discounts by modifying the cart.

📥 Request Format
POST /api/cart-mutate - Request Body
{
"orderId": 1705,
"sessionId": "some-unique-token",
"customer": {
"id": "42",
"externalId": "my-customer-94325",
"metadata": {
"loyaltyCode": "ABCD1234"
}
},
"session": {
"metadata": {
"events": [
{
"eventId": "uuid",
"metadata": {
"loyaltyCode": "123456"
}
}
]
}
},
"storeId": 2,
"storeExternalId": "mystore-0001",
"cart": [
{
"barcode": "1201303",
"category": null,
"name": "Pepsi",
"sku": null,
"thumbnail": "https://aifigtins.blob.core.windows.net/product/1201303/1.jpeg",
"id": "1",
"externalId": "1201303",
"price": 10,
"quantity": 1,
"taxLines": [],
"totalTax": "0.99",
"subtotalPrice": "10.00",
"totalPrice": "10.99",
"productSnapshot": {
"id": 1,
"name": "Pepsi, 12 fl oz",
"weight": "1.00",
"barcode": "1201303",
"category": null,
"sku": null,
"thumbnail": "https://aifigtins.blob.core.windows.net/product/1201303/1.jpeg",
"taxCode": null,
"externalId": "1201303",
"price": "10.00",
"createdAt": "2025-07-11T00:59:15.972Z",
"updatedAt": "2025-07-11T00:59:15.972Z",
"productId": 1
}
}
],
"totalPrice": "10.99",
"totalTax": "0.99",
"subtotalPrice": "10.00"
}
🛒 Modified Cart Response (201)

Return this format when applying loyalty discounts or modifications to the cart:

HTTP 201 - Cart with loyalty modifications
{
"orderId": 1,
"totalPrice": "30.00",
"subtotalPrice": "28.00",
"totalTax": "2.00",
"cart": [
{
"id": "1",
"externalId": 123,
"quantity": 4,
"totalPrice": "20.00",
"subtotalPrice": "18.00",
"totalTax": "2.00",
"taxLines": [
{
"title": "Example",
"rate": "0.1",
"amount": "0.50",
"taxId": "123"
}
],
"isDeposit": false
},
{
"id": "2",
"externalId": 1234,
"quantity": 1,
"totalPrice": "10.00",
"subtotalPrice": "10.00",
"totalTax": "0.00",
"taxLines": [],
"isDeposit": false
}
]
}
➡️ No Changes Response (201)

If the cart doesn't need changes, return the same payload with HTTP 201:

HTTP 201 - No loyalty modifications needed
{
"customer": {
"metadata": {
"loyaltyCode": "ABCD1234"
}
},
"session": {
"metadata": {
"events": [
{
"eventId": "uuid",
"metadata": {
"loyaltyCode": "123456"
}
}
]
}
}
}

Loyalty code data location

In the cart-mutate webhook payload, the scanned loyalty code is found in either:

  • customer.metadata
  • session.metadata

Two Configuration Scenarios:

  • If the QR scan is linked to the customer profile → the code appears in customer.metadata
  • If the QR scan is for that specific visit/session → the code appears in session.metadata

Loyalty Limitations

  • Endpoint Paths Are Fixed

    • You must implement the following endpoints exactly as specified:
      • POST /api/v1/loyalty/code-scan
      • POST /api/cart-mutate
  • Authentication Method

    • Only Bearer tokens are currently supported
    • Custom authentication methods aren't available
  • Customization

    • Custom endpoint paths aren't supported in the current API version
    • Standard webhook payload formats are required
    • No flexibility for custom request/response structures