Məzmuna keçin
walaoraWalaora

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ı.

Müştərilərin məlumatlarını yalnız onların xəbəri ilə göndərin və marketingConsent dəyərini yalnız müştəri açıq şəkildə razılıq verdikdə true edin.

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Endpoint-lər

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

GET/programs

Loyallıq proqramlarının siyahısı.

GET/customers?phone=0551234567&tag=vip

Müş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/customers

Müş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}/earn

Mö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}/redeem

Mö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}/redeem

Kuponu 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-offers

Kupon təkliflərinin siyahısı: dəyəri, bitmə tarixi və indi kod yaratmaq mümkün olub-olmadığı (usable).

POST/coupon-offers/{id}/coupons

Tə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

İ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 ?? ""));
}