Cashback
The Score Exchange lets customers redeem their available loyalty balance (points or wallet amount) as a monetary discount at checkout. The exchange rate is configured per currency.
Cashback vs. debt compensation
POST /scores/redemption is not for checkout cashback β it compensates customers with a negative score balance (debt). Checkout cashback uses cashback_score_desired on POST /carts.
How It Worksβ
- Configure a Score Exchange for each currency (defines the points β money conversion rate).
- At checkout, the POS simulates the transaction with
POST /carts/simulate+cashback_score_desiredto preview the per-line distribution. - The customer confirms β the POS sends
POST /cartswith thecashbacks[]array from the simulate response. - Balance is deducted and a
redeementry is created inscore_transactions.
How much cashback to redeemβ
| Value | Behavior |
|---|---|
-1 | Redeem as much available balance as the cart can accept under the company's cashback configuration |
| Positive integer | Try to redeem exactly that many points; if the balance or configured discount cap prevents full redemption, Loyal Guru applies the maximum allowed amount |
0 | No cashback on this transaction |
When the customer requests more than available or more than the company-configured cap allows, the unspent amount is returned in cashback_score_desired_unused. See Company-configurable discount cap for how that cap works.
Simulate β preview cashback before commitβ
Always simulate first. The simulate call returns the per-line distribution that must be sent back on the persist call.
Request:
POST /carts/simulate
{
"id": 9001,
"location_id": 5,
"customer_id": 1042,
"creation_date": "2025-03-01T10:00:00Z",
"total": 80.00,
"currency": "EUR",
"lines": [
{"order": 1, "product_id": 101, "total": 60.00, "quantity": 2},
{"order": 2, "product_id": 205, "total": 20.00, "quantity": 1}
],
"cashback_score_desired": -1
}
Response (excerpt):
{
"cashback_score_desired": 8000,
"cashback_score_desired_unused": 0,
"score_used": -8000,
"score_used_as_money": -40.00,
"cashbacks": [
{"line_order": 1, "score": 6000, "discount": 30.00},
{"line_order": 2, "score": 2000, "discount": 10.00}
],
"customer": {
"score": 8000,
"score_available": 8000,
"score_threshold_cashback": 1000,
"money_threshold_cashback": 0
}
}
Persist β send cashbacks[] back:
POST /carts
{
"id": 9001,
"location_id": 5,
"customer_id": 1042,
"creation_date": "2025-03-01T10:00:00Z",
"total": 80.00,
"currency": "EUR",
"lines": [
{"order": 1, "product_id": 101, "total": 60.00, "quantity": 2},
{"order": 2, "product_id": 205, "total": 20.00, "quantity": 1}
],
"cashbacks": [
{"line_order": 1, "score": 6000, "discount": 30.00},
{"line_order": 2, "score": 2000, "discount": 10.00}
]
}
Minimum thresholdsβ
Before cashback activates, two conditions must be met:
| Field | Description |
|---|---|
score_threshold_cashback | Minimum points balance the customer must have (e.g. 1,000 pts). Visible in the customer object of the response. |
money_threshold_cashback | Minimum cart amount for cashback to be available (e.g. β¬10). |
score_to_reach_cashback | Points still needed to reach the threshold (shown in response if customer is below). |
Company-configurable discount capβ
The system enforces a maximum combined discount per line. This cap is configurable per company: it commonly defaults to 50%, but can be configured up to 100% when the business wants to allow full line redemption.
The cap applies to the sum of all promotional discounts plus cashback on each line.
Example: if the configured cap is 50%, a line that already has a 30% promotional discount can redeem cashback for at most 20% more on that line. If the configured cap is 100%, that same line can redeem up to 70% more. The rest goes to cashback_score_desired_unused.
Configurationβ
Go to Loyalty β Cashback β New Cashback.
| Field | Description |
|---|---|
| Name | Descriptive name for this exchange configuration |
| Currency | The currency this exchange applies to. Each currency can have only one Score Exchange |
| Amount (conversion rate) | How many currency units equal 1 point. Example: 0.01 means 1 pt = β¬0.01 |
Money wallet (accrual_mode: money)
In accrual_mode: money, the wallet balance is already in currency β the rate is effectively 1:1 (β¬1 wallet = β¬1 discount). No conversion formula needed.
Returnsβ
When a cart is cancelled (POST /carts/cancellation) or partially returned (POST /carts with negative lines and returns[]), cashback points are restored to the customer with their original expiry dates. If some of the original balance had already expired, only the non-expired portion is restored.
Full cancellation also reverses all vouchers linked to the cart β they return to available status.
See Returns for full API examples, edge cases, and rounding rules.