POS Integration

Let’s Trade’s POS integration enables seamless interaction between your Point of Sale (POS) system and Let’sTrade offerings. This integration allows your POS system to send codes to Let’sTrade to determine applicable offerings and finalise transactions, facilitating earning rewards, redeeming vouchers, and making payments..

API Base URL

The base URL for all API endpoints is:

https://lets-trade-integration-prod.letstrade.global

Authentication

Let'sTrade API uses Bearer Token Authentication for securing API requests. Each API call must include a valid bearer token in the Authorisation header. Here’s an example of how to include the bearer token in your request:

Authorization: Bearer YOUR_ACCESS_TOKEN

Ensure that you replace YOUR_ACCESS_TOKEN with a valid token obtained during the authentication process.

Key Features:

1. Request Offerings: Send a code (either P, R, or E) along with basket details to Let’sTrade to determine applicable offerings for rewards, voucher redemptions, or payments.

2. Finalise Transaction: Complete the transaction by confirming the codes, processing rewards, payments, and finalising vouchers.

Step 1: Request Offerings

1. Check Code Applicability:

The POS can call the offerings endpoint to check what the provided code and basket applies to:

  • For P codes, the backend simulates the payment and returns deducted outstanding amount.

  • For R codes, the backend returns voucher details without redeeming them.

  • For E codes, no action is taken at this stage.

This step only determines the offerings and does not finalise the transaction

2. Code Expiry:

Codes are set to have a 10-minute expiry from the moment they are generated. The user has 10 minutes to complete the transaction and use the code. If the code expires, a new code must be generated and passed.

Step 2: Finalise Transaction

1. Complete Order on POS:

Once the order is complete on the POS and payment is being finalised, the finalise endpoint is called. This step executes the rules linked to the provided code/s and finalises the transaction.

  • For P codes: Payment is finalise, card and/or wallet charged.

  • For R codes: The voucher is redeemed (burned) in the system.

  • For E codes: Points or rewards are awarded once based on the transaction.

2. Irreversibility:

Once the finalise endpoint is called, the transaction is executed based on the rules linked to the code, and this action cannot be undone.

3. Payment Scenarios:

If the code is used for payment, the offerings endpoint will indicate the breakdown of the payment amount per type (e.g., card, wallet, loan).

Example Workflow

1. User at POS:

The user at the POS system receives a code (P, R, or E), either by reading it out or scanning a QR code.

2. POS Requests Offerings:

The POS sends the code and basket details to the offerings endpoint to determine what the code applies to (e.g., earning rewards, or redeeming vouchers). If the code is used for payment, this call ensures that the payment process is initiated and handled by Let’sTrade.

3. Display Offerings:

The POS displays the applicable offerings to the user based on the response.

4. User Confirms Transaction:

The user confirms the transaction within 10 minutes of the code generation.

5. Finalise Transaction:

The POS calls the finalise endpoint to execute the rules linked to the code and complete the transaction. If the code is used for earning rewards or redeeming vouchers, this call ensures that rewards are credited and vouchers are redeemed (burned) in the system accordingly.

By following this process, the integration ensures that the POS system can effectively manage code-based transactions, provide timely information to the user, and finalise transactions securely and efficiently.

Sequence

Offerings

POST /v1/get/offerings

This endpoint is used to retrieve applicable offerings for a given code at the POS.

Headers

Name
Value

Content-Type

application/json

Authorization

Bearer <token>

Body

Root:

Name
Type
Description

code*

string

A string indicating the type of operation. Possible values are:

store_id*

string

A string representing the unique identifier of the store where the transaction is taking place.

terminal_id*

string

A string representing the unique identifier of the terminal within the store where the transaction is processed.

basket*

object

An object containing details about the customer’s shopping basket.

Basket Object:

Name
Type
Description

uuid*

string

A string representing the unique identifier of the basket.

total*

string

A number indicating the total amount of the basket, including all fees and taxes.

outstanding*

string

A number representing the remaining amount to be paid after all discounts, fees, and vouchers have been applied.

product_list*

array

An array of objects representing the products in the basket.

vat

string

A number representing the Value Added Tax amount for the basket.

sub_total

string

A number indicating the subtotal amount of the basket, excluding VAT and fees.

delivery_fee

string

A number representing the fee for delivering the items in the basket.

service_fee

string

A number representing the additional service fee applied to the basket, such as tips.

