Walaora API başvuru kılavuzu
Bir POS'u, e-ticaret mağazasını veya şirket içi sisteminizi bağlayın. HTTPS üzerinden JSON, her entegrasyon için bir API anahtarı.
Kimlik doğrulama
Panel → API ve Webhooks bölümünden bir anahtar oluşturun (İşletme veya Kurumsal paketi). Anahtarı her istekte gönderin. Anahtarlar yalnızca bir kez gösterilir; açığa çıkarsa iptal edin. Sınır: anahtar başına dakikada 120 istek.
Authorization: Bearer wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxUç noktalar
Base URL: https://walaora.com/api/v1
| GET | /programsSadakat programlarını listeler. |
| GET | /customers?phone=0551234567&tag=vipMüşterileri bulur (sayfa başına 50, ?page=2…). ?tag=vip o etikete sahip müşterileri listeler; her müşteri etiketlerini içerir. |
| POST | /customersBir müşteriyi programa kaydeder. Gövde: { programId, name, phone, email?, marketingConsent?, locale? }. Oluşturulduğunda 201, zaten kayıtlıysa 200 döndürür. |
| GET | /cards/{serial}Müşterinin kartındaki / QR'ındaki koda göre kart. |
| POST | /cards/{serial}/earnDamga programları: { stamps?: 1–10 }. Puan programları: çalışma alanının para biriminde { amount }. İsteğe bağlı { branchId }. Çoklu damga kartları: kartın setlerinden biri olan setId’yi gönderin. |
| POST | /cards/{serial}/redeemKullanılabilir bir ödülü kullandırır veya damga/puan karşılığı fiyatlandırılmış bir katalog ödülünü kullandırmak için {"rewardId"} gönderin. |
| POST | /cards/{serial}/sellÖn ödemeli paketler: bir paket satar, kullanımları karta eklenir (ödeme kasanızda alınır). Webhook: package.sold. |
| POST | /cards/{serial}/useÖn ödemeli paketler: bir kullanım düşer (boşsa veya süresi dolduysa reddedilir). Personel kartları: ayrıcalığı günlük sınır içinde kaydeder. Webhook’lar: package.used, perk.used. |
| GET | /coupons/{code}Bir kuponu kullanmadan kontrol eder: fırsatını, kullanılıp kullanılamayacağını ve kullanılamıyorsa nedenini (kullanılmış, süresi dolmuş veya duraklatılmış). |
| POST | /coupons/{code}/redeemBir kuponu bir kez kullanır. İsteğe bağlı { amount } (çalışma alanının para biriminde satış tutarı) ve { branchId }. Zaten kullanılmışsa veya fırsat sona erdiyse 409. Webhook: coupon.redeemed. |
| GET | /coupon-offersKupon fırsatlarını değeri, bitiş tarihi ve şu an kod oluşturulup oluşturulamayacağı (usable) ile listeler. |
| POST | /coupon-offers/{id}/couponsBir fırsatın kodlarını oluşturur. { customerId } o müşteriye bir kod verir (kart sayfasında görünür); ya da { count: 1–500 } yazdırmak veya paylaşmak için müşteriye bağlı olmayan kodlar. Kodlarla 201; fırsat duraklatıldıysa veya sona erdiyse 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}'Yeniden denemeler ve idempotency
POST istekleri için bir Idempotency-Key başlığı gönderin (benzersiz herhangi bir metin, örneğin fiş numaranız). 24 saat içinde aynı anahtarla yeniden denemek, iki kez damga eklemek yerine ilk yanıtı döndürür.
Hatalar
Hatalar, bir HTTP durum koduyla birlikte { error: { code, message } } biçiminde JSON gövdesi döndürür: 401 geçersiz anahtar · 403 plan_required · 404 bulunamadı · 409 cooldown / no_reward / program_inactive · 422 doğrulama · 429 istek sınırı aşıldı.
Webhooks
Panelden bir HTTPS uç noktası ekleyin ve olayları seçin. Her teslimat, JSON { id, type, createdAt, data } içeren bir POST isteğidir ve şu başlıkları taşır: Walaora-Event, Walaora-Delivery ve Walaora-Signature. 10 saniye içinde 2xx ile yanıt verin. Başarısız teslimatlar 1 dk, 5 dk, 30 dk, 2 sa ve 12 sa sonra yeniden denenir.
Olaylar
customer.enrolledcard.earnedreward.unlockedreward.redeemedcard.adjustedcustomer.deletedfeedback.receivedpackage.soldpackage.usedperk.usedcoupon.redeemed
İmzaları doğrulama (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 ?? ""));
}