Webhooks
Com webhooks, o Loy avisa o seu sistema quando algo acontece — um cliente novo, uma visita, uma recompensa conquistada ou resgatada — sem você precisar ficar consultando a API.
1. Cadastre um endereço
curl -X POST https://loynow.com/api/v1/webhook_endpoints \
-H "Authorization: Bearer $LOY_API_KEY" -H "Content-Type: application/json" \
-d '{"webhook_endpoint": {"url": "https://hooks.seusistema.com/loy",
"event_types": ["visit.recorded", "reward.earned"]}}'
A resposta traz o secret (whsec_…) uma única vez — guarde-o para
verificar a assinatura. O endereço precisa ser https:// e público; endereços internos são
recusados. Use POST /webhook_endpoints/{id}/test para receber um evento ping na hora.
2. Eventos
| Evento | Quando | data |
|---|---|---|
customer.created | Cliente cadastrado (app ou API) | cliente |
visit.recorded | Visita paga registrada, ou marcada como paga depois | visita |
reward.earned | Recompensa conquistada (programa, aniversário, sazonal, reativação ou indicação) | recompensa |
reward.redeemed | Recompensa resgatada (app ou API) | recompensa |
O corpo de cada aviso:
{
"id": "evt_8Kd2Qz…",
"type": "reward.earned",
"created_at": "2026-10-10T14:03:11-03:00",
"data": {
"id": "rwd_2Pq8Xs4K",
"customer_id": "cus_4fRk9P2xQ",
"code": "LOY-8KD2QZ",
"status": "available",
"…": "…"
}
}
data tem o mesmo formato que a API devolve para aquele recurso.
3. Verifique a assinatura
Cada aviso traz Loy-Signature: t=<unix>,v1=<hex>, onde v1 é o
HMAC-SHA256 do texto "#{t}.#{corpo bruto}" com o seu secret. Recuse avisos com
assinatura diferente ou com t mais antigo que 5 minutos.
# Ruby
timestamp, signature = header.scan(/(?:t|v1)=([^,]+)/).flatten
expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{raw_body}")
valid = Rack::Utils.secure_compare(expected, signature) && (Time.now.to_i - timestamp.to_i).abs < 300
// Node.js
const [t, v1] = header.split(",").map((part) => part.split("=")[1]);
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))
&& Math.abs(Date.now() / 1000 - Number(t)) < 300;
4. Responda rápido e trate repetição
- Responda com qualquer
2xxem até 5 segundos; processe depois, se precisar. - Sem
2xx, o Loy tenta de novo em 1 min, 5 min, 30 min, 2 h, 6 h, 12 h e 24 h. - O mesmo evento pode chegar mais de uma vez: use
Loy-Event-Idpara ignorar repetidos. - Depois de 20 falhas seguidas ao longo de mais de um dia, o endereço é pausado e a empresa é avisada. Corrija e reative com
POST /webhook_endpoints/{id}/enable.
O acesso é liberado pela equipe do Loy. Pedir acesso.