☰ Меню · Правила й ліміти закладу
Посібники

Правила й ліміти закладу

Як заклад керує тим, що можуть робити підключені каси: рівні кешбеку, категорії товарів, резерви, нумерація чеків, чеки, надіслані пізніше, ліміти та перевірка скану.

Усе, що описано на цій сторінці, власник закладу налаштовує в розділі Розробникам → Правила для кас. Правила діють для всіх ключів API закладу, а для окремого ключа (однієї каси, одного кіоску) будь-яке з них можна задати по-своєму. Ваша інтеграція отримує правила, за якими працює, з GET /v1/account, у полі settings.

JSON
"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
}

Рівні кешбеку

Програма з кешбеком може мати рівні: наприклад, Базовий 5%, Срібний 7% з другого візиту, Золотий 10% після 1000.00 покупок. Рівні рахуються за візитами, за сумою покупок або за тим, що настане раніше. Власник задає їх у програмі лояльності. На боці каси нічого робити не потрібно: кожен чек нараховує кешбек за рівнем, який гість має після цього чека, а в кожному об’єкті учасника видно, на якому рівні гість.

JSON
"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 і next_level.spent_left можна одразу показати гостю («ще 2 візити до Срібного»). У display.receipt_lines цей рядок уже є мовою гостя.

Категорії товарів

Один раз вивантажте товари з їхніми категоріями, а далі надсилайте лише зміни. Категорії з’являються в кабінеті власника, і для кожної з них можна задати, що вона не нараховує кешбек (тютюн, алкоголь), що її не можна оплатити кешбеком (товари, які вже в акції), або що вона нараховує власний відсоток замість рівня гостя (кава 10%). Через API можна створювати товари й категорії та перейменовувати їх, але змінювати ці правила може лише власник.

curl
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 }

Потім передавайте line_items з кожним чеком. Позиція може мати category або лише sku, тоді категорію ми знайдемо в каталозі. Суми позицій масштабуються до суми чека, тож знижки, зроблені на боці каси, розподіляються пропорційно. Позиції з категорій без правил нараховують кешбек за рівнем гостя.

curl
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": 775

Оплата кешбеком через резерв

У режимі У чеку (за замовчуванням) каса передає redeem_amount разом із закритим чеком. У режимі Через резерв каса відкладає суму, щойно гість просить оплатити кешбеком, а закритий чек її підтверджує. Якщо чек так і не надійшов (зник зв’язок, продаж скасовано), резерв знімається через час, який задав власник, і гроші залишаються в гостя. Знижка ніколи не надається без списання з балансу.

  1. 1
    Резерв

    POST /v1/holds з учасником, сумою та сумою чека. Діють ті самі обмеження, що й для чека. У відповіді є id резерву.

  2. 2
    Підтвердження

    POST /v1/transactions з hold_id. Не передавайте redeem_amount, щоб використати весь резерв, або передайте меншу суму.

  3. 3
    Або зняття

    POST /v1/holds/{id}/release, якщо продаж скасовано. Повторне зняття нічого не зламає.

curl
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 учасника, у лімітах і у власному касовому застосунку закладу, тож ту саму суму не можна витратити двічі.

Номери чеків для кожної каси

Якщо кожна каса рахує чеки з 1, виберіть У кожної каси свої. Тоді register_id обов’язковий, а чек зберігається як <register_id>:<external_id>, наприклад R3:15. Використовуйте цей складений id, щоб прочитати, скасувати чек або зробити повернення.

Чеки, надіслані пізніше

Після збою каса надсилає накопичену чергу. Якщо ліміт становить, скажімо, 72 години, чеки зі старішим closed_at відхиляються з check_too_old. Так каса, відновлена зі старої резервної копії, не завалить заклад застарілими чеками. Чек із closed_at більш ніж на 10 хвилин у майбутньому відхиляється завжди.

Ліміти списання

Крім частки чека, заданої в програмі, власник може обмежити кешбек на один чек і на одного гостя за день (для всіх кас разом, за часовим поясом закладу). Якщо чек просить більше, списується дозволена сума, і відповідь показує фактичний redeem_amount. Резерв на більшу суму відхиляється з limited_by. Щоб заздалегідь показати гостю точну суму, скористайтеся розрахунком.

Обов’язковий скан картки

З цим правилом чек, візит, резерв чи нагорода для картки приймаються, лише якщо той самий ключ незадовго до цього надіслав цю картку в POST /v1/scans. Номер картки, введений на касі вручну, відхиляється з scan_required. Надсилайте сирий вивід сканера в /v1/scans, а далі працюйте як зазвичай.

Ручні коригування

За замовчуванням вимкнені. Якщо власник їх дозволив, ключ із правом members:adjust може нарахувати або зняти кешбек із зазначенням причини, у межах ліміту на одне коригування, який задав власник. Кожне коригування потрапляє в історію учасника й надсилає balance.adjusted.

curl
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
Питання щодо інтеграції: api@loyaltyfy.io. Відповідаємо протягом одного робочого дня.