Saltar al contenido
walaoraWalaora

Referencia de la API de Walaora

Conecte un TPV, una tienda en línea o un sistema interno. JSON sobre HTTPS, una clave de API por integración.

Envíe datos de clientes solo con su conocimiento, y establezca marketingConsent en true únicamente cuando el cliente lo haya aceptado de forma explícita.

Autenticación

Cree una clave en Panel → API y webhooks (plan Negocios o Empresas). Envíela en cada solicitud. Las claves se muestran una sola vez; revóquelas si quedan expuestas. Límite: 120 solicitudes por minuto por clave.

Authorization: Bearer wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Endpoints

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

GET/programs

Listar los programas de fidelidad.

GET/customers?phone=0551234567&tag=vip

Buscar clientes (50 por página, ?page=2…). ?tag=vip lista los clientes con esa etiqueta; cada cliente incluye sus etiquetas.

POST/customers

Inscribir a un cliente en un programa. Cuerpo: { programId, name, phone, email?, marketingConsent?, locale? }. Devuelve 201 si se crea y 200 si ya estaba inscrito.

GET/cards/{serial}

Tarjeta según el código de la tarjeta / QR del cliente.

POST/cards/{serial}/earn

Programas de sellos: { stamps?: 1–10 }. Programas de puntos: { amount } en la moneda del espacio de trabajo. Opcional: { branchId }. Tarjetas de sellos múltiples: envía setId, una de las series de la tarjeta.

POST/cards/{serial}/redeem

Canjear una recompensa disponible, o enviar {"rewardId"} para canjear una recompensa del catálogo con precio en sellos/puntos.

POST/cards/{serial}/sell

Paquetes prepago: vende un paquete y suma sus usos a la tarjeta (el pago se cobra en su caja). Webhook: package.sold.

POST/cards/{serial}/use

Paquetes prepago: descuenta un uso (rechazado si no quedan o caducó). Tarjetas de empleado: registra la ventaja dentro de su límite diario. Webhooks: package.used, perk.used.

GET/coupons/{code}

Comprobar un cupón sin usarlo: su oferta, si se puede usar y, si no, por qué (canjeado, caducado o en pausa).

POST/coupons/{code}/redeem

Usar un cupón una vez. Opcional: { amount } (la venta, en la moneda del espacio de trabajo) y { branchId }. 409 si ya se usó o la oferta ha finalizado. Webhook: coupon.redeemed.

GET/coupon-offers

Lista las ofertas de cupones con su valor, fecha de fin y si ahora se pueden crear códigos (usable).

POST/coupon-offers/{id}/coupons

Crea códigos de una oferta. { customerId } da un código a ese cliente (aparece en la página de su tarjeta); o { count: 1–500 } códigos sin asignar para imprimir o compartir. 201 con los códigos; 409 si la oferta está en pausa o ha terminado.

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}'

Reintentos e idempotencia

En las solicitudes POST, envíe un encabezado Idempotency-Key (cualquier cadena única, p. ej., su número de recibo). Si reintenta con la misma clave en un plazo de 24 horas, recibirá la respuesta original en lugar de sellar dos veces.

Errores

Los errores devuelven un cuerpo JSON { error: { code, message } } con un estado HTTP: 401 clave incorrecta · 403 plan_required · 404 no encontrado · 409 cooldown / no_reward / program_inactive · 422 validación · 429 límite de solicitudes superado.

Webhooks

Añada un endpoint HTTPS en el panel y elija los eventos. Cada entrega es un POST con JSON { id, type, createdAt, data } y estos encabezados: Walaora-Event, Walaora-Delivery y Walaora-Signature. Responda con un 2xx en un máximo de 10 segundos. Las entregas fallidas se reintentan después de 1 min, 5 min, 30 min, 2 h y 12 h.

Eventos

Verificación de firmas (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 ?? ""));
}