☰ Meniu · Regulile localului și limite
Regulile localului și limite
Cum controlează localul ce pot face casele conectate: niveluri de cashback, categorii de produse, rezervări, numerotarea bonurilor, bonuri trimise mai târziu, limite și verificarea scanării.
Tot ce este pe această pagină se setează de proprietarul localului în Dezvoltatori → Reguli pentru case. Regulile se aplică tuturor cheilor API ale localului; o singură cheie (o casă, un chioșc) poate avea valori proprii pentru oricare dintre ele. Integrarea ta citește regulile după care lucrează din GET /v1/account, în settings.
"settings": {
"redemption": "hold",
"hold_minutes": 30,
"check_numbering": "per_register",
"offline_max_hours": 72,
"redeem_max_per_check": 50000,
"redeem_max_per_day": null,
"require_scan": true,
"scan_window_minutes": 30,
"allow_adjustments": false,
"adjustment_max": 50000
}Niveluri de cashback
Un program de cashback poate avea niveluri: de exemplu De bază 5%, Silver 7% de la a doua vizită, Gold 10% de la 1000,00 cheltuiți. Nivelurile se calculează după vizite, după suma cheltuită sau după ce se atinge primul. Proprietarul le setează în programul de fidelitate. Pe partea casei nu trebuie făcut nimic: fiecare bon acumulează la nivelul pe care oaspetele îl are după acel bon, iar fiecare obiect member îți arată unde se află oaspetele.
"cashback": {
"balance": 10200,
"held": 0,
"available": 10200,
"currency": "MDL",
"earn_rate": 7,
"level": "Silver",
"level_basis": "any",
"levels": [
{ "name": "Base", "earn_rate": 5, "min_visits": null, "min_spent": null },
{ "name": "Silver", "earn_rate": 7, "min_visits": 2, "min_spent": null },
{ "name": "Gold", "earn_rate": 10, "min_visits": null, "min_spent": 100000 }
],
"next_level": { "name": "Gold", "earn_rate": 10, "visits_left": null, "spent_left": 80000 },
...
}next_level.visits_left și next_level.spent_left pot fi afișate direct oaspetelui ("încă 2 vizite până la Silver"). display.receipt_lines conține deja acest rând în limba oaspetelui.
Categorii de produse
Încarcă o dată produsele cu categoria lor, apoi trimite doar modificările. Categoriile apar în panoul proprietarului, unde fiecare poate fi setată să nu acorde cashback (tutun, alcool), să nu poată fi plătită cu cashback (produse deja la promoție) sau să acorde un procent propriu în locul nivelului oaspetelui (cafea 10%). API-ul poate crea și redenumi produse și categorii, dar numai proprietarul schimbă aceste reguli.
curl https://loyaltyfy.io/api/v1/catalog/products/bulk \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"products": [
{ "sku": "4840001", "name": "Marlboro Gold", "category": "TOB", "category_name": "Tobacco", "price": 6500 },
{ "sku": "1001", "name": "Latte", "category": "COF", "category_name": "Coffee", "price": 4500 },
{ "sku": "2040", "name": "Zeama", "category": "KIT", "category_name": "Kitchen", "price": 6500 }
]
}'
# { "object": "catalog_sync", "upserted": 3 }Apoi trimite line_items cu fiecare bon. O linie poate avea category sau doar sku: căutăm categoria în catalog. Totalurile liniilor sunt scalate la suma bonului, așa că reducerile făcute pe casă se distribuie corect. Liniile din categorii fără reguli acumulează la nivelul oaspetelui.
curl https://loyaltyfy.io/api/v1/transactions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"external_id": "CHK-2026-000130",
"member": "2000111703779",
"amount": 17500,
"line_items": [
{ "sku": "4840001", "quantity": 1, "unit_price": 6500 },
{ "sku": "1001", "quantity": 1, "unit_price": 4500 },
{ "sku": "2040", "quantity": 1, "unit_price": 6500 }
]
}'
# Tobacco earns nothing, Coffee has its own 10%, Kitchen earns at the guest's level (5%):
# 0 + 450 + 325 = "cashback_earned": 775Plata cu cashback prin rezervare
Cu În bon (implicit), casa trimite redeem_amount împreună cu bonul închis. Cu Prin rezervare, casa pune suma deoparte când oaspetele cere să plătească cu cashback, iar bonul închis o confirmă. Dacă bonul nu mai vine (a căzut rețeaua, vânzarea a fost anulată), rezervarea se eliberează după timpul stabilit de proprietar, iar banii rămân la oaspete. Nicio reducere nu se acordă fără să fie scăzută din sold.
- 1Rezervă
POST /v1/holdscu membrul, suma și totalul bonului. Se aplică aceleași plafoane ca la un bon. Răspunsul conțineid-ul rezervării. - 2Confirmă
POST /v1/transactionscuhold_id. Omiteredeem_amountca să folosești toată rezervarea sau trimite o sumă mai mică. - 3Sau eliberează
POST /v1/holds/{id}/releasecând vânzarea este anulată. O eliberare repetată nu are niciun efect.
curl https://loyaltyfy.io/api/v1/holds \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hold-R3-000131" \
-d '{ "member": "2000111703779", "amount": 3000, "check_amount": 20000, "register_id": "R3" }'
# at payment: the check captures it
curl https://loyaltyfy.io/api/v1/transactions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "external_id": "000131", "register_id": "R3", "member": "2000111703779",
"amount": 20000, "hold_id": "5b0d6c1e-8f3a-4d7e-9a61-2c4b8e0f7d19" }'cashback.available al membrului, în limite și în aplicația de casă a localului, așa că aceiași bani nu pot fi cheltuiți de două ori.Numerele bonurilor pe fiecare casă
Dacă fiecare casă numără bonurile de la 1, alege Fiecare casă are numerotarea ei. Atunci register_id devine obligatoriu, iar bonul este salvat ca <register_id>:<external_id>, de exemplu R3:15. Folosește acest id combinat ca să citești, să anulezi sau să returnezi bonul.
Bonuri trimise mai târziu
După o întrerupere, casa își trimite coada. Cu o limită de, să zicem, 72 de ore, bonurile al căror closed_at este mai vechi sunt refuzate cu check_too_old, așa că o casă restaurată dintr-o copie de rezervă veche nu poate umple localul cu bonuri expirate. Un closed_at cu mai mult de 10 minute în viitor este refuzat întotdeauna.
Limite de folosire
Pe lângă partea din bon stabilită de program, proprietarul poate seta suma maximă de cashback pe bon și pe oaspete pe zi (toate casele împreună, după fusul orar al localului). Un bon care cere mai mult folosește cât este permis, iar răspunsul arată redeem_amount real; o rezervare care cere mai mult este refuzată cu limited_by. Folosește calculul ca să-i arăți mai întâi oaspetelui suma exactă.
Cardul trebuie scanat
Cu această regulă, un bon, o vizită, o rezervare sau o recompensă pentru un card sunt acceptate doar dacă aceeași cheie a trimis cardul la POST /v1/scans cu puțin înainte. Un număr de card tastat de mână pe casă este refuzat cu scan_required. Trimite la /v1/scans ce a produs scanerul, fără modificări, apoi continuă ca de obicei.
Corecții manuale
Dezactivate implicit. Când proprietarul le permite, o cheie cu permisiunea members:adjust poate adăuga sau scădea cashback cu un motiv, până la limita stabilită de proprietar pentru o corecție. Fiecare corecție apare în istoricul membrului și trimite balance.adjusted.
curl https://loyaltyfy.io/api/v1/members/2000111703779/adjustments \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "external_id": "ADJ-2026-0009", "amount": 2000, "reason": "Goodwill after a complaint" }'
# a negative amount takes cashback away