“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).
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. | 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 lineIds? | 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). |