Webhooks
For a developer wiring Cascade into their own systems. A webhook is a URL of yours that Cascade posts to when something happens, so you hear about a published review or a redeemed reward without polling for it.
Registering an endpoint
Add one under Settings → Webhooks, or over the API:
The URL has to accept HTTPS. Subscribe to the events you actually handle: the list you send replaces the subscription wholesale on an update, so send the full list every time.
hmacSecret is a shared secret you choose. Cascade never returns it again, so store it
alongside your own configuration. Leave it out and deliveries are unsigned, which means
your endpoint has no way to tell a real delivery from anyone who guesses the URL.
Editing an endpoint under Settings → Webhooks leaves the secret alone unless you say
otherwise: the secret field is blank on open, and a blank field keeps whatever is stored.
To stop signing, tick "Stop signing this endpoint and remove the secret." Over the API the
same two intents are the difference between omitting hmacSecret and sending it as null.
What a delivery looks like
Every delivery is a POST with the same envelope:
data is the record the event is about, in the same shape the API returns it. Answer with
any 2xx status. Anything else is recorded as a failed delivery.
Answer quickly, and do your own work afterwards. Cascade waits for your response, so an endpoint that takes ten seconds to process the payload is an endpoint that takes ten seconds to acknowledge it.
Verifying the signature
When a secret is set, deliveries carry an X-Webhook-Signature header:
It is the HMAC-SHA256 of the raw request body, keyed with your secret, hex encoded,
prefixed with sha256=.
Verify it before you parse the body. Re-serializing the JSON changes the bytes, and the digest never matches again. This is the single most common mistake in a webhook receiver.
Compare in constant time, as above, rather than with ===.
Duplicates and retries
Every delivery carries an idempotencyKey. The same key is never delivered twice to the
same webhook, but network timeouts are real: if you answered a request that never reached
us, or your own handler crashed after acknowledging, you can end up processing the same
work twice. Record the key and ignore one you have already handled.
There are no automatic retries. A delivery your endpoint rejects or times out on is recorded as failed and is not sent again. This is deliberate but easy to be caught by: treat webhooks as a fast path, not as a guaranteed one, and reconcile anything that matters by reading the API on a schedule.
Failed deliveries are listed with their error under the webhook in
Settings → Webhooks, and over the API at
GET /webhooks/{id}/events. Each row holds the payload that was sent, so
you can see what your endpoint was asked to accept.
The events
Names are resource.action. Subscribe with the exact string;
GET /webhook-events returns the current list.
Store data
Tag changes have their own events: customerTag.*, orderTag.* and productTag.*, each
with created, updated and deleted.
Reviews and surveys
A review that arrives unpublished and is published later fires review.created then
review.updated. If you are syncing reviews to your own storefront, look at published
on the payload rather than assuming created means visible. Questions work the same way:
one arrives unpublished and fires productQuestion.updated when you publish it.
Loyalty
Configuration changes fire too: loyaltyProgram.*, loyaltyRule.* and loyaltyTier.*,
each with created, updated and deleted.
The two expiringSoon events come from the overnight job rather than from anything a
customer did, so they arrive on your organization's schedule. See
Loyalty.
Wishlists
wishlist.created, wishlist.updated and wishlist.deleted.
There are no item-level events. Adding, removing or editing an item fires
wishlist.updated for the list it belongs to.
Everything else
emailTemplate.*, quickFilter.* and webhook.* fire on their own configuration
changes, each with created, updated and deleted.
Testing an endpoint
The fastest way to see real deliveries is the example custom store, which registers a webhook against itself on boot and shows every inbound event in one list. See Custom integration.
While you are building, point the webhook at a tunnel to your machine and watch the deliveries land under Settings → Webhooks. A delivery that fails tells you the status and the body your endpoint returned, which is usually enough to see what went wrong.