☰ Меню · POS і каси
POS і каси
Усе, що потрібно касі: знайти гостя, провести чек, списати кешбек, обробити повернення та випустити картки з власними номерами каси.
Звичайний сценарій на касі: касир сканує картку гостя в гаманці (або вводить телефон), каса показує баланс, гість вирішує, чи оплатити частину чека кешбеком, чек закривається, і каса надсилає його нам. Картка в телефоні гостя оновлюється за кілька секунд.
1. Знайдіть гостя
GET /v1/members/{member} приймає те, що є в каси: номер картки, вміст штрихкоду, телефон у міжнародному форматі або наш id учасника. Телефон кодуйте для URL (+ перетворюється на %2B).
# by the number on the card (or the barcode the scanner read)
curl https://loyaltyfy.io/api/v1/members/2000111703779 \
-H "Authorization: Bearer sk_test_..."
# by phone, with fresh add-to-wallet links
curl "https://loyaltyfy.io/api/v1/members/%2B37366791102?expand=wallet" \
-H "Authorization: Bearer sk_test_..."Покажіть касиру з об’єкта учасника те, що важливо для програми:
| program.mechanic | Що показати |
|---|---|
| cashback | cashback.balance і максимальну суму списання: менше з двох значень, балансу та redeem_max_percent від суми чека. |
| stamps | stamps.current з stamps.required, а також stamps.rewards_available, якщо на гостя чекає безкоштовна позиція. |
| visit_discount, vip | discount.percent і discount.tier: застосуйте цю знижку до чека на своєму боці. |
2. Що містить штрихкод картки
Заклад вибирає формат штрихкоду в розділі Розробникам → Штрихкод картки, щоб він відповідав тому, що читає сканер каси:
| Формат | Що містить штрихкод | Коли використовувати |
|---|---|---|
| QR з номером картки | card_number, наприклад 2000111703779 | Сканер читає QR, а каса шукає за номером картки. Рекомендовано. |
| Штрихкод (Code 128) з номером картки | Той самий номер у вигляді лінійного штрихкоду, надрукований під смужками | Старіші лазерні сканери, які не читають QR. |
| QR для каси Loyaltyfy | Наш внутрішній серійний номер (UUID) | За замовчуванням. Його читає лише касовий застосунок Loyaltyfy. POS усе одно може знайти гостя за телефоном. |
Після зміни формату картки, які вже є в гаманцях гостей, оновлюються самі, нічого перевстановлювати не потрібно. Незалежно від формату, передавайте відскановане значення як є в GET /v1/members/{member} або в POST /v1/scans. Останній також прибирає префікси сканера та переноси рядків.
3. Випускайте картки з номерами каси
Якщо в каси вже є своя система карток, залиште її номери. Реєструйте гостя з card_number, що дорівнює номеру каси. Картка в гаманці показує цей номер і кодує його в штрихкоді, тож сканер знайде гостя і у власній базі каси. Номери унікальні в межах закладу: дублікат отримає 409 card_number_taken. Щоб пізніше призначити номер каси наявному учаснику, викличте PATCH /v1/members/{member} з card_number.
curl https://loyaltyfy.io/api/v1/members \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7d1b2c4e-enrol-000123" \
-d '{
"phone": "+37366791102",
"first_name": "Ion",
"last_name": "Popescu",
"card_number": "2000111703779",
"language": "ro",
"consent": true
}'У відповіді є wallet.apple_url і wallet.google_url. Надрукуйте їх як QR на чеку, надішліть SMS або покажіть на дисплеї покупця: гість відкриває посилання, і картка додається в телефон.
4. Проведіть чек
Надсилайте кожен закритий чек один раз, після оплати. amount означає повну суму чека до списання кешбеку, redeem_amount показує, скільки з неї гість оплатив кешбеком. Ми застосовуємо правила програми (мінімальний чек, ліміт списання, рівні) так само, як екран касира в закладі.
curl https://loyaltyfy.io/api/v1/transactions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"external_id": "CHK-2026-000123",
"member": "2000111703779",
"amount": 25000,
"currency": "MDL",
"register_id": "POS-1",
"closed_at": "2026-10-06T18:17:00+03:00",
"line_items": [
{ "sku": "1001", "name": "Espresso", "quantity": 2, "unit_price": 4000, "category": "Coffee" },
{ "sku": "2005", "name": "Cheesecake", "quantity": 1, "unit_price": 17000, "category": "Desserts" }
]
}'{
"object": "transaction",
"id": "f8acbb16-0b3b-4afc-acbb-e5eabd4dd072",
"external_id": "CHK-2026-000123",
"status": "completed",
"amount": 25000,
"redeem_amount": 0,
"cashback_earned": 1250,
"stamps_earned": 0,
"reward_unlocked": false,
"net_amount": 25000,
"currency": "MDL",
"register_id": "POS-1",
"closed_at": "2026-10-06T15:17:00+00:00",
"livemode": false,
"created_at": "2026-10-06T18:17:17.921+00:00",
"voided_at": null,
"member": {
"object": "member",
"id": "6dacfe0a-2500-44c6-a37c-05c660b093b4",
"card_number": "2000111703779",
"cashback": { "balance": 1250, "currency": "MDL", "earn_rate": 5, ... },
...
}
}external_id має бути унікальним серед усіх кас закладу. Якщо номери чеків починаються заново на кожній касі чи в кожній зміні, поєднуйте їх, наприклад POS-3-000123 (каса 3, чек 123).Кешбек нараховується на суму, яку гість фактично сплатив: amount − redeem_amount. У програмах зі штампами та візитами чек зараховується як візит. Поля stamps_earned і reward_unlocked показують, що сталося, тож каса може написати «ще одна кава, і наступна безкоштовно».
5. Оплата кешбеком
Спершу запитайте баланс, дайте гостю вибрати, а потім надішліть чек із redeem_amount. Якщо баланс тим часом змінився (гість щойно розрахувався деінде), ви отримаєте 402 insufficient_balance з поточною сумою в available. Покажіть її, щоб касир зміг повторити.
curl https://loyaltyfy.io/api/v1/transactions \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"external_id": "CHK-2026-000124",
"member": "2000111703779",
"amount": 12000,
"redeem_amount": 1250
}'{
"error": {
"type": "invalid_request_error",
"code": "insufficient_balance",
"message": "redeem_amount is more than the available balance.",
"param": "redeem_amount",
"available": 1250
},
"request_id": "req_6f4c30b8ca7d4423a9d4"
}201 або 200. Надсилайте чек, коли сума вже остаточна, але до прийому оплати. Якщо відповіді немає, повторіть запит з тим самим external_id або закрийте чек без кешбеку. Інакше гість отримає і знижку, і збереже баланс.6. Видача нагороди за штампи
Коли stamps.rewards_available більше нуля, гостю належить безкоштовна позиція. Видайте її на касі та зафіксуйте:
curl -X POST https://loyaltyfy.io/api/v1/members/4285324286429/rewards/redeem \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: reward-4285324286429-0001"7. Повернення та помилки
Скасуйте весь чек за його external_id. Нараховані кешбек або штампи списуються, а використаний кешбек повертається гостю. Часткове повернення: скасуйте чек і надішліть новий із виправленою сумою та новим external_id.
curl -X POST https://loyaltyfy.io/api/v1/transactions/CHK-2026-000123/void \
-H "Authorization: Bearer sk_test_..."8. Коли каса офлайн
Зберігайте чеки в локальній черзі разом з external_id і closed_at та надсилайте їх, коли з’явиться зв’язок. Дублікати ігноруються, тому всю чергу можна спокійно надіслати повторно. Для пошуку гостя потрібна мережа. Якщо її немає, дозвольте касиру провести чек без лояльності, а не блокуйте продаж.
Чеки із сервера каси
Деякі POS-системи не можуть звертатися до API безпосередньо з каси, але вміють надсилати закриті чеки зі свого сервера. Це теж підходить: надсилайте той самий POST /v1/transactions із сервера одразу після закриття чека, з номером картки, який відсканував касир. Якщо каса хоче показати результат пізніше, підпишіться на transaction.completed.