Loyalty card resolved successfully
Show this when the card belongs to the current merchant.
Use this API to pair an installation, read a card, list rewards, and commit a transaction.
Call /card during checkout. Call /rewards for points or stamps. Call /transaction
after receipt close.
POST /pair.POST /card.POST /transaction.{
"cardToken": "DISC00000000000000000000"
}
// Read card
const cardResponse = await fetch('/card', {
method: 'POST',
headers: {
Authorization: 'Bearer pos_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({ cardToken })
})
const card = await cardResponse.json()
// Apply discount locally
if (card.programType === 'DISCOUNT') {
applyDiscount(card.discountPercent)
}
// Commit transaction
await fetch('/transaction', {
method: 'POST',
headers: {
Authorization: 'Bearer pos_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
transactionId,
cardToken,
type: 'ADD',
amountOriginal,
amountPaid,
status: 'CONFIRMED'
})
})
| Environment | Base URL | Usage |
|---|---|---|
| PROD | https://loyalty.nuvio.group/api/pos/v1 |
Use this for live partner installations. |
| DEV | https://dev.loyalty.nuvio.group/api/pos/v1 |
Use this for integration work and validation. |
| Local | http://localhost:3300/api/pos/v1 |
Use this for local wrapper development. |
Partners use only /api/pos/v1/*. Internal terminal routes stay private.
Send a partner API key on every runtime request.
Authorization: Bearer pos_<api_key>
| Route | Authentication |
|---|---|
POST /pair |
No partner key required. |
POST /card |
Partner key required. |
POST /rewards |
Partner key required. |
POST /transaction |
Partner key required. |
GET /health |
No authentication required. |
Pair each POS installation once. Store the returned API key securely.
POST /pair.POST /api/pos/v1/pair
{
"pairingCode": "1234-5678",
"deviceFingerprint": "register-01",
"source": "android-pos",
"installationName": "Front counter"
}
200 OK
{
"status": "PAIRED",
"merchantId": "merch_demo_krk",
"merchantName": "Nuvio Demo Merchant",
"apiKey": "pos_xxxxxxxxxxxxxxxxxxxxxx",
"baseUrl": "https://loyalty.nuvio.group/api/pos/v1"
}
Build one internal adapter for all /api/pos/v1 calls.
| Layer | Partner builds | Nuvio provides |
|---|---|---|
| Settings | Pairing field and secure key storage. | Merchant resolution and key issuance. |
| Runtime adapter | HTTP client for /api/pos/v1/*. |
Loyalty logic and card state. |
| Cashier UI | Prompts, tiles, and checkout controls. | Reward availability and balances. |
| Checkout | Discount, tenders, receipt close, fiscalization. | Post-checkout accrual and redemption. |
Nuvio returns loyalty state. The partner controls checkout and receipt close.
| Concern | Partner POS | Nuvio |
|---|---|---|
| Card scanning | Read scanner input and pass cardToken. |
Resolve token to active loyalty state. |
| Discount | Apply price change locally. | Return current discount entitlement. |
| Cashback | Apply chosen cashback locally. | Return balance and burn committed amount. |
| Rewards | Show tiles and send selected reward id. | Return eligibility and burn rewards. |
| Final commit | Send final amounts after receipt close. | Persist loyalty outcome. |
POST /card to resolve the program.POST /rewards for points or stamps.POST /transaction with final values.Scanner input -> Partner loyalty adapter -> Nuvio Partner POS API
|
+-> Partner cashier UI
+-> Partner checkout engine
+-> Partner receipt close and fiscalization
+-> Final transaction commit
/pair
Bind one POS installation to one merchant.
| Field | Type | Required | Description |
|---|---|---|---|
pairingCode | string | yes | Merchant-issued code. Example: 1234-5678. |
deviceFingerprint | string | yes | Stable device or installation id. |
source | string | no | Partner source name. |
installationName | string | no | Human-readable register name. |
| Field | Type | Description |
|---|---|---|
status | string | Expected value: PAIRED. |
merchantId | string | Nuvio merchant id. |
merchantName | string | Merchant display name. |
apiKey | string | Partner key for runtime calls. |
baseUrl | string | Environment base URL. |
| Status | Meaning |
|---|---|
| 200 | Pairing succeeded. |
| 400 | Request is invalid. |
| 404 | Pairing code is invalid or expired. |
/card
Resolve the scanned card and return the active program state.
| Field | Type | Required | Description |
|---|---|---|---|
cardToken | string | yes | Scanned loyalty token or normalized card id. |
{
"merchantId": "merch_demo_krk",
"cardToken": "DISC00000000000000000000",
"programType": "DISCOUNT",
"discountPercent": 10,
"currentTier": "silver",
"nextTier": "gold"
}
{
"merchantId": "merch_demo_krk",
"cardToken": "CASH0000000000000000000",
"programType": "CASHBACK",
"cashbackBalance": 3000,
"cashbackRate": 10
}
{
"merchantId": "merch_demo_krk",
"cardToken": "POINT0000000000000000000",
"programType": "POINTS",
"pointsBalance": 320,
"readyRewards": 2
}
/rewards
Return merchant-defined rewards for points or stamps cards.
| Field | Type | Required | Description |
|---|---|---|---|
cardToken | string | yes | Scanned loyalty token or normalized card id. |
{
"merchantId": "merch_demo_krk",
"cardToken": "POINT0000000000000000000",
"member": {
"points_balance": 320,
"ready_rewards": 2
},
"rewards": [
{
"reward_id": "points_0_100",
"name": "100 pts = Hot dog",
"required_points": 100,
"type": "POINTS"
},
{
"reward_id": "points_1_200",
"name": "200 pts = Coffee",
"required_points": 200,
"type": "POINTS"
}
]
}
{
"merchantId": "merch_demo_krk",
"cardToken": "STMP0000000000000000000",
"member": {
"stampsBalance": 10,
"stampsRequired": 10,
"readyRewards": 1
},
"rewards": [
{
"reward_id": "stamp_0_10",
"name": "10 stamps = Ice cream scoop",
"required_stamps": 10,
"type": "STAMPS"
}
]
}
/transaction
Send the final loyalty result after receipt close.
| Field | Type | Required | Description |
|---|---|---|---|
transactionId | string | yes | Partner transaction id used for idempotency. |
cardToken | string | yes | Card token used in the sale. |
type | enum | yes | ADD, REDEEM, or REDEEM_REWARD. |
amountOriginal | integer | conditional | Original basket value in minor units. |
amountPaid | integer | conditional | Final paid value in minor units. |
cashbackUsed | integer | no | Redeemed cashback in minor units. |
selectedReward | string | no | Selected reward identifier. |
status | enum | yes | Usually CONFIRMED. |
paymentMethod | string | no | Partner-side payment method label. |
metadata | object | no | Partner trace metadata. |
| Type | Required fields | Optional fields |
|---|---|---|
ADD |
transactionId, cardToken, amountOriginal, amountPaid, status |
paymentMethod, metadata |
REDEEM |
transactionId, cardToken, amountOriginal, amountPaid, cashbackUsed, status |
paymentMethod, metadata |
REDEEM_REWARD |
transactionId, cardToken, selectedReward, status |
amountOriginal, amountPaid, paymentMethod, metadata |
{
"merchantId": "merch_demo_krk",
"transactionId": "txn_1001",
"cardToken": "DISC00000000000000000000",
"status": "CONFIRMED",
"programType": "DISCOUNT",
"pointsEarned": 0,
"pointsBalance": 0,
"cashbackEarned": 0,
"cashbackBalance": 0,
"discountSavings": 2000
}
{
"merchantId": "merch_demo_krk",
"transactionId": "txn_cashback_1002",
"cardToken": "CASH0000000000000000000",
"status": "CONFIRMED",
"programType": "CASHBACK",
"cashbackUsed": 3000,
"cashbackBalance": 0,
"amountPaid": 7000
}
{
"merchantId": "merch_demo_krk",
"transactionId": "txn_reward_1003",
"cardToken": "POINT0000000000000000000",
"status": "CONFIRMED",
"programType": "POINTS",
"selectedReward": "points_0_100",
"pointsBalance": 220
}
Reuse the same transactionId on every retry for the same receipt.
/health
Use this for deployment checks and runtime diagnostics.
All failures return the same JSON object.
{
"error": {
"code": "INVALID_INPUT",
"message": "cardToken is required.",
"requestId": "req_01JERR2YJ2V8"
}
}
| Field | Type | Description |
|---|---|---|
code | string | Stable machine-readable error id. |
message | string | Developer-readable message. |
requestId | string | Correlation id for support. |
{
"error": {
"code": "PAIRING_CODE_INVALID",
"message": "The provided pairing code is invalid or expired.",
"requestId": "req_01JPAIR7Y8X4"
}
}
{
"error": {
"code": "CARD_NOT_FOUND",
"message": "The scanned card could not be resolved for this merchant.",
"requestId": "req_01JCARD4X1E0"
}
}
{
"error": {
"code": "TRANSACTION_ALREADY_PROCESSED",
"message": "The transactionId was already processed for this merchant.",
"requestId": "req_01JTXN9M4C1",
"idempotentReplay": true
}
}
POST /card.discountPercent.| Stage | Partner action | Nuvio effect |
|---|---|---|
| Card read | Read discount and tier data. | Return active entitlement. |
| Checkout | Reduce basket total locally. | No local checkout calculation in Nuvio. |
| Commit | Send final amounts. | Update sale history and tier progression. |
POST /card.Sale total: 100.00 PLN
Cashback available: 30.00 PLN
POS behavior:
- 30.00 PLN covered by cashback
- 70.00 PLN collected normally
Commit payload:
{
"transactionId": "txn_cashback_1002",
"cardToken": "CASH0000000000000000000",
"type": "REDEEM",
"amountOriginal": 10000,
"amountPaid": 7000,
"cashbackUsed": 3000,
"status": "CONFIRMED"
}
| Branch | Partner action | Transaction type | Nuvio effect |
|---|---|---|---|
| Cashback used | Reduce payable amount locally. | REDEEM | Burn committed cashback amount. |
| Cashback not used | Close checkout normally. | ADD | Accrue new cashback after commit. |
Nuvio owns balances, reward availability, accrual rules, and burn logic.
| Program | Read | Display | Commit |
|---|---|---|---|
| Points | POST /card + POST /rewards |
Points balance and reward tiles. | REDEEM_REWARD or ADD |
| Stamps | POST /card + POST /rewards |
Stamp progress and reward tiles. | REDEEM_REWARD or ADD |
1. Call POST /card
2. If programType is POINTS or STAMPS, call POST /rewards
3. Render rewards as partner-owned tiles
4. If cashier selects a reward, commit REDEEM_REWARD
5. If no reward is selected, close checkout and commit ADD
Keep your own UI. Keep the same decision points.
Show this when the card belongs to the current merchant.
Show available balance and the remaining payable amount.
Render points or stamps rewards as clickable partner-owned tiles.
| Component | Required implementation |
|---|---|
| Settings screen | One pairing field and secure partner key storage. |
| Loyalty adapter | Dedicated service layer for all /api/pos/v1/* calls. |
| Scanner input | Stable cardToken normalization. |
| Cashier prompts | Local prompts for discount, cashback, and rewards. |
| Checkout integration | Ability to reduce basket amount locally. |
| Transaction commit | One final commit after receipt close. |
| Retry handling | Reuse the same transactionId on retries. |
| Support logging | Persist request ids and wrapper error codes. |
Partners do not need Nuvio styling, local loyalty balance storage, or direct terminal API access.
| Control | Requirement |
|---|---|
| Kill switch | Support global, partner-level, and merchant-level disable. |
| Logging | Log request id, partner id, merchant id, transaction id, and latency. |
| Rate limiting | Apply partner-level and merchant-level limits. |
| Auditability | Persist pairing events, key issuance, and idempotent results. |
Use DEV for all validation. There is no separate UAT environment.
| Scenario | Route sequence | Expected result |
|---|---|---|
| Discount checkout | /pair → /card → /transaction |
POS applies discount locally and commits final values. |
| Cashback partial redeem | /pair → /card → /transaction |
Cashback covers part of the basket and burns only the committed amount. |
| Points reward redemption | /pair → /card → /rewards → /transaction |
Selected reward is burned and new balance is returned. |
| Stamp reward redemption | /pair → /card → /rewards → /transaction |
Ready reward is consumed after explicit cashier action. |
Use these files in the public Git package.
| Artifact | Location | Purpose |
|---|---|---|
| Reference screens | /reference-screens.html | Cashier UI reference set. |
| Download package README | /downloads/README.md | Entry point for the public package. |
| Integration checklist | /downloads/integration-checklist.md | Build checklist for partner teams. |
| Testing scenarios | /downloads/dev-validation-scenarios.md | DEV validation scenarios. |
| JSON examples | /downloads/json/... | Request and response examples. |
| Reference integration sample | /downloads/reference-integration-sample.md | Suggested internal module layout. |
| Artifact | Purpose |
|---|---|
| Download package README | Defines the public package structure. |
| JSON request and response examples | Give engineers direct payload references. |
| Reference integration sample | Shows the hidden virtual terminal module layout. |
| DEV validation card set | Supports controlled validation in DEV. |
| Reference screen pack | Gives product and engineering teams UI references. |
| Integration checklist | Summarizes required platform work. |