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.

circle-info

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

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.

code

array

An array of code strings indicating the type of operation. Possible values per code are P (payment), R (redemption), or E (earning). Defaults to [] if omitted

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.

user

object

An object containing customer identification details. See User Object below.

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.

User Object:

Note: If user._id is not provided but email or cell_number is, the API will attempt to find or create the customer. Additionally, the user can be omitted if providing codes as codes are tied to a user and will be prioritised when selecting a user.

Name
Type
Description

_id

string

Known Let'sTrade user ID. If provided, skips user lookup.

name

string

Customer first name.

surname

string

Customer surname.

email

string

Customer email address (must be valid email format).

cell_country_code

string

Phone country code (e.g. "+27").

cell_number

string

Customer phone number.

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

string

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

quantity

string

The number of units to discount. If omitted, the discount applies to all units of the matched product. If provided, only this many units are discounted (capped at the product quantity).

apply_to_promotion

boolean

If true and the matched product is on promotion, the voucher discount is calculated against the promotion_price instead of the regular price.

Product List (array):

Name
Type
Description

sku*

string

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

pid*

string

The product identifier in Let'sTrade.

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.

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

condiments

array

An array of condiment/modifier items attached to the product. See Condiments below.

Condiments (array):

Note: Condiments represent modifiers attached to a parent product (e.g. milk choice on a coffee). They are sent as a flat array on the product. The API resolves them into condiment groups internally and returns them as a flat array in the response.

Name
Type
Description

pid*

string

The condiment product identifier in Let'sTrade.

sku

string

The condiment SKU.

title

string

The condiment name (e.g. "Almond Milk").

price

string

The condiment price.

quantity

string

The condiment quantity.

Sample request

Response

Response descriptions

Name
Type
Description

order_id

string

Unique order identifier for tracking.

order_code

string

Human-readable order code for tracking.

basket.outstanding_amount

string

The remaining amount to be paid after discounts have been applied.

basket.service_fee

string

Service fee applied to the basket.

basket.product_handling_fees

string

Product-related handling fees.

basket.product_list[].vouchers

array

An array of voucher objects applied to the product.

basket.product_list[].vouchers[].discount

string

The discount amount applied to the product by the voucher.

basket.product_list[].vouchers[].discounted_price

string

The price of the product after the voucher discount has been applied.

basket.product_list[].deal

object

A deal object applied to the product, or null if no deal applies.

basket.product_list[].subscription

object

Subscription discount applied to the product, if applicable. Contains redemption_id and discount.

basket.product_list[].condiments

array

Flat array of condiment/modifier items on the product (pid, sku, title, price, quantity).

basket.card

object

Card payment breakdown. Only present if a P (payment) code with card details was submitted.

basket.card.amount

number

The amount that was paid using a card.

basket.wallet

object

Wallet payment breakdown. Only present if a P (payment) code with wallet details was submitted.

basket.wallet.amount

number

The amount that was paid using a wallet.

basket.vouchers

array

An array of basket-level vouchers applied.

basket.vouchers[].discount

number

The discount amount applied to the basket by the voucher.

basket.deals

array

An array of basket-level deals applied.

basket.subscriptions

array

Subscription discounts applied to the cheapest qualifying products. Contains redemption_id, product_pid, product_title, and discount.

Finalise

POST /v1/finalise/offerings

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

Headers

Name
Value

Content-Type

application/json

Authorization

Bearer <token>

Body

Fields marked with * are required.

Root:

Name
Type
Description

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.

code

array

An array of code strings indicating the type of operation. Possible values per code are P (payment), R (redemption), or E (earning). Defaults to [] if omitted.

Basket Object:

Name
Type
Description

uuid*

string

A string representing the unique identifier of the basket.

total*

string

The total amount of the basket, including all fees and taxes.

product_list*

array

An array of objects representing the products in the basket. Minimum 1 item required.

outstanding_amount

string

The remaining amount to be paid after all discounts, fees, and vouchers have been applied.

vat

string

The Value Added Tax amount for the basket.

sub_total

string

The subtotal amount of the basket, excluding VAT and fees.

delivery_fee

string

The fee for delivering the items in the basket.

service_fee

string

An additional service fee applied to the basket, such as tips.

discount

string

The total discount applied to the basket.

product_handling_fees

string

Product-related handling fees applied to the basket.

user

object

An object containing customer identification details. Same structure as the Offerings User Object.

deals

array

An array of deal objects from the offerings response — pass back any deals the POS applied.

vouchers

array

An array of voucher objects from the offerings response — pass back any vouchers the POS applied.

Note: The external_vouchers field is not accepted on the finalise endpoint — external vouchers are only processed during get/offerings.

Product List (array):

Same fields as the Offerings Product List, plus:

Name
Type
Description

vouchers

array

Voucher objects from the offerings response — pass back any product-level vouchers.

deal

object

Deal object from the offerings response — pass back if a deal was applied to this product. May be null.

Sample request

Response

Response descriptions

Name
Type
Description

client_id

string

The client identifier. Only present in the finalise response.

order_id

string

Unique order identifier for tracking.

order_code

string

Human-readable order code for tracking.

basket.outstanding_amount

string

The remaining amount to be paid after discounts have been applied.

basket.service_fee

string

Service fee applied to the basket.

basket.product_handling_fees

string

Product-related handling fees.

basket.product_list[].vouchers

array

Product-level vouchers, echoed from the request.

basket.product_list[].vouchers[].discount

string

The discount amount applied to the product by the voucher.

basket.product_list[].vouchers[].discounted_price

string

The price of the product after the voucher discount has been applied.

basket.product_list[].deal

object

A deal object applied to the product, echoed from the request. null if no deal applies.

basket.product_list[].condiments

array

Flat array of condiment/modifier items on the product (pid, sku, title, price, quantity).

basket.vouchers

array

An array of basket-level vouchers (filtered to BASKET apply_to only).

basket.vouchers[].discount

number

The discount amount applied to the basket by the voucher.

basket.deals

array

An array of basket-level deals 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

Response

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)

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