---
title: Outbound webhooks
description: "Receive signed Authic webhooks for points and tier changes: available events, request format, signature verification, retries and testing."
---

[Skip to content](https://welcome.authic.io/en/knowledge-base/outbound-webhooks#main-content)

English

Show submenu for translations

[![](https://welcome.authic.io/hs-fs/hubfs/Logo-B.png?width=134&height=50&name=Logo-B.png)](https://www.authic.io/)

Open main navigation

Close main navigation

- English
  
  Show submenu for translations
- [Authic Dashboard Login](https://app.authic.io/signin)

[Authic Dashboard Login](https://app.authic.io/signin)

 How can we help you?

- There are no suggestions because the search field is empty.

1. [Authic Knowledge Base](https://welcome.authic.io/en/knowledge-base?hsLang=en)
2. [Partner integrations](https://welcome.authic.io/en/knowledge-base/partner-integrations?hsLang=en)

# Outbound webhooks

## HOW TO RECEIVE AUTHIC LOYALTY EVENTS (POINTS AND TIER CHANGES) ON YOUR PLATFORM.

This is a quick overview of how to receive Authic loyalty events on your platform. Whenever something important happens to one of your members, such as earning or spending points, changing tier or receiving a push notification, we send a signed webhook to your backend so you can keep your own systems (CRM, booking platform, data warehouse) in sync.

Each event is a plain HTTPS POST with a JSON body, signed with a shared secret. No polling or SDK is required.

In practice, the flow looks like this:

- Dashboard: **App settings → Integrations → Webhooks**
- Add your endpoint URL, enable webhooks, select the events you want and save
- Copy the signing secret (shown once) and store it on your backend
- Verify the `Authic-Webhook-Signature` header on every request
- Process the event and return a 2xx response

```
curl -X POST https://your-domain.com/webhooks/authic \     -H "Content-Type: application/json" \     -H "Authic-Webhook-Id: evt_a1b2c3d4-..." \     -H "Authic-Webhook-Event: points_earned" \     -H "Authic-Webhook-Timestamp: 1779004800" \     -H "Authic-Webhook-Signature: v1=5f2b..." \     -d '{       "id": "evt_a1b2c3d4-...",       "event": "points_earned",       "createdAt": "2026-05-17T08:00:00.000Z",       "apiVersion": "2026-05-17",       "tenant": { "uuid": "tenant_uuid", "name": "Example Club" },       "data": {         "user": {           "id": "user_uuid",           "externalId": "unique_user_id_001",           "name": "Jane Doe",           "email": "jane@example.com"         },         "points": 120,         "balance": 560,         "source": "checkin",         "reason": "Member checked in",         "sourceIds": { "checkinId": 123 }       }     }'# Sent by Authic. Respond with any 2xx status.
```

### Available events

Select one or more of these events in the dashboard. You only receive the events you selected, and the event name is sent in both the body and the `Authic-Webhook-Event` header.

| Event | Sent when |
| --- | --- |
| `points_earned` | A member earned points through check-ins, quests, purchases, bookings, referrals, manual adjustments or earning rules. |
| `points_spent` | A member spent or redeemed points, for example on a reward. |
| `points_expired` | A member lost points through the points expiration process. |
| `tier_upgraded` | A member's loyalty tier was assigned for the first time or upgraded. |
| `tier_downgraded` | A member's loyalty tier moved to a lower tier. |
| `notification_notice` | A push notification was sent to one or more members. See the separate Notification Notice Webhook guide. |

### Request format

Every webhook uses the same envelope. Only the contents of `data` change per event.

#### Headers

| Header | Description |
| --- | --- |
| `Content-Type` | Always application/json. |
| `Authic-Webhook-Id` | Unique event id, same as the id field in the body. |
| `Authic-Webhook-Event` | The event name, for example points\_earned. |
| `Authic-Webhook-Timestamp` | Unix time in seconds when this attempt was signed. |
| `Authic-Webhook-Signature` | HMAC-SHA256 signature, prefixed with v1=. See Verifying the signature. |

#### Parameters

- **id** (String): Unique per event (evt\_...). Use it as your deduplication key.
- **event** (String): The event name (see table above).
- **createdAt** (Date): When the event was created, in ISO 8601 (UTC).
- **apiVersion** (String): Payload version, currently 2026-05-17.
- **tenant** (Object): uuid and name of your club or program.
- **data.user** (Object): The member: id (Authic id), externalId, name and email.
- **data.user.externalId** (String): Matches the externalID you send at PWA login. Can be null if the member was never linked.

### Points events

`points_earned`, `points_spent` and `points_expired` share the same data shape:

- **points** (Number): Amount of points in this change. Always positive; the event name tells you the direction.
- **balance** (Number): The member's point balance after this change.
- **source** (String): What caused the change (see table below).
- **reason** (String): Short human-readable description.
- **sourceIds** (Object): Ids of the related record, for example checkinId, purchaseId or claimedPerkId. Can be empty.

| Source | Description |
| --- | --- |
| `checkin` | Points from a check-in. |
| `purchase` | Points from a purchase. |
| `play` | Points from a booking synced from your booking platform. |
| `quest` | Points from a completed quest. |
| `quest_streak` | Bonus for completing a quest streak. |
| `leaderboard` | Prize for a leaderboard position. |
| `referral` | Referral bonus. |
| `points_sharing` | Points shared between members. |
| `linked_payment`, `linked_payment_bonus` | Points from a linked payment and its bonus. |
| `manual_addition`, `manual_deduction` | Manual adjustment by a dashboard admin. |
| `reward` | Points spent on a reward. |
| `expiration` | Points removed by the expiration process. |
| `unknown` | Any other source. Treat it as a generic change. |

### Tier events

`tier_upgraded` and `tier_downgraded` include the tier before and after the change:

- **previousTier** (Object): id and name of the old tier. null when the member gets a tier for the first time.
- **currentTier** (Object): id and name of the new tier.
- **reason** (String): Why the tier changed, for example a recalculation from member activity.
- **effectiveAt** (Date): When the change took effect.

### Verifying the signature

Each request is signed with HMAC-SHA256 over `timestamp + "." + rawBody` using your signing secret. The signature header already includes the `v1=` prefix. Reject requests that fail verification.

```
import crypto from 'crypto';// Use the raw request body, before JSON parsing.function verifyAuthicWebhook({ rawBody, headers, secret }) {  const timestamp = headers['authic-webhook-timestamp'];  const signature = headers['authic-webhook-signature'];  const expected = 'v1=' + crypto    .createHmac('sha256', secret)    .update(`${timestamp}.${rawBody}`)    .digest('hex');  return signature?.length === expected.length &&    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));}
```

> **Note:** Every attempt, including retries, is signed again with a fresh timestamp. To block replayed requests you can also reject timestamps older than a few minutes.

### Delivery and retries

- Respond with a 2xx status within 7 seconds. Do heavy work asynchronously.
- Timeouts, network errors, 429 and 5xx responses are retried automatically. Each event is tried up to 5 times in total: right away, then after about 15 seconds, 30 seconds, 1 minute and 2 minutes.
- Other 4xx responses are not retried, they are marked as failed.
- Because of retries, the same id can be delivered more than once. Ignore ids you have already processed.
- Events can arrive out of order. Use createdAt and the balance field rather than arrival order to decide what is latest.

### Testing and monitoring

The Webhooks page in the dashboard also helps you test and troubleshoot:

- **Send test webhook** sends a sample of the chosen event to your endpoint. Test payloads contain `"test": true` inside data. Webhooks must be enabled and the event selected first.
- **Recent deliveries** lists the latest 25 deliveries with status, HTTP response, attempts, error and the full request body.
- **Retry** resends a failed delivery with the same id.
- **Retry today's failed** resends all of today's failed deliveries, oldest first. Deliveries that already succeeded or are still pending are skipped.
- **Rotate secret** creates a new signing secret and shows it once. The old secret stops working immediately, so update your backend straight away.

- [Onboarding guide](https://welcome.authic.io/en/knowledge-base/onboarding-guide?hsLang=en)
- [Product guide](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#main-content)

    - [App settings](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#app-settings)
    - [Rewards](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#rewards)
    - [Engagement and features](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#engagement-and-features)
    - [Communication](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#communication)
    - [Analytics](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#analytics)
    - [Marketing](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#marketing)
    - [Settings](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#settings)
    - [CRM Campaigns](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#crm-campaigns)
    - [Contacts](https://welcome.authic.io/en/knowledge-base/product-guide?hsLang=en#contacts)
- [Inspiration guide](https://welcome.authic.io/en/knowledge-base/inspiration-guide?hsLang=en)
- [Partner integrations](https://welcome.authic.io/en/knowledge-base/partner-integrations?hsLang=en)

[![](https://welcome.authic.io/hs-fs/hubfs/Logo-B.png?width=134&height=50&name=Logo-B.png)](https://welcome.authic.io/?hsLang=en)

<https://www.facebook.com/> <https://www.twitter.com/> <https://www.instagram.com/> <https://podcasts.apple.com/> [mailto:email@email.com](mailto:email@email.com)

Copyright © 2026, Authic Labs