> Portal Navigation: > > - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version. > - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages). > - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`). > - Top-level index of all portals: https://dev.wix.com/docs/llms.txt > - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt ## Resource: Handle Events with Webhooks for Self-hosting Using the JavaScript SDK ## Article: Handle Events with Webhooks ## Article Link: https://dev.wix.com/docs/build-apps/develop-your-app/frameworks/self-hosting/webhooks/handle-events-with-webhooks-for-self-hosting-using-the-java-script-sdk.md ## Article Content: # Handle Events with Webhooks for Self-hosting Using the JavaScript SDK > **Note:** This article explains how to handle events with webhooks for self-hosting using the [JavaScript SDK](https://dev.wix.com/docs/sdk.md). If you're not using the JavaScript SDK, instead read [Handle Events with Webhooks for Self-hosting Without the JavaScript SDK](https://dev.wix.com/docs/build-apps/develop-your-app/frameworks/self-hosting/webhooks/handle-events-with-webhooks-for-self-hosting-without-the-java-script-sdk.md). To handle [events](https://dev.wix.com/docs/build-apps/develop-your-app/api-integrations/events-and-webhooks/about-events.md) with [webhooks](https://dev.wix.com/docs/build-apps/develop-your-app/api-integrations/events-and-webhooks/about-webhooks.md), you need to subscribe to the webhook and create a webhook handler. When you subscribe to a webhook in the [app dashboard](https://manage.wix.com/account/custom-apps), you specify the endpoint where Wix should send webhook data. Then, when the event occurs, Wix sends a POST request to your handler containing event data and proceeds based on your response. > **Notes:** > > - When building apps using Blocks, [handle events using Velo](https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/events/about-backend-events.md) instead of webhooks. > - When building apps using the CLI, [handle events using event extensions](https://dev.wix.com/docs/wix-cli/guides/extensions/backend-extensions/events/add-event-extensions.md). This article outlines the process of subscribing to and processing the order canceled webhook from Wix eCommerce. ## Step 1 | Subscribe to a webhook To subscribe to a webhook: 1. Select an app from the [Custom Apps page](https://manage.wix.com/account/custom-apps) in your Wix Studio workspace. 1. In the side menu, click **Webhooks**. 1. Click **+ Create Webhook**. 1. Select an **API Category**. For example, **eCommerce**. 1. Choose a webhook event from the available options. For example, **Order Canceled**. 1. Enter your server **Callback URL**. This is where Wix sends the event data. 1. Add the relevant **Permissions**. 1. Click **Subscribe**. Your app is set up to receive the webhook. ## Step 2 | Save your public key Webhook payloads are sent in [JSON web token (JWT)](https://jwt.io/) format. Your public key allows you to verify the signature in any webhook you receive. To get your public key: 1. Select your app from the [Custom Apps page](https://manage.wix.com/account/custom-apps) in your Wix Studio workspace. 1. In the side menu, click **Webhooks**. 1. Click **Get Public Key**. ![Get public key button](https://wixmp-833713b177cebf373f611808.wixmp.com/images/5b361213265d2010aa96586b5da9c90f.png) 1. Save the public key in a secure location. You need to use this public key in your handler to verify that the request is from Wix. ## Step 3 | Handle the event The following steps demonstrate how to handle a webhook event using the [JavaScript SDK](https://dev.wix.com/docs/sdk.md): 1. Set up an Express server to handle incoming webhook requests: ```javascript import express from "express"; const app = express(); ``` 1. Create a [`WixClient`](https://dev.wix.com/docs/sdk/core-modules/sdk/wix-client.md) with the [`AppStrategy`](https://dev.wix.com/docs/sdk/core-modules/sdk/app-strategy.md). Our client is initialized with the [`orders`](https://dev.wix.com/docs/sdk/backend-modules/ecom/orders/setup.md) module, which allows us to access webhooks related to order events: ```javascript import { AppStrategy, createClient } from "@wix/sdk"; import { orders } from "@wix/ecom"; const PUBLIC_KEY = ``; const APP_ID = ""; const client = createClient({ auth: AppStrategy({ appId: APP_ID, publicKey: PUBLIC_KEY, }), modules: { orders }, }); ```
__Tip:__ Find your app ID on the **OAuth** page of your app's dashboard.
1. Use the [`onOrderCanceled`](https://dev.wix.com/docs/sdk/backend-modules/ecom/orders/on-order-canceled.md) method to register a callback function to handle order cancellation events: ```javascript client.orders.onOrderCanceled((event) => { console.log(`onOrderCanceled event received with data:`, event); console.log(`App instance ID:`, event.metadata.instanceId); // // Handle your event here // }); ``` > **Note:** You get the app instance ID in the webhook metadata. Learn more [about app instances](https://dev.wix.com/docs/build-apps/develop-your-app/access/app-instances/about-app-instances.md). 1. Define a `POST` endpoint `/webhook` on your Express server to receive incoming webhook payloads. Within the endpoint, process the incoming webhook payload using the `process` method provided by the SDK: ```javascript app.post("/webhook", express.text(), async (request, response) => { try { await client.webhooks.process(request.body); } catch (err) { console.error(err); response .status(500) .send(`Webhook error: ${err instanceof Error ? err.message : err}`); return; } response.status(200).send(); }); app.listen(3000, () => console.log("Server started on port 3000")); ```
__Important:__ You must return a 200 response upon successful receipt of the webhook.
Here's the complete code example: ```javascript import express from "express"; import { AppStrategy, createClient } from "@wix/sdk"; import { orders } from "@wix/ecom"; const app = express(); const PUBLIC_KEY = ``; const APP_ID = ""; const client = createClient({ auth: AppStrategy({ appId: APP_ID, publicKey: PUBLIC_KEY, }), modules: { orders }, }); client.orders.onOrderCanceled((event) => { console.log(`onOrderCanceled event received with data:`, event); console.log(`App instance ID:`, event.metadata.instanceId); // // Handle your event here // }); app.post("/webhook", express.text(), async (request, response) => { try { await client.webhooks.process(request.body); } catch (err) { console.error(err); response .status(500) .send(`Webhook error: ${err instanceof Error ? err.message : err}`); return; } response.status(200).send(); }); app.listen(3000, () => console.log("Server started on port 3000")); ``` > **Note:** Though not shown in this example, we recommend storing processed event IDs and checking against them before processing new webhooks to ensure you don't process the same event multiple times. ## See also * [Test a Webhook Locally](https://dev.wix.com/docs/build-apps/develop-your-app/frameworks/self-hosting/webhooks/test-a-webhook-locally-for-self-hosting.md)