> ## Documentation Index
> Fetch the complete documentation index at: https://docs.loyalty.xeniamoments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changes from Version 1

> What changed between OnlinePOS's V1 (28 Aug 2026) / V1-sync (4 Sep 2026) and REKOM's Version 2 (8 Oct 2026).

Version 2 keeps the structure and most of the terminology of OnlinePOS's original
description, so that the two can be compared section by section. The changes below
are either decisions made after V1 was written or REKOM proposals that resolve a
gap in V1.

## Model and flow

| Area | Version 1 (28 Aug / 4 Sep 2026) | Version 2 (8 Oct 2026) | Status |
| - | - | - | - |
| Call model | Asynchronous: `basketId`, polling from POS, `LoyaltyBasketCallback` / `LoyaltyBasketCallbackCancel` from REKOM (28 Aug). Synchronous in the 4 Sep update. | Synchronous only. Checkout waits on the REKOM response; no callbacks, no polling, no `basketId`. | Agreed 4 Sep 2026 |
| User interaction during the call | "REKOM runs its logic (optionally with user interaction)". | None. All upsell and choices happen before payment intent; the call is a pure calculation. | Agreed 31 Aug / 4 Sep 2026 |
| Correlation ID | `loyaltyDiscountReference` on the response (dropped 28 Aug). | POS/mPOS generate a **GUID per basket calculation** (`calculationId`), sent to REKOM and later exposed on the order as a **meta attribute** in the REST API. | Agreed 7 Oct 2026; meta attribute agreed after 7 Oct |
| "No change" outcome | Status `unchanged` existed, mechanism unspecified. | Explicit `unchanged` response with a `reason`; no lines returned. | Agreed 7 Oct 2026 |
| Source of truth | OnlinePOS validates and may reject. | The basket REKOM returns is authoritative; OnlinePOS validates arithmetic and schema only. | Agreed 7 Oct 2026 |

## Scope of basket changes

| Area | Version 1 | Version 2 | Status |
| - | - | - | - |
| Line price override | Allowed. | Kept (`overrideUnitPrice`). REKOM practice: member prices as an amount discount with text "Member price", so the benefit is visible as loyalty discount data. | Agreed scope kept; field name proposed |
| Add / remove / split lines | Allowed (product must exist on venue). | Kept, made explicit with `addedByLoyalty` and `splitFromLineId`. REKOM practice: partial-quantity benefits ("1 of 3 free") as an amount discount on the line. | Agreed scope kept; field names proposed |
| Existing discounts on the basket | Sent as `existingLineDiscount*`, "informational". | Input to REKOM's logic: REKOM keeps them or swaps them for a larger loyalty discount; OnlinePOS applies the returned basket as-is. | REKOM logic; OnlinePOS to confirm (O4) |
| Order-level discounts | Allowed as a separate order discount with allocation to lines. | Kept. REKOM supplies the per-line allocation, skipping lines flagged `noDiscount` (3 Sep 2026); shown at the bottom of the receipt through the free-text field (7 Oct 2026). | Agreed |
| Discount identification | Not mentioned. | No campaign ID. Every REKOM discount carries a predefined, semantic discount code (`lineDiscountCode`) for the catch-all third-party-loyalty type; exact string to be confirmed. | 6 Oct 2026 (campaign or generic type), resolved to the generic code after 7 Oct 2026 |
| Receipt | Discount text as a separate line under the product. | Same, formalised as a note line; no new print layouts; product receipt text untouched; discount is dedicated POS discount data, never a free-text 0-price product. | Agreed 17 Aug, 3 Sep, 6 Oct 2026 |

## Endpoints exposed by REKOM

| Version 1 | Version 2 | Status |
| - | - | - |
| `loyaltyBasket` | `POST /v1/onlinepos/basket` | Same purpose, now synchronous |
| `loyaltySaleFinalization` | `POST /v1/onlinepos/sale` with `status` `applied` / `unchanged` / `member_not_found` / `failed` | Merged — proposed |
| `loyaltySaleCancellation` | `POST /v1/onlinepos/sale` with `status` `cancelled` | Merged — proposed |
| `loyaltyOfflineSale` | `POST /v1/onlinepos/sale` with `status` `failed`, `failureReason` `offline` | Merged — proposed |
| `LoyaltyBasketCallback`, `LoyaltyBasketCallbackCancel` (OnlinePOS side) | Removed with the asynchronous model. | Agreed 4 Sep 2026 |

The 4 Sep text said "the three webhooks" while listing four endpoints. Version 2
resolves this to **two** REKOM endpoints.

## Naming and data

All Version 2 names in this section are directional: they show which information
is exchanged. REKOM adopts OnlinePOS's default names and structures.

| Area | Version 1 | Version 2 | Status |
| - | - | - | - |
| Member identifier | `memberID` in prose, `loyaltyID` in the 4 Sep lookup example. | "loyalty ID" in prose, `loyaltyId` in examples. Opaque, no PII. | Directional name; follows OnlinePOS default |
| Money | Integers in the example (10000 − 2000 − 1000 = 7000), unit never stated. | Integer minor units (øre) plus ISO 4217 `currency`. | Proposed — OnlinePOS to confirm |
| Context on the request | `venue`. | `venueId`, `baxId` and `cashRegisterId` (all required, so REKOM can attribute every order to a venue and till), `terminalId`, `clerkNumber`, `channel`. Names mirror the REST transaction API so reconciliation is a join. | BAX and terminal identifiers agreed after 7 Oct 2026; names directional |
| Line fields | `lineId`, `productId`, prices, discounts, allocation. | Adds `quantity`, `unitPrice`, `productGroupId`, `productMasterId`, `ean`, `parentLineId`, `noDiscount`, `noPercentageDiscount`, existing-discount text/campaign, `totals`, `requestedAt`. | Information proposed; names directional |
| Loyalty metadata on the transaction | Rich metadata (status, per-line breakdown, error, memberID filter) in V1 §15. | GUID confirmed and exposed as a meta attribute on the order in the REST API; everything else reconciled from REKOM's own records. Further meta attributes remain an open point. | Agreed 7 Oct 2026 and after / Open |
| Authentication | "Authentication" as part of webhook registration, unspecified. | HMAC-SHA256 request signatures (`OnlinePOS-Signature`), secret per environment; no scheduled rotation, REKOM swaps the secret itself with both secrets active during the overlap. | Proposed |
| Timeout and retries | "Up to three retries… within an agreed overall maximum timeout", numbers open. | p95 ≤ 150 ms / p99 ≤ 250 ms target on REKOM's side; POS timeout 500 ms per attempt, one connect-retry, hard cap 3 s. | Proposed |

## Store enrollment

Version 1 listed store enrollment with Nexi Engage as "currently not specced";
the 4 Sep update dropped the section. Version 2 documents the decision from the
separate "Rekom | Nexi Engage integration" thread:
**Option 1** (2 Sep 2026) — OnlinePOS adds a "Nexi Engage Store ID" field in
Backoffice terminal setup, REKOM fills it with the BAX ID, and the terminal runs
`registerstore` at every startup. See [Store enrollment](/architecture/store-enrollment).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.