> ## Documentation Index
> Fetch the complete documentation index at: https://developers.perkstar.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks and instant scenarios

> Understand Make attached webhooks, server-attested delivery verification, retries, duplicate protection, and queues.

**Watch loyalty events** is an instant trigger backed by a Make attached
webhook. When its webhook is created, the app registers the unique Make HTTPS
callback with Perkstar for one event and optional Card/live-test filters.
Perkstar sends matching events as they happen; the module does not poll customer
or transaction lists.

<Info>
  Let the official module create and manage its subscription. Do not also copy a
  custom Make webhook URL into Perkstar for the same event unless two
  independent deliveries are an intentional, reviewed design.
</Info>

## Attached webhook lifecycle

<Steps>
  <Step title="Make creates the attached webhook">
    The module sends one create request containing Make's unique HTTPS callback,
    the selected event and filters, and active state. Perkstar returns the
    subscription ID that Make stores for detach; there is no separate activation
    request. A retried create uses the same deterministic callback identity to
    recover the live row instead of creating another subscription.
  </Step>

  <Step title="Perkstar records a matching event">
    Perkstar durably creates a delivery before scheduling the outbound POST.
    Events that do not match the event type, Card, or live/test selection are
    rejected before an outbound delivery is created.
  </Step>

  <Step title="Make accepts a bundle">
    An HTTP `2xx` acknowledges the delivery. Acceptance by Make proves only that
    its webhook endpoint received the bundle; inspect scenario history and
    incomplete executions to confirm downstream modules completed.
  </Step>

  <Step title="Make detaches the webhook">
    Deleting the attached webhook invokes the app's detach operation and deletes
    that app-owned Perkstar subscription. Recreating it produces a new callback
    relationship. Scenario and destination history are not erased.
  </Step>
</Steps>

Turning a scenario **Off** and deleting its attached webhook are different
operations. Do not assume an inactive scenario has already removed the
Perkstar subscription. Check the scenario's webhook configuration and Make's
webhook queue, then delete an unused attached webhook deliberately.

One Perkstar OAuth application, installing Perkstar user, and business
combination can own up to 200 Perkstar webhook subscriptions. Multiple Make
connections authorised by that same Perkstar user for that business share the
allowance. Paused rows left by interrupted cleanup or a revoked grant still
count, and each **Watch loyalty events** webhook normally uses one. At the
limit, remove unused attached webhooks and confirm detach succeeded; Perkstar returns
`409 webhook_subscription_limit_reached` rather than replacing another
scenario's subscription.

Perkstar binds subscription idempotency to the live row rather than a short
response cache. A lost create response, access-token refresh, or repeated
attach call with the same app identity can recover that row. Deleting it
releases the identity and capacity immediately.

<Warning>
  The first Customer Lifecycle Group Changed or Google Wallet Pass Installed
  subscription for a business needs one completed warm-up sweep. Perkstar stores
  existing state without replaying the customer base, then tracks later changes.
  Apple installation remains callback-driven.
</Warning>

## Event identity

Perkstar sends this common envelope:

```json theme={null}
{
  "id": "whd_01JEXAMPLE",
  "type": "transaction.created",
  "created": 1785312000,
  "orgId": "org_123",
  "data": {
    "enrollmentId": "enr_123",
    "type": "STAMP",
    "delta": 1,
    "occurredAt": "2026-08-02T10:00:00.000Z"
  }
}
```

`id` and `X-Perkstar-Delivery-Id` identify one logical delivery and stay stable
across automatic retries. `created` is the source event's `data.occurredAt`
expressed as Unix seconds, not the delivery-attempt time. Different events can
arrive out of order.

Use the event ID as the scenario's duplicate key. If a destination write is
not naturally idempotent, record processed IDs in a destination uniqueness
constraint or a Make Data Store before the write. Do not assume Make will
deduplicate two accepted deliveries automatically.

## Delivery policy

| Attempt | Timing                             |
| ------- | ---------------------------------- |
| 1       | Immediately                        |
| 2       | 1 minute after the first failure   |
| 3       | 5 minutes after the second failure |
| 4       | 30 minutes after the third failure |

* Any HTTP `2xx` response succeeds.
* A non-`2xx`, network failure, or response taking longer than ten seconds
  schedules the next attempt.
* `410 Gone` permanently exhausts that delivery and pauses the Perkstar
  subscription.
* After four failed attempts, the delivery is exhausted and retained for
  support diagnostics.
* Delivery is at least once. Every route and destination write must tolerate a
  duplicate.
* Perkstar retries only when delivery to Make fails. If Make accepted the
  bundle and a later scenario module failed, resume or retry the Make execution
  with the same source identifiers.
* Use `data.occurredAt` or outer `created` for business ordering, not arrival
  time or Make execution time.

## Server-attested delivery verification

Perkstar signs every outbound request with HMAC-SHA256 and sends
`X-Perkstar-Signature: t=<unix-seconds>,v1=<hex>`. Make exposes the parsed JSON
event to a custom app rather than the exact original bytes, so the official
module does not attempt to recreate the raw-body HMAC inside Make.

Instead, **Watch loyalty events** sends the received event and signed delivery
headers back to Perkstar over the tenant-scoped OAuth connection before it
outputs a bundle. Perkstar verifies the app-owned subscription, organisation,
authorising user, delivery ID, signing time, stored signature proof, and exact
event envelope. A missing, stale, forged, cross-tenant, or altered delivery is
rejected and does not become a normal scenario bundle. The per-subscription
signing secret remains encrypted in Perkstar and is never stored by Make.

Treat the callback URL as a secret as an additional defence: never log it,
paste it into a ticket, expose it in a screenshot, or reuse it as a public
endpoint. The stable event ID remains the duplicate key; verification proves
origin and integrity but does not turn at-least-once delivery into exactly-once
processing.

<Note>
  Make acknowledges the incoming HTTP delivery before the scenario's
  authenticated verification step finishes. A temporary Perkstar verification
  outage therefore appears in Make as a failed or incomplete execution rather
  than causing Perkstar to resend an already accepted callback. Resume that
  execution with the same event ID after service recovers. The exact stored
  proof remains recoverable for up to 90 days, matching Perkstar's terminal
  webhook-delivery retention; proofs older than that are rejected. Normal
  duplicate handling by Event ID is still required when an execution is resumed
  or replayed.
</Note>

## Test an instant scenario

1. Add **Watch loyalty events** as the first module.
2. Select the intended Perkstar connection and create its attached webhook.
3. Choose exactly one Event and, only when that event carries a Card ID, the
   intended Card.
4. Keep **Include Test Events** off for a live scenario.
5. Choose **Run once**, then perform the exact event in Perkstar.
6. Confirm the module completed its Perkstar verification request, then inspect
   the event ID, event type, organisation, source time, and relevant fields
   inside **Event Data** before mapping another module.
7. Stop **Run once**, add duplicate/error handling, save, and turn the scenario
   on only after the test result is understood.

The `webhook.test` diagnostic is not an Event choice. A sample bundle is not a
promise that every optional field will be populated on later events.

## Observation boundaries

* **Wallet Pass Installed** fires on first provider-owned installation
  evidence. Apple reports device registration directly. Recently issued Google
  passes are eligible for a periodic projector; object age, provider response,
  and backlog can extend the delay. Issuing a pass or opening a save link is not
  installation evidence.
* **Card Scanned** covers successful online Perkstar Scanner lookups only. An
  offline cache lookup, dashboard search, or POS lookup is outside the event.
* **Customer Card Expired** belongs to one enrolment and effective expiry. If
  an extension later reaches a new expiry, another event is expected.
* **Customer Lifecycle Group Changed** tracks movement among six Perkstar
  lifecycle groups, not saved-segment membership. Initial classification is a
  suppressed baseline.
* **New Customer Referral** is one loyalty customer referring another. It
  is not a merchant, agency, partner, or affiliate invitation.

Some bundles contain purchaser or customer data. Make execution history,
queues, Data Stores, and every mapped destination can retain those values. Read
[Data and security](/integrations/make/data-security) before activating the
scenario.


## Related topics

- [Connect Perkstar to Make](/integrations/make/setup.md)
- [Make data and security](/integrations/make/data-security.md)
- [Make troubleshooting](/integrations/make/troubleshooting.md)
- [Instant triggers and webhooks](/integrations/zapier/webhooks.md)
- [Make scenario recipes](/integrations/make/recipes.md)
