Walaora API 參考文件
連接 POS、網店或內部系統。透過 HTTPS 傳送 JSON,每項整合使用一個 API 金鑰。
身份驗證
在「控制台 → API 與 Webhooks」建立金鑰(商業版或企業版方案)。每次請求均須附上金鑰。金鑰只會顯示一次;如有外洩,請立即撤銷。限制:每個金鑰每分鐘 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預付套餐:扣除一次(用完或到期時拒絕)。員工卡:在每日上限內記錄福利。Webhook: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。請在 10 秒內以 2xx 回應。傳送失敗會在 1 分鐘、5 分鐘、30 分鐘、2 小時及 12 小時後重試。
事件
customer.enrolledcard.earnedreward.unlockedreward.redeemedcard.adjustedcustomer.deletedfeedback.receivedpackage.soldpackage.usedperk.usedcoupon.redeemed
驗證簽署(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 ?? ""));
}