discount

string

A number indicating the total discount applied to the basket.

external_vouchers

array

An array of objects representing external vouchers applied to the basket.

External_vouchers (array):

Name
Type
Description

title

string

A string indicating the name of the voucher.

id*

string

A string representing the unique identifier of the voucher.

value*

string

A number indicating the monetary value of the voucher.

sku

object

A string representing the stock keeping unit (SKU) of the product that the voucher applies to in the product_list of the basket

Product List (array):

Name
Type
Description

sku*

string

A string representing the stock keeping unit (SKU) of the product, used for inventory tracking.

quantity*

string

A number indicating the quantity of the product in the basket.

price*

string

A number representing the price of the product before any discounts are applied.

title

string

A string indicating the name of the product.

discount

string

A number indicating the discount amount applied to the product.

on_promotion

boolean

A boolean indicating whether the product is currently on promotion.

promotion_price

string

A number representing the promotional price of the product, if applicable.

barcode

string

A string representing the barcode of the product, used for scanning and inventory purposes.

add_ons

array

An array of objects representing additional items or accessories related to the main product. Array of product objects

Sample request

{
  "code": "E | R | P",
  "store_id": "232323",
  "terminal_id": "1234234",
  "basket": {
    "uuid": "6697b10a9a1620583b208f77",
    "user_id": "65f7e8d2b531f1c92cf94825",
    "total": "289.95",
    "vat": "29.99",
    "sub_total": "199.96",
    "delivery_fee": "60.00",
    "service_fee": "60.00",
    "discount": "100.00",
    "outstanding": "10.00",
    "external_vouchers": [
      {
        "title": "Sample Product A",
        "id": "uywduci",
        "value": "100.00",
        "sku": "1234567890123"
      }
    ],
    "product_list": [
      {
        "title": "Sample Product A",
        "sku": "1234567890123",
        "quantity": "1",
        "price": "229.95",
        "discount": "100.00",
        "on_promotion": false,
        "promotion_price": "0.00",
        "barcode": "1234567890123",
        "add_ons": [
          {
            "title": "Sample Product A Add-on",
            "sku": "1234567890123",
            "quantity": "1",
            "price": "229.95",
            "discount": "100.00",
            "on_promotion": false,
            "promotion_price": "0.00",
            "barcode": "1234567890123",
            "add_ons": []
          }
        ]
      }
    ]
  }
}

Response

{
  "success": true,
  "message": "Successfully retrieved offerings",
  "content": {
    "code": ["P", "R", "E"],
    "store_id": "000000",
    "terminal_id": "000000",
    "client_id": "00",
    "basket": {
      "uuid": "0000000000000000000000",
      "user_id": "65f7e8d2b531f1c92cf94825",
      "delivery_fee": "0.00",
      "service_fee": "0.00",
      "outstanding_amount": "166.00",
      "total": "166.00",
      "product_handling_fees": "0.00",
      "vat": "21.65",
      "sub_total": "144.35",
      "product_list": [
        {
          "image_url": "https://....jpg",
          "title": "Latte Coffee",
          "sub_title": "Medium Latte",
          "description": "<p>Smooth and creamy coffee.</p>",
          "sku": "001",
          "pid": "001",
          "quantity": "1",
          "price": "30.00",
          "on_promotion": true,
          "promotion_price": "25.00",
          "barcode": "001",
          "vouchers": [
            {
              "voucher_name": "R10 off",
              "quantity": "1",
              "price": "30.00",
              "discounted_price": "20.00",
              "discount": "10.00",
              "voucher_id": "66ebc52c084f1481c69d59f9",
              "voucher_type": "VALUE"
            }
          ],
          "deal": {
            "configuration": "DISCOUNT",
            "quantity": "1",
            "discounted_price": "112.00",
            "discount": "28.00",
            "deal_id": "68e5fb3d61dea1aabc20876e",
            "deal_name": "Sample Discount",
            "deal_priority": 1,
            "apply_to": "PRODUCT",
            "deal_image_url": "https://....png"
          }
        },
        {
          "image_url": "https://....jpg",
          "title": "Blueberry Muffin",
          "sub_title": "Fresh Muffin",
          "description": "<p>Delicious blueberry muffin.</p>",
          "sku": "002",
          "pid": "002",
          "quantity": "3",
          "price": "47.00",
          "on_promotion": false,
          "promotion_price": "0.00",
          "barcode": "002",
          "deal": null
        }
      ],
      "card": {
        "_id": "",
        "amount": "66.00",
        "currency": "ZAR"
      },
      "wallet": {
        "amount": "100.00",
        "currency": "ZAR",
        "provider": "LETS-TRADE"
      },
      "vouchers": [
        {
          "voucher_name": "R10 off",
          "quantity": "1",
          "discount": "10.00",
          "voucher_id": "66ebc52c084f1481c69d59f9",
          "voucher_type": "VALUE"
        }
      ],
      "deals": [
        {
          "configuration": "DISCOUNT",
          "quantity": "1",
          "discounted_price": "272.00",
          "discount": "68.00",
          "deal_id": "68f22aa8d2f808da3b0246a7",
          "deal_name": "Sample Basket Deal",
          "deal_priority": 100,
          "apply_to": "BASKET",
          "deal_image_url": "https://....png"
        }
      ]
    },
    "customer": {
      "name": "Customer Name",
      "surname": "Customer Surname",
      "birthday": "1995-10-08T22:00:00.000Z"
    },
    "rewards": [
      {
        "title": "cashback",
        "value": "100.00"
      }
    ]
  }
}

