Receive and verify Wix webhooks. Use when setting up Wix webhook handlers for self-hosted/self-managed apps, debugging JWT signature verification with your app's public key, or handling events like wix.ecom.v1.order_created, wix.ecom.v1.order_approved, wix.ecom.v1.order_updated, and wix.ecom.v1.order_canceled.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Receive and verify Wix webhooks. Use when setting up Wix webhook handlers for self-hosted/self-managed apps, debugging JWT signature verification with your app's public key, or handling events like wix.ecom.v1.order_created, wix.ecom.v1.order_approved, wix.ecom.v1.order_updated, and wix.ecom.v1.order_canceled.
How do I receive Wix webhooks in a self-hosted app?
How do I verify Wix webhook signatures (the JWT)?
Where do I get my Wix public key to verify webhooks?
How do I handle wix.ecom.v1.order_created / order_approved / order_canceled events?
Why is my Wix webhook JWT verification failing?
How Wix Webhooks Work
Wix delivers each webhook as an HTTP POST whose entire request body is a signed JWT (RS256), signed by Wix. There are noX-Wix-Signature/HMAC headers and it is not Standard Webhooks โ verification means validating the JWT with your app's public key.
Get your public key from the app dashboard โ Custom Apps โ your app โ Webhooks โ "Get Public Key" (also under View ID & keys). It is per-app; there is no global JWKS endpoint.
Verify against the raw, unparsed body. Re-serializing the JSON breaks the signature.
The decoded JWT is a nested envelope: outer { data, iat, exp } โ data is a JSON string โ parse it to { eventType, instanceId, data } โ parse the inner data string to get the entity/event payload.
Verification (core)
Node.js โ official @wix/sdk verifies (RS256, via jose) and decodes in one call. Pass the raw text body:
import { AppStrategy, createClient } from'@wix/sdk';
import { orders } from'@wix/ecom';
const client = createClient({
auth: AppStrategy({
appId: process.env.WIX_APP_ID,
publicKey: process.env.WIX_PUBLIC_KEY.replace(/\\n/g, '\n'), // PEM, or base64-encoded PEM
}),
modules: { orders },
});
// Register typed handlers up front...
client.orders.onOrderCanceled((event) => {
console.log('Order canceled', event.metadata.entityId, 'event', event.metadata._id);
});
// ...then verify + dispatch the raw JWT body (throws if the signature/exp is invalid):await client.webhooks.process(rawBody);
Python (no official server SDK) โ verify the JWT manually with PyJWT + your public key:
Event type strings follow wix.<product>.<version>.<entity>_<action>. Configure each one on the Webhooks page of your app dashboard.
Event Type
Triggered When
wix.ecom.v1.order_created
A new eCommerce order is created
wix.ecom.v1.order_approved
An order is approved (e.g. payment authorized)
wix.ecom.v1.order_updated
An order is updated
wix.ecom.v1.order_canceled
An order is canceled
App instance events
Lifecycle events such as your app being installed or removed from a site (App Instance Installed / Removed) โ confirm the exact event identifier in the Wix app dashboard's Webhooks catalog, as the wire encoding differs from the eCommerce FQDN form above.
WIX_APP_ID=your-app-id # OAuth page of your app dashboard
WIX_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"# Webhooks > Get Public Key
Store the PEM public key on one line with \n escapes (the examples convert them back to newlines). A base64-encoded PEM also works with @wix/sdk.
Delivery, Retries & Idempotency
Respond 200 within ~1250 ms or Wix retries โ up to 12 more times over hours (1 min โ 12 hours).
Because of retries, events arrive out of order and duplicated. Dedupe on the event ID (event.metadata._id via the SDK, or the inner payload's id when verifying manually) and return 200 fast; do slow work asynchronously.
Some legacy webhooks send only changed fields, not the full entity โ GET the entity if you need the full object.
Local Development
# Start a tunnel (no account needed) and forward to your local handler
npx hookdeck-cli listen 3000 wix --path /webhooks/wix
Use the printed HTTPS URL (path /webhooks/wix) as the Callback URL when creating the webhook in your app dashboard.
We recommend installing the webhook-handler-patterns skill alongside this one for handler sequence, idempotency, error handling, and retry logic. Key references (open on GitHub):
Handler sequence โ Verify first, parse second, handle idempotently third
Idempotency โ Prevent duplicate processing (critical for Wix retries)
Error handling โ Return codes, logging, dead letter queues
hookdeck-event-gateway - Webhook infrastructure that replaces your queue โ guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers