Перейти до вмісту
walaoraWalaora

Довідник API Walaora

Підключіть POS-систему, інтернет-магазин або внутрішню систему. JSON через HTTPS, один ключ API на кожну інтеграцію.

Надсилайте дані клієнтів лише з їхнього відома, а marketingConsent встановлюйте в true тільки тоді, коли клієнт явно погодився.

Автентифікація

Створіть ключ у розділі Панель керування → API і вебхуки (тариф «Бізнес» або «Корпоративний»). Надсилайте його з кожним запитом. Ключ показується лише один раз; якщо він потрапив до сторонніх осіб, відкличте його. Ліміт: 120 запитів на хвилину для кожного ключа.

Authorization: Bearer wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Ендпоінти

Base URL: https://walaora.com/api/v1

GET/programs

Список програм лояльності.

GET/customers?phone=0551234567&tag=vip

Пошук клієнтів (50 на сторінку, ?page=2…). ?tag=vip показує клієнтів із цією міткою; кожен клієнт містить свої мітки.

POST/customers

Реєстрація клієнта в програмі. Тіло: { programId, name, phone, email?, marketingConsent?, locale? }. Повертає 201, якщо картку створено, і 200, якщо клієнт уже зареєстрований.

GET/cards/{serial}

Картка за кодом на картці клієнта / QR.

POST/cards/{serial}/earn

Програми зі штампами: { stamps?: 1–10 }. Програми з балами: { amount } у валюті робочого простору. Необов’язково: { branchId }. Картки з кількома штампами: передайте setId — один із наборів картки.

POST/cards/{serial}/redeem

Видати одну доступну винагороду або надіслати {"rewardId"}, щоб видати винагороду з каталогу, ціна якої вказана в штампах/балах.

POST/cards/{serial}/sell

Передплачені пакети: продає пакет, його використання додаються на картку (оплата на вашій касі). Webhook: package.sold.

POST/cards/{serial}/use

Передплачені пакети: списує одне використання (відмова, якщо порожньо або минув термін). Картки працівників: відзначає привілей у межах денного ліміту. Webhooks: package.used, perk.used.

GET/coupons/{code}

Перевірити купон, не використовуючи його: його пропозиція, чи можна його використати, а якщо ні — чому (використано, термін минув або призупинено).

POST/coupons/{code}/redeem

Використати купон один раз. Необов’язково: { amount } (сума покупки у валюті робочого простору) і { branchId }. 409, якщо купон уже використано або пропозиція завершилася. Webhook: coupon.redeemed.

GET/coupon-offers

Список купонних пропозицій: значення, дата завершення і чи можна зараз створювати коди (usable).

POST/coupon-offers/{id}/coupons

Створює коди пропозиції. { customerId } видає цьому клієнтові один код (він з’явиться на сторінці його картки); або { count: 1–500 } кодів без прив’язки до клієнта для друку чи поширення. 201 з кодами; 409, якщо пропозицію призупинено або вона закінчилася.

curl -X POST https://walaora.com/api/v1/cards/ABCDE23456/earn \
  -H "Authorization: Bearer wl_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: receipt-10045" \
  -d '{"stamps": 1}'

Повторні запити та ідемпотентність

Для POST-запитів надсилайте заголовок Idempotency-Key (будь-який унікальний рядок, наприклад номер чека). Повторний запит із тим самим ключем протягом 24 годин поверне початкову відповідь, а не поставить штамп удруге.

Помилки

Помилки повертають JSON-тіло { error: { code, message } } з HTTP-статусом: 401 неправильний ключ · 403 plan_required · 404 не знайдено · 409 cooldown / no_reward / program_inactive · 422 помилка валідації · 429 перевищено ліміт запитів.

Webhooks

Додайте HTTPS-адресу в панелі керування й виберіть події. Кожна доставка — це POST-запит із JSON { id, type, createdAt, data } і такими заголовками: Walaora-Event, Walaora-Delivery та Walaora-Signature. Дайте відповідь 2xx протягом 10 секунд. Невдалі доставки повторюються через 1 хв, 5 хв, 30 хв, 2 год і 12 год.

Події

Перевірка підписів (Node.js)

import crypto from "node:crypto";

// rawBody: the exact request body string; header: req.headers["walaora-signature"]
export function verifyWalaora(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // replay window
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 ?? ""));
}