Response descriptions

Name
Type
Description

customer

object

An object containing information about the customer.

rewards

array

An array of objects representing the rewards applicable to the customer, that they have earned due to this transaction.

transaction_details

object

An object containing details about the transaction.

ref

string

A string representing a unique reference identifier for the transaction content.

discount

string

A number indicating the total discount that needs to be applied to the order.

basket.outstanding

string

A number representing the remaining amount to be paid after discounts have been applied.

basket.product_list.voucher.discount

string

A number indicating the discount applied to the product.

basket.product_list.voucher.discounted_price

string

A number representing the price of the product after the discount has been applied.

basket.card.amount

string

A number representing the amount that was paid using a card

basket.wallet.amount

string

A number representing the amount that was paid using a card

basket.vouchers.discount

string

A number indicating the discount applied to the basket.

Finalise

POST /v1/finalise/offerings

This endpoint is used to finalise the transaction by confirming the code and processing the details.

Headers

Name
Value

Content-Type

application/json

Authorization

Bearer <token>

Sample request

{
  "code": ["E", "R", "P"],
  "store_id": "232323",
  "terminal_id": "1234234",
  "basket": {
    "uuid": "6697b10a9a1620583b208f77",
    "user_id": "65f7e8d2b531f1c92cf94825",
    "total": "289.95",
    "vat": "29.99",
    "sub_total": "199.96",
    "delivery_fee": "60.00",
    "service_fee": "60.00",
    "discount": "100.00",
    "outstanding": "10.00",
    "vouchers": [
      {
        "title": "Sample Product A",
        "id": "uywduci",
        "value": "100.00",
        "sku": "100.00"
      }
    ],
    "deals": [
      {
        "configuration": "DISCOUNT",
        "quantity": "1",
        "discounted_price": "272.00",
        "discount": "68.00",
        "deal_id": "68f22aa8d2f808da3b0246a7",
        "deal_name": "Sample Basket Deal",
        "deal_priority": 100,
        "apply_to": "BASKET",
        "deal_image_url": "https://....png"
      }
    ],
    "product_list": [
      {
        "title": "Sample Product A",
        "sku": "1234567890123",
        "quantity": "1",
        "price": "229.95",
        "discount": "100.00",
        "on_promotion": false,
        "promotion_price": "0.00",
        "barcode": "1234567890123",
        "add_ons": [
          {
            "title": "Sample Product A Add-on",
            "sku": "1234567890123",
            "quantity": "1",
            "price": "229.95",
            "discount": "100.00",
            "on_promotion": false,
            "promotion_price": "0.00",
            "barcode": "1234567890123",
            "add_ons": []
          }
        ],
        "deal": {
          "configuration": "DISCOUNT",
          "quantity": "1",
          "discounted_price": "112.00",
          "discount": "28.00",
          "deal_id": "68e5fb3d61dea1aabc20876e",
          "deal_name": "Sample Discount",
          "deal_priority": 1,
          "apply_to": "PRODUCT",
          "deal_image_url": "https://....png"
        }
      }
    ]
  }
}

Response

