> ## 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.

# Open points

> Everything still unresolved, with an owner, REKOM's proposal where there is one, and the milestone it blocks.

<Note>
  "Needed before" uses three milestones: **Contract** (joint sign-off of the API
  contract), **Phase 1 live** (first venue with lookup), **Phase 2 live** (first venue
  with discounts).
</Note>

## Owned by OnlinePOS

| # | Point | REKOM proposal | Needed before |
| - | - | - | - |
| O1 | **Timeout and retry numbers** for the basket call, inside the BAXI prepurchase window. | 500 ms per attempt, one connect-only retry, hard cap 3 s; REKOM targets p95 ≤ 150 ms / p99 ≤ 250 ms. Joint measurement on staging with `Server-Timing`. | Contract |
| O2 | **Discount code value.** The exact predefined, semantic string for the catch-all third-party-loyalty discount type (`lineDiscountCode`), and how POS maps it to its note line and discount categorisation. | `loyalty`, one string for amount and percentage discounts. | Contract |
| O3 | **Meta attributes beyond the GUID.** The GUID is exposed as a meta attribute on the order (agreed after 7 Oct). Can the loyalty ID and the order loyalty status be stored as meta attributes too, and is the Phase 1 tag readable via REST? Can the transaction list be filtered by loyalty ID? | Store `loyaltyId` and loyalty status as meta attributes next to the GUID; REKOM only requires the GUID. | Phase 1 live (loyalty ID), Phase 2 live (status) |
| O4 | **Swapping existing discounts.** Confirm that OnlinePOS applies the returned basket as-is when REKOM has replaced or removed a staff discount, a product price discount or an order discount, and that no POS-side combination rule is involved (6 Oct: "REKOM follows POS's rules for combining discounts"). | The logic is REKOM's: keep the existing discount, or swap it for a larger loyalty discount. OnlinePOS validates arithmetic and product identity only. | Contract |
| O5 | **Product identity across venues**: is `productMasterId` reliable for the same product in different venues, or should REKOM key on EAN or per-venue IDs? | Send all three on each line; REKOM keys on `productMasterId` when present, else EAN, else venue `productId`. | Contract |
| O6 | **Split payments, tabs, partial card payments.** | Loyalty runs only when a single card payment settles the full basket; otherwise `not_applicable`. | Contract |
| O7 | **Webhook registration mechanics**: what is registrable, per venue or per partner, event names, where the secret is entered. | One base URL and one secret per environment per partner, with REKOM able to update the secret itself; per-venue activation in Backoffice. | Phase 2 live |
| O8 | **Money unit**: confirm integer minor units in the loyalty payloads (the REST API uses decimal strings). | Integer minor units + `currency`. | Contract |
| O9 | **Clocks**: NTP on Windows POS hosts; timezone semantics of the REST API `datetime` fields. | RFC 3339 with offset in loyalty payloads; signatures ±300 s. | Contract |
| O10 | **Limits**: 200 lines, 256 KB body, 50 rps sustained — acceptable? Egress IPs for allowlisting? | As stated in [Configuration and security](/architecture/configuration-and-security#limits). | Contract |
| O11 | **Basket object format and names.** OnlinePOS stated (6 Oct) that POS/mPOS define the order object. Every field name, enum value, header and structure in this document and the draft OpenAPI is directional. | OnlinePOS shares its default order object and webhook conventions; REKOM adopts them and maps the information in this document onto them. | Contract |
| O12 | **Legal-discount flag per line.** Confirm that `noDiscount` is populated from the product's `no_discount` setting on every line, including option lines, and whether any legal restriction exists that the flag does not cover. REKOM needs it to split order-level benefits correctly (3 Sep 2026). | Flags as drafted, mandatory on every line; `400` if missing. | Contract |
| O13 | **Added and split lines.** For lines REKOM adds: does OnlinePOS take `unitPrice` from the response or re-price from its own price list? Any convention for new `lineId`s? | OnlinePOS re-prices added lines from the venue price list and rejects a mismatch; REKOM prefixes new ids with `rk-`. | Contract |

## Owned by OnlinePOS and Nexi

| # | Point | REKOM proposal | Needed before |
| - | - | - | - |
| ON1 | **Single approval via BAXI on Windows**: confirm that the prepurchase step gives the POS a window to update the amount before authorisation, and how long it is. | None; this bounds O1. | Contract |
| ON2 | **One-time JWT store token for `registerstore`** under Option 1: needed at all? Who fetches it, how it reaches the terminal, fresh per startup? Endpoint and credentials. | If needed, the OnlinePOS backend fetches it at startup with credentials REKOM provides; nothing in the terminal boot path depends on REKOM. | Phase 1 live |

## Owned by both

| # | Point | REKOM proposal | Needed before |
| - | - | - | - |
| B1 | **Same member in two open baskets** at once (two tills). | Benefits with a quantity limit are reserved at calculation and released on `cancelled`, supersession or expiry; first sale wins; the second calculation returns `unchanged` for the exhausted benefit. | Phase 2 live |
| B2 | **Test plan**: test venues, test BAX IDs as Nexi test stores, staging secrets, a joint latency run. | REKOM provides staging host, secret and a test member; OnlinePOS provides a test venue and terminal. | Phase 1 live |

## Owned by Nexi

| # | Point | Note | Needed before |
| - | - | - | - |
| N1 | **`loyaltyId` format** as returned by `getasset` and Softpay: length, character set, stability. | OnlinePOS treats it as an opaque string ≤ 64 chars until confirmed. | Contract |
| N2 | **Shared Slack channel** and Baxi / Engage API documentation hand-over to REKOM. | Promised for when work starts. | Phase 1 live |
| N3 | **DAM API-based enrollment** (≈ 2 months). | Parked; raised as a general improvement only. | — |

## REKOM-internal (for completeness)

| # | Point | Note |
| - | - | - |
| R1 | Guest card-enrolment channel (Nexi Engage API versus terminal action). | Does not affect OnlinePOS. |
| R2 | Consolidation to one BAX per venue (depends on Nets reconciliation window). | Does not affect the design; the field holds whatever BAX the setup uses. |
| R3 | Hosts `loyalty.xeniamoments.com` / `loyalty-staging.xeniamoments.com` go live (DNS, certificates). | Marked TBC throughout. |

## Resolved in this document

| Was open | Resolution |
| - | - |
| `memberID` versus `loyaltyID` naming | "loyalty ID" in prose; the payload field name is directional and follows OnlinePOS's default. |
| "Three" versus four webhooks in the 4 Sep text | Two REKOM endpoints: `POST /v1/onlinepos/basket` and `POST /v1/onlinepos/sale`. |
| How `unchanged` is signalled | Explicit `unchanged` response with `reason`, no lines (7 Oct 2026). |
| Correlation between systems | Calculation GUID (7 Oct 2026), exposed as a meta attribute on the order in the REST API (after 7 Oct 2026). |
| Campaign ID provisioning | Not needed: loyalty discounts carry the predefined catch-all discount code instead of a campaign ID (after 7 Oct 2026); only the exact string is open (O2). |
| Venue attribution of orders | BAX number and terminal identifier are required in the order sent to REKOM (after 7 Oct 2026). |
| Store enrollment ownership | Option 1 (2 Sep 2026), token hand-over still open (ON2). |


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