Versioning and Changelog
Read first: Overview & Concepts · General Requirements
This page is the version story for the In-Store Loyalty API: how the protocol is versioned, which capability arrived in which version, what changed at each step, and how to migrate an existing integration forward. New integrations are recommended to build on version 1.5 or later — the latest is 1.7, and the rest of this document set describes it. Versions below 1.5 are deprecated: integrations built on them keep working for backward compatibility, but these versions are no longer part of the specification or this documentation set. Field-level detail for the supported versions lives in the In-Store Loyalty API specification.
1. How versioning works
The protocol version is part of every URL path: POST {baseUrl}/qr-code/1.7, POST {baseUrl}/order-closed/1.7, and so on. The pattern is {baseUrl}/{operation}/{version}. There is no version header and no content negotiation — the path is the version selector.
The OpenAPI specification describes the supported versions 1.5 through 1.7 as distinct paths — all four operation families (one-time-salt, qr-code, order-closed, refund) are present at each supported version. Deprecated paths (below 1.5) are not part of the spec; this Markdown describes only 1.7.
Which version an outlet uses is set in its configuration, not chosen per call: the sales-outlet config carries an apiVersion value (alongside fields including apiUrl, establishmentId, the establishment password, and the scan flow), and your integration calls the matching versioned path. New outlets are provisioned for 1.7. See Kiosk and POS Configuration for the full config contract.
Note: Use the same version on every operation within one order. The version of
order-closedandrefundmust match the version used for theqr-codevalidation that opened the order — mixing versions on a single order is not supported.
2. Capability × version matrix
Each row is a vendor-visible capability; each column a supported version. "added" marks the version that introduced the capability; "available" marks later versions where it remains in force. A blank cell means the capability does not exist in that version. Deprecated versions (below 1.5) are not shown.
| Capability | 1.5 | 1.6 | 1.7 |
|---|---|---|---|
QR-code validation (qr-code) | available | available | available |
SHA-256 AuthorizationToken auth | available | available | available |
Structured messages[] with numeric code | available | available | available |
payment object | available | available | available |
hasEverRewardedPoints in response | available | available | available |
maxPointsPercent in response | available | available | available |
customerEmail in response | added | available | available |
Structured modifiers + value/fixedPrice discounts | added | available | available |
Required total (qr-code); item price expected | added | available | available |
phone number-based flow (phoneNumber et al.) | — | added | available |
customerTier + customerPointsBalance | — | — | added |
publicClientId lookup | — | — | added |
3. Per-version changelog
Concise, vendor-facing deltas. Each entry states what a vendor would notice on the wire; field-level detail lives in the spec.
- 1.7 (latest) — Added customer tier name (
customerTier) and points balance (customerPointsBalance) to theqr-coderesponsecustomerblock (both nullable, best-effort enrichment), and a third identification method:publicClientIdlookup. Additive and non-breaking over 1.6. - 1.6 — Added the phone number-based flow: identify or register a customer by
phoneNumberinstead of a QR code — the customer enters their number on the self-service kiosk, or the cashier enters it at the cash register / POS terminal — with optionalclientNameandsubscribedToPushNotifications. The same fields appear onorder-closed. - 1.5 — Restructured the order model: modifiers changed from string arrays to objects (
itemId,title,price,quantity); discounts moved to a singlevaluefield with a newfixedPricetype;totalbecame required on theqr-coderequest, and itemtitle/priceare expected onqr-codemenu items per the migration contract. Also addedcustomer/customerEmailto theqr-coderesponse (exposed only when the outlet has the additional-customer-info feature enabled). - 1.0–1.4 (deprecated) — legacy versions predating the 1.5 order-model restructure; versions 1.0–1.3 additionally use the legacy MD5
Signatureauth scheme. They are no longer part of the specification or this documentation set; integrations built on them keep working for backward compatibility. To move to a supported version, see Section 4.1.
4. Migration guides
Each guide covers moving to the named version. Apply them cumulatively if you skip versions — e.g. moving from a deprecated version to 1.7 means doing 4.1, 4.2, and 4.3 in order.
4.1 From a deprecated version (below 1.5) — to 1.5
Versions below 1.5 are deprecated; moving off them means two changes — authentication and the order-model structure.
Authentication. Versions 1.0–1.3 send a Signature header equal to MD5(requestBody + apiPrivateKey + salt), and the server signs its response with the same scheme. From 1.4 on, send an AuthorizationToken header equal to SHA256(apiPrivateKey + salt) (key first, request body excluded), and the response is unsigned.
- Replace the
Signatureheader withAuthorizationToken(keepSaltId, which is unchanged — it is sent on both legacy and current requests). - Compute the token as
SHA256(apiPrivateKey + salt), lowercase hex — the request body is no longer part of the hash. - Stop verifying the response
Signatureheader; responses are not signed anymore. - Start handling HTTP 400 validation errors: a JSON object mapping each invalid field's JSON-Pointer path to a reason.
The token mechanics are detailed in the QR Code Loyalty Guide.
Order model. 1.5 reshapes the order model. The change is in field structure, not new operations.
| Deprecated (pre-1.5) shape | 1.5+ shape |
|---|---|
discount: type (percent/amount) + percent/amount field | discount: type (percent/amount/fixedPrice) + single value field |
modifiers: array of strings (["EXTRA_CHEESE"]) | modifiers: array of objects ({itemId, title, price, quantity}) |
qr-code menu item: title/price optional, no total | qr-code menu item: title/price expected (per migration contract); request total required |
To migrate: convert every discount's percent/amount field to a single value (e.g. {"type":"percent","percent":10} → {"type":"percent","value":10}); convert each modifier string into an object with itemId, title, price, quantity; add price to every order item; and add total to the qr-code request. The new fixedPrice discount type is optional — use it only if needed.
Note: The OpenAPI
MenuItem.requiredset is[itemId, quantity]— itemtitleandpriceare not flagged required by the machine schema. Their requiredness at 1.5+ comes from the migration business contract and server-side validation, not the OpenAPIrequiredlist. Sending them is always safe. Warning: Thevalue/fixedPricediscount shape and modifier objects apply to bothqr-codeandorder-closed. Update the order composition in both requests, ororder-closedwill fail schema validation.
4.2 To 1.6 — phone number-based flow
1.6 adds the phone number-based flow and is otherwise unchanged from 1.5 on the wire for existing QR-code traffic — your QR validation keeps working as-is. To adopt the new capability:
- On
qr-code, sendphoneNumber(international format) instead ofqrCode, optionally withclientNameandsubscribedToPushNotifications— the customer enters their number on the self-service kiosk, or the cashier enters it at the cash register / POS terminal. - Echo the same
phoneNumber,clientName, andsubscribedToPushNotificationsonorder-closedfor that order.
Full implementation is in the Phone Number Guide. Migrating from a deprecated version requires doing 4.1 first.
4.3 To 1.7 — tier, balance, and publicClientId
1.7 is additive and non-breaking over 1.6. A 1.6 client can move to the /1.7 paths with no request changes and will simply start receiving two extra response fields. To use the new features:
- Read
customer.customerTier(tier name, e.g."Gold") andcustomer.customerPointsBalance(points balance) from theqr-coderesponse when present, and surface them at the point of payment. - Optionally, identify a customer by
publicClientIdinstead ofqrCode/phoneNumber.
Warning:
customerTierandcustomerPointsBalanceare best-effort enrichment and may benullin a successful (accepted: true) response if the backing lookup is unavailable. Treat them as optional display data; never gate the flow on their presence. Note: When more than one identifier is sent, the in-store API resolves them in priority orderqrCode→phoneNumber→publicClientId; if none is sent, the request is rejected.
5. Support and deprecation policy
- Versions below 1.5 are deprecated. Integrations built on the
1.0–1.4paths keep working for backward compatibility, but these versions have been removed from the specification and this documentation set. To move to a supported version, see Section 4.1. - New integrations are recommended to build on 1.5 or later. 1.7 is the latest version, and this documentation set describes it.
- The legacy Integration Server XML protocol is out of scope. The older session-based in-store protocol ("Фабрика Лояльности" / Universal Protocol) is a separate, deprecated product and is not documented here; the In-Store Loyalty API is the current in-store API.
Note: No end-of-life dates are published for any version of the in-store API. If LoyaltyPlant schedules the retirement of a legacy version for your integration, it is communicated through your integration contact, not through this document.
Next: Message & Error Codes →