{
  "success": true,
  "message": "Successfully retrieved offerings",
  "content": {
    "code": ["P", "R", "E"],
    "store_id": "000000",
    "terminal_id": "000000",
    "client_id": "00",
    "basket": {
      "uuid": "0000000000000000000000",
      "delivery_fee": "0.00",
      "service_fee": "0.00",
      "outstanding_amount": "166.00",
      "total": "166.00",
      "product_handling_fees": "0.00",
      "vat": "21.65",
      "sub_total": "144.35",
      "product_list": [
        {
          "image_url": "https://....jpg",
          "title": "Latte Coffee",
          "sub_title": "Medium Latte",
          "description": "<p>Smooth and creamy coffee.</p>",
          "sku": "001",
          "pid": "001",
          "quantity": "1",
          "price": "30.00",
          "on_promotion": true,
          "promotion_price": "25.00",
          "barcode": "001",
          "vouchers": [
            {
              "voucher_name": "R10 off",
              "quantity": "1",
              "price": "30.00",
              "discounted_price": "20.00",
              "discount": "10.00",
              "voucher_id": "66ebc52c084f1481c69d59f9",
              "voucher_type": "VALUE"
            }
          ],
          "deal": {
            "configuration": "DISCOUNT",
            "quantity": "1",
            "discounted_price": "112.00",
            "discount": "28.00",
            "deal_id": "68e5fb3d61dea1aabc20876e",
            "deal_name": "Sample Discount",
            "deal_priority": 1,
            "apply_to": "PRODUCT",
            "deal_image_url": "https://....png"
          }
        },
        {
          "image_url": "https://....jpg",
          "title": "Blueberry Muffin",
          "sub_title": "Fresh Muffin",
          "description": "<p>Delicious blueberry muffin.</p>",
          "sku": "002",
          "pid": "002",
          "quantity": "3",
          "price": "47.00",
          "on_promotion": false,
          "promotion_price": "0.00",
          "barcode": "002"
        }
      ],
      "card": {
        "_id": "",
        "amount": "66.00",
        "currency": "ZAR"
      },
      "wallet": {
        "amount": "100.00",
        "currency": "ZAR",
        "provider": "LETS-TRADE"
      },
      "vouchers": [
        {
          "voucher_name": "R10 off",
          "quantity": "1",
          "price": "30.00",
          "discounted_price": "20.00",
          "discount": "10.00",
          "voucher_id": "66ebc52c084f1481c69d59f9",
          "voucher_type": "VALUE"
        }
      ],
      "deals": [
        {
          "configuration": "DISCOUNT",
          "quantity": "1",
          "discounted_price": "272.00",
          "discount": "68.00",
          "deal_id": "68f22aa8d2f808da3b0246a7",
          "deal_name": "Sample Basket Deal",
          "deal_priority": 100,
          "apply_to": "BASKET",
          "deal_image_url": "https://....png"
        }
      ]
    },
    "customer": {
      "name": "Customer Name",
      "surname": "Customer Surname",
      "birthday": "1995-10-08T22:00:00.000Z"
    },
    "rewards": [
      {
        "title": "cashback",
        "value": "100.00"
      }
    ]
  }
}

Respons descriptions

Name
Type
Description

customer

object

An object containing information about the customer.

rewards

array

An array of objects representing the rewards applicable to the customer, that they have earned due to this transaction.

transaction_details

object

An object containing details about the transaction.

ref

string

A string representing a unique reference identifier for the transaction content.

discount

string

A number indicating the total discount that needs to be applied to the order.

outstanding

string

A number representing the remaining amount to be paid after discounts have been applied.

product_list.sku

string

A string representing the product that the discount applies to.

product_list.reward

string

A string representing the name of the reward that applies to the product

product_list.discount

string

A number indicating the discount applied to the product.

product_list.discounted_price

string

A number representing the price of the product after the discount has been applied.

Refund

UPCOMING FEATURE

The Refund API is designed to handle situations where a user requests a refund for codes that have already been used or when an order needs to be voided entirely. This ensures flexibility for Point of Sale (POS) transactions by providing a secure and efficient way to reverse actions associated with codes and baskets.

Purpose:

1. Refund Codes:

  • Allows the system to reverse the actions associated with codes (e.g., rewards awarded, vouchers redeemed, or payments processed).

  • Ensures that any benefits or deductions linked to the code are voided.

2. Void Basket:

  • Cancels the entire basket linked to the transaction.

  • Clears any processed payments, redeemed vouchers, or rewards associated with the transaction.

POST /v1/refund

This endpoint is used to refund codes that have been used but where the customer has asked to void the order.

Headers

Name
Value

Content-Type

application/json

Authorization

Bearer <token>

Sample request

{
  "code": ["E", "R", "P"],
  "store_id": "232323",
  "terminal_id": "1234234"
}

Response

{
  "success": true,
  "message": "Successfully refunded codes",
  "content": {
    "code": ["P", "R", "E"],
    "store_id": "000000",
    "terminal_id": "000000"
  }
}

QR Code Slip Printing (Loyalty Scanning)

This section describes how the POS should support printed QR codes on the customer bill/slip to enable loyalty scanning and voucher selection in the Let’sTrade app.

Goal

Allow a customer to scan a QR code on a printed bill to:

  1. Identify the store/terminal/transaction in Let’sTrade.

  2. View/select applicable offerings (earn and/or redeem vouchers) in-app before the cashier finalises the bill.


1. Get Offerings on Bill Print (for QR)

Trigger

When the bill is printed (pre-payment), the POS must call Get Offerings so that:

  • Let’sTrade can calculate eligible offerings for the basket, and

  • The POS can print a QR tied to the open bill.

Endpoint

POST /v1/get/offerings

Send the request exactly as per the /v1/get/offerings Offerings endpoint above, including full store_id, terminal_id, and complete basket payload in that same structure. The only difference for QR slip printing is that code may be null / omitted at this stage because the customer has not yet scanned or selected a code in-app.


2. Customer Scans QR in App (Pre-Finalise)

  1. Customer scans the printed QR.

  2. A client's app uses store_id + terminal_id + transaction_id to load the open bill’s offerings.

  3. Customer selects vouchers to apply (optional).

  4. Before bill closure, Let’sTrade must be able to send the selected vouchers to the POS.


3. Append Vouchers to Order (Pre-Closure)

Important: This is NOT a Let’sTrade endpoint. The POS provider must implement this endpoint on their side, and Let’sTrade will call it to append vouchers to the open order.

POS-Provided Endpoint

POST {POS_BASE_URL}/append-vouchers (name/path chosen by POS provider)

Use Case

  • POS already printed the QR and kept the bill open.

  • Customer selects vouchers in Client's app.

  • Let’sTrade calls the POS endpoint to attach those vouchers to the live bill before payment finalisation.

Request Body (from Let’sTrade → POS)

{
  "uid": "string",            // Let’sTrade basket UUID
  "reference": "string",      // Reference to display on bill (voucher label/ref)
  "store_id": "string",       // Store ID
  "transaction_id": "string", // POS bill/transaction ID from QR
  "original_amount": 123.45,
  "discount_amount": 50.00,
  "remaining_amount": 73.45
}

Field Notes

  • uid: identifies the basket in Let'sTrade the user is applying vouchers to.

  • reference: printable reference the POS must show on the slip (e.g., voucher name/code).

  • store_id + transaction_id: binds to the exact open bill.

  • Amounts are for reconciliation and validation:

    • original_amount: bill total before vouchers.

    • discount_amount: total discount selected in app.

    • remaining_amount: amount due after voucher application.

Expected POS Behaviour

  • Validate the open bill exists and matches identifiers.

  • Apply discounts / attach vouchers to the transaction.

  • Update totals accordingly.

  • Optionally reprint the bill showing voucher application.


4. Finalise Offerings on Bill Close (Always)

Trigger

When the cashier closes the bill after payment, the POS must call Finalise Offerings every time, even if:

  • no QR was scanned,

  • no vouchers were applied,

  • no offerings were returned.

Endpoint

POST /v1/finalise/offerings

Why this matters

Finalise is the commit step that:

  • creates the order in Let’sTrade, and

  • ensures earn/burn rules execute correctly.


End-to-End Workflow Summary

  1. Bill print (pre-payment) POS → POST /v1/get/offerings POS prints QR with store_id, terminal_id, transaction_id.

  2. Customer scans QR App loads offerings for that open bill.

  3. Customer selects vouchers (optional) Client App → POS-provided POST /append-vouchers with voucher bundle.

  4. Payment occurs POS processes payment normally.

  5. Bill close / commit (always) POS → POST /v1/finalise/offerings

Last updated