İçeriğe geç
walaoraWalaora

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

Müşterilerin verilerini yalnızca onların bilgisi dahilinde gönderin ve marketingConsent değerini yalnızca müşteri açıkça onay verdiyse true yapın.

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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Uç noktalar

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

GET/programs

Sadakat programlarını listeler.

GET/customers?phone=0551234567&tag=vip

Müşterileri bulur (sayfa başına 50, ?page=2…). ?tag=vip o etikete sahip müşterileri listeler; her müşteri etiketlerini içerir.

POST/customers

Bir 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}/earn

Damga 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}/redeem

Kullanı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}/redeem

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

Kupon fırsatlarını değeri, bitiş tarihi ve şu an kod oluşturulup oluşturulamayacağı (usable) ile listeler.

POST/coupon-offers/{id}/coupons

Bir 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

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