☰ Meniu · Webhook-uri
Ghiduri

Webhook-uri

Primește un POST HTTPS când se întâmplă ceva: un bon aplicat oriunde, o recompensă deblocată, o comandă plasată la masă.

Evenimentele acoperă tot ce se face prin API la acest local, de integrarea ta și de oricare alta (altă casă, un chioșc, un conector de programări). Abonează-te doar la evenimentele pe care le folosești.

Adaugă un endpoint

Din Dezvoltatori → Webhook-uri sau prin API. URL-ul trebuie să fie HTTPS public. Secretul de semnare este întors o singură dată, la crearea endpointului.

curl
curl https://loyaltyfy.io/api/v1/webhook_endpoints \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://pos.example.com/loyaltyfy/webhooks",
    "events": ["transaction.completed", "order.created"]
  }'
Răspuns · 201
{
  "object": "webhook_endpoint",
  "id": "01c2a784-4bcf-43b9-8ac9-ddbad7a25341",
  "url": "https://pos.example.com/loyaltyfy/webhooks",
  "description": null,
  "events": ["transaction.completed", "order.created"],
  "status": "enabled",
  "disabled_reason": null,
  "livemode": false,
  "created_at": "2026-10-06T18:17:32.381+00:00",
  "secret": "whsec_UvjHvXfPk80ITYl_xPeAtskI0WjR8-PS"
}

Ce primești

curl
POST /loyaltyfy/webhooks HTTP/1.1
Content-Type: application/json
User-Agent: Loyaltyfy-Webhooks/1.0
Loyaltyfy-Signature: t=1791310488,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
JSON
{
  "id": "evt_5a1f0c9e2b7d4e3f81a0c6d2",
  "object": "event",
  "type": "order.created",
  "created": 1791310488,
  "livemode": true,
  "data": {
    "object": {
      "object": "order",
      "id": "0c69a81c-0fbc-4333-b26c-789566b9bea4",
      "number": 10,
      "status": "new",
      "table": "7",
      ...
    }
  }
}

data.object este același obiect pe care îl întoarce API-ul (o tranzacție, un membru, o comandă), așa cum era în momentul evenimentului. Răspunde cu orice 2xx în 10 secunde. Fă procesarea lentă după ce ai răspuns.

Verifică semnătura

Loyaltyfy-Signature conține un timestamp t și o semnătură v1: HMAC-SHA256 calculat peste t, un punct și corpul brut al cererii, cu secretul endpointului tău drept cheie, în hex. Calculeaz-o peste exact octeții primiți, înainte de orice parsare JSON, compară în timp constant și respinge timestamp-urile mai vechi de cinci minute.

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string or Buffer, not parsed JSON)
export function verifyLoyaltyfy(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python
import hmac, hashlib, time

def verify_loyaltyfy(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if abs(time.time() - t) > tolerance:
        return False
    signed = f"{t}.".encode() + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Reîncercări

Dacă endpointul tău nu răspunde cu 2xx la timp, reîncercăm după 1 minut, 5 minute, 30 de minute, 2 ore, 6 ore, 12 ore și 24 de ore. După 20 de livrări eșuate la rând, endpointul este dezactivat, iar localul vede motivul în panou; îl reactivezi cu PATCH /v1/webhook_endpoints/{id} și enabled: true.

Din cauza reîncercărilor, un eveniment poate sosi de mai multe ori, iar evenimentele pot sosi în altă ordine. Folosește id-ul evenimentului ca să sari peste duplicate și timestamp-urile obiectului ca să decizi ce este mai nou.

Testează un endpoint

curl
curl -X POST https://loyaltyfy.io/api/v1/webhook_endpoints/01c2a784-4bcf-43b9-8ac9-ddbad7a25341/test \
  -H "Authorization: Bearer sk_test_..."

# { "object": "webhook_test", "delivered": true, "status_code": 200, "error": null }

Lista completă de evenimente este în referința Evenimente.

Întrebări despre integrare: api@loyaltyfy.io. Răspundem în cel mult o zi lucrătoare.