Walaora API arayışı
POS sistemini, onlayn mağazanı və ya daxili sistemi qoşun. HTTPS üzərindən JSON, hər inteqrasiya üçün bir API açarı.
Autentifikasiya
Açarı İdarə paneli → API və Webhooks bölməsində yaradın (Biznes və ya Korporativ plan). Onu hər sorğu ilə göndərin. Açarlar yalnız bir dəfə göstərilir; ifşa olunarsa, onları ləğv edin. Limit: hər açar üçün dəqiqədə 120 sorğu.
Authorization: Bearer wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEndpoint-lər
Base URL: https://walaora.com/api/v1
| GET | /programsLoyallıq proqramlarının siyahısı. |
| GET | /customers?phone=0551234567&tag=vipMüştəriləri tapın (səhifədə 50, ?page=2…). ?tag=vip həmin etiketi olan müştəriləri göstərir; hər müştəri öz etiketlərini ehtiva edir. |
| POST | /customersMüştərini proqrama qeydiyyata alın. Gövdə: { programId, name, phone, email?, marketingConsent?, locale? }. Yaradıldıqda 201, artıq qeydiyyatdadırsa 200 qaytarır. |
| GET | /cards/{serial}Müştərinin kartındakı / QR-dakı koda görə kart. |
| POST | /cards/{serial}/earnMöhür proqramları: { stamps?: 1–10 }. Xal proqramları: iş sahəsinin valyutasında { amount }. İstəyə görə { branchId }. Çoxmöhürlü kartlar: kartın dəstlərindən biri olan setId göndərin. |
| POST | /cards/{serial}/redeemMövcud bir mükafatı istifadə edin və ya möhür/xal ilə qiymətləndirilmiş kataloq mükafatını istifadə etmək üçün {"rewardId"} göndərin. |
| POST | /cards/{serial}/sellƏvvəlcədən ödənişli paketlər: paket satır, istifadələri karta əlavə olunur (ödəniş kassanızda alınır). Webhook: package.sold. |
| POST | /cards/{serial}/useƏvvəlcədən ödənişli paketlər: bir istifadə çıxır (boşdursa və ya müddəti bitibsə rədd edilir). İşçi kartları: imtiyazı gündəlik limit daxilində qeyd edir. Webhook-lar: package.used, perk.used. |
| GET | /coupons/{code}Kuponu istifadə etmədən yoxlayın: onun təklifi, istifadə oluna bilib-bilmədiyi və olmursa, səbəbi (istifadə olunub, müddəti bitib və ya dayandırılıb). |
| POST | /coupons/{code}/redeemKuponu bir dəfə istifadə edin. İstəyə görə { amount } (satış məbləği, iş sahəsinin valyutasında) və { branchId }. Artıq istifadə olunubsa və ya təklif bitibsə 409 qaytarır. Webhook: coupon.redeemed. |
| GET | /coupon-offersKupon təkliflərinin siyahısı: dəyəri, bitmə tarixi və indi kod yaratmaq mümkün olub-olmadığı (usable). |
| POST | /coupon-offers/{id}/couponsTəklifin kodlarını yaradın. { customerId } həmin müştəriyə bir kod verir (kart səhifəsində görünür); və ya { count: 1–500 } çap etmək və ya paylaşmaq üçün müştəriyə bağlı olmayan kodlar. Kodlarla 201; təklif dayandırılıb və ya bitibsə 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}'Təkrar cəhdlər və idempotentlik
POST sorğuları üçün Idempotency-Key başlığı göndərin (istənilən unikal sətir, məsələn, çek nömrəniz). Eyni açarla 24 saat ərzində təkrar cəhd etdikdə ikinci dəfə möhür vurulmur, ilkin cavab qaytarılır.
Xətalar
Xətalar HTTP statusu ilə birlikdə { error: { code, message } } formatında JSON gövdəsi qaytarır: 401 yanlış açar · 403 plan_required · 404 tapılmadı · 409 cooldown / no_reward / program_inactive · 422 yoxlama xətası · 429 sorğu limiti aşılıb.
Webhooks
İdarə panelində HTTPS endpoint əlavə edin və hadisələri seçin. Hər çatdırılma { id, type, createdAt, data } JSON-u və bu başlıqlarla göndərilən POST sorğusudur: Walaora-Event, Walaora-Delivery və Walaora-Signature. 10 saniyə ərzində 2xx ilə cavab verin. Uğursuz çatdırılmalar 1 dəq, 5 dəq, 30 dəq, 2 saat və 12 saat sonra təkrarlanır.
Hadisələr
customer.enrolledcard.earnedreward.unlockedreward.redeemedcard.adjustedcustomer.deletedfeedback.receivedpackage.soldpackage.usedperk.usedcoupon.redeemed
İmzaların yoxlanılması (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 ?? ""));
}