Skip to main content

Webhooks

Webhooks notify your server when things happen in Loyali. React to events in real-time to power notifications, fulfillment, and integrations.


Why Webhooks?

Polling vs Webhooks

ApproachHow It WorksDrawback
PollingYou ask "anything new?" every X secondsWasteful, delayed
WebhooksWe tell you the moment something happensReal-time, efficient

Real-Time Reactions

When a customer earns points, you can immediately:

  • Send a push notification
  • Update their profile in your app
  • Trigger a celebratory animation
  • Log to your analytics platform

Available Webhook Events

Customer Events

EventWhen It Fires
customer.createdNew customer added to your program
customer.updatedCustomer profile changed

Points Events

EventWhen It Fires
points.earnedPoints awarded (from event or direct)
points.redeemedPoints spent on a reward
points.expiredPoints expired due to inactivity
points.adjustedManual points adjustment

Tier Events

EventWhen It Fires
tier.upgradedCustomer moved UP a tier
tier.downgradedCustomer moved DOWN a tier

Redemption Events

EventWhen It Fires
redemption.createdCustomer redeemed a reward
redemption.pendingRedemption awaiting approval
redemption.approvedRedemption approved
redemption.fulfilledRedemption delivered
redemption.rejectedRedemption rejected
redemption.cancelledRedemption cancelled, points refunded

Achievement Events

EventWhen It Fires
achievement.earnedCustomer earned an achievement badge

Webhook Payload Structure

Every webhook delivers a consistent structure:

{
"id": "whd_xyz789",
"event_type": "tier.upgraded",
"created_at": "2024-01-20T14:30:00Z",
"data": {
// Event-specific data
}
}

Example Payloads

Tier Upgrade:

{
"event_type": "tier.upgraded",
"data": {
"customer_id": "cust_abc123",
"customer_email": "alex@example.com",
"previous_tier": { "name": "Silver", "id": "tier_silver" },
"new_tier": { "name": "Gold", "id": "tier_gold" }
}
}

Points Earned:

{
"event_type": "points.earned",
"data": {
"customer_id": "cust_abc123",
"amount": 150,
"new_balance": 2350,
"reason": "Purchase - Order #12345"
}
}

Redemption Created:

{
"event_type": "redemption.created",
"data": {
"redemption_id": "red_xyz789",
"customer_id": "cust_abc123",
"reward": { "title": "$25 Gift Card", "type": "digital" },
"points_spent": 2500,
"status": "pending"
}
}

Use Cases

Send Notifications

WebhookNotification
points.earned"You just earned 150 points! 🎉"
tier.upgraded"Congratulations! You're now Gold! ⭐"
redemption.fulfilled"Your reward is on its way! 📦"

Trigger Fulfillment

When redemption.created fires:

  1. Check reward type (digital vs physical)
  2. Digital → Send gift card code immediately
  3. Physical → Create order in fulfillment system
  4. Update redemption status via API

Sync to Your System

Keep your user database in sync:

WebhookAction
customer.createdAdd loyalty data to user profile
tier.upgradedUpdate user's tier badge
points.earnedUpdate cached balance

Analytics & Reporting

Log all webhooks to your analytics platform:

  • Track engagement patterns
  • Build custom reports
  • Feed machine learning models
  • Audit trail of all activity

Security: Signature Verification

Always verify webhook signatures. This ensures the webhook came from Loyali, not an attacker.

How It Works

Every webhook includes a signature header:

X-Loyali-Signature: t=1705766400,v1=5257a869e7ece...

This contains:

  • t — Timestamp when we sent it
  • v1 — HMAC-SHA256 signature

Verification Steps

  1. Extract timestamp and signature from header
  2. Reject if timestamp is too old (prevents replay attacks)
  3. Compute expected signature using your webhook secret
  4. Compare computed signature with received signature
  5. If they match → Process the webhook
  6. If they don't → Reject with 401

Why This Matters

Without verification, anyone could send fake webhooks to your endpoint:

  • Fake tier upgrades
  • Fake redemptions
  • Data manipulation

Never skip signature verification in production.


Retry Policy

If your endpoint fails, we retry with exponential backoff:

AttemptDelayTotal Time
1Immediate0
21 minute1 min
35 minutes6 min
430 minutes36 min
52 hours~2.5 hours

After 5 Failures

  • Webhook marked as failed
  • Visible in Dashboard
  • Can manually resend
  • Consider adding monitoring/alerts

Best Practices for Reliability

  • Return 200 quickly (process async if needed)
  • Implement idempotency (handle duplicate deliveries)
  • Use a queue for heavy processing
  • Monitor your endpoint uptime

Delivery Monitoring

What to Track

MetricHealthy Range
Success rate> 99%
Latency< 500ms response
Retry rate< 5%
Failed deliveries0

In the Dashboard

View delivery logs for each webhook:

  • ✅ Successful deliveries
  • ⚠️ Retries and eventual success
  • ❌ Failed deliveries with error details
  • Response codes and timing

Testing Webhooks

During Development

  1. Use a tool like ngrok to expose localhost
  2. Register your ngrok URL as webhook endpoint
  3. Trigger actions in test mode
  4. See webhooks arrive in real-time

In Dashboard

Click Test on any webhook to send a sample payload with realistic data.

Staging Environment

Before going live:

  • Set up webhooks in your staging environment
  • Run through full customer journeys
  • Verify all handlers work correctly
  • Check signature verification

Common Mistakes

❌ Don't Do This

MistakeProblemBetter Approach
No signature verificationSecurity vulnerabilityAlways verify
Slow processingTimeouts, retriesReturn 200 fast, process async
No idempotencyDuplicate actionsTrack processed webhook IDs
Ignoring failuresMissing critical eventsMonitor and alert
HTTP (not HTTPS)Man-in-the-middle attacksAlways use HTTPS

Dashboard vs API

TaskDashboardAPI
Create webhooks✅ Visual setup✅ POST endpoint
Update events✅ Checkbox list✅ PATCH endpoint
View delivery logs✅ Built-in viewer✅ GET deliveries
Test webhooks✅ Test button
Resend failed✅ Retry button✅ Retry endpoint

Next Steps