Loyalty events API
Cascade rewards what it can see: orders, visits, referrals, birthdays. Everything else happens in systems only you have. A customer attended a class, left a review on a site you run yourself, renewed a subscription, or walked into your shop. Two endpoints let your own backend report those and have the loyalty engine treat them like anything else.
Both are part of the admin API. They take your organization's secret API key, exactly
like every other admin endpoint, because the caller is your server rather than a shopper's
browser. Do not put either of these in storefront JavaScript. The storefront has its own
endpoint, POST /widgets/loyalty/events, which is authenticated with a publishable key and a
signed customer instead.
Setting up a rule to fire
Add a rule the usual way and set its trigger to Does something your own systems report. Saving it generates a Token, which is the routing key: it names this rule when you post an event.
Copy it from the rule editor. Tokens are readable rather than shown once, so you can come back for it, and Rotate replaces it when you need to. Rotating stops every caller still sending the old one, and the change is written to the audit trail.
Several rules can share one token. That is deliberate: give three rules the same token and one call fires all three. It is how you award points and a coupon from a single event without your backend knowing there are two rules.
The token alone does nothing. The API key authenticates the call and the token only decides which rule runs, so a token on its own is not enough to award anybody anything. Still treat it as a secret: anyone holding both can fire the rule.
Reporting an event
A 202 means the event was accepted, not that anything was awarded. Events are queued and
dispatched in the background, so a slow rule never holds up your checkout or your webhook
handler. accepted tells you it reached at least one program; whether it earns anything is
up to that program's rules, its caps and its availability window.
occurredAt is worth sending when you are reporting something that happened earlier, for
example when you catch up after an outage. Leave it out and the event is treated as
happening now.
Fields
Events that are worth more than one
Some events have a size. Three items reviewed, five classes attended, forty dollars donated.
Turn on Scale the reward with the value the event carries in the rule editor and send a
value:
The reward is multiplied by the value, so a rule worth 50 points awards 150. An event that
leaves value out uses the rule's Value to assume, and a rule with neither awards its
reward once.
Only rewards with a face value can scale: points, fixed-amount coupons and gift cards. Percentage discounts and free shipping have nothing to multiply, and Cascade refuses to save that combination in the editor rather than letting it fail later.
Retries and duplicates
Send idempotencyKey and mean it. It is your own identifier for the thing that caused the
event, usually the primary key of the record: a booking id, an order id, a webhook delivery
id. Replaying the same key awards nothing a second time, which is what makes it safe to
retry a failed call, and safe to replay a queue after an incident.
The key is scoped to the customer before it is used, so two of your systems reusing one
record id do not collide with each other. That is what dedupeKey in the response shows
you.
Leave it out and every call is its own event. That is the right choice for something with no natural identifier, and the wrong choice for anything you might retry.
Customers Cascade has not met
Neither endpoint creates customers by default. An integration with a bad address in it would
otherwise fill your customer list with addresses nobody can reach, so an unknown email is a
404 that names the address:
Send "createCustomer": true when creating them is what you want, for example when your own
system is the place customers sign up.
Paused programs
A paused program earns nothing, so an event aimed at one is reported back rather than
queued. pausedLoyaltyProgramIds names it, and accepted is false when every program the
token reaches is paused:
Queuing it would only produce an outcome you never get to see, so you are told instead. This is not an error: your integration can carry on and the merchant can resume the program when they are ready.
Errors
A rotated token is the usual cause of a sudden 404, and the message says so:
Rate limits
Each endpoint allows a burst of 120 calls and refills at two a second, counted per
organization. Over that is a 429, and the right response is to back off and retry rather
than to drop the event. Because the limit is per organization and per endpoint, events and
stamps do not compete with each other.
These calls also draw on the organization-wide admin API limit, so in practice whichever bucket empties first is the one you will hit.
If you are backfilling rather than reporting live activity, use the member import for balances or the history import for the entries behind them. Both are built for that, and these endpoints are not: an event replayed through here earns at today's rules and is filed under today's date.
Watching what happens next
The event is queued, so the result arrives later. Subscribe to webhooks under Settings, Webhooks to see it. The loyalty events are:
GET /webhook-events returns the full list of names, loyalty and otherwise, so a
subscription picker never has to hardcode it.
Two of these are read-only signals rather than facts about a balance.
loyaltyReward.expiringSoon fires exactly once per reward, and
loyaltyPoints.expiringSoon fires once per balance and expiry date, so a member with points
earned over several months hears about each batch separately. Neither changes anything. If
you want to know that points actually expired, watch loyaltyTransaction.created for an
entry whose details say pointsExpired.
Joins, tier changes and referrals deliberately do not also fire
loyaltyTransaction.created, even though they appear on the activity feed. They each have
their own event above, and firing both would deliver everything twice.
Reference
Full request and response schemas are in the API reference: Loyalty events, Loyalty stamps and Loyalty rules.