> 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/develop-a-self-managed-app/webhooks/handle-events-with-webhooks-for-self-hosting-using-the-java-script-sdk.md

## Article Content:

# Handle Webhook Events with the JavaScript SDK

> **Note:** This article explains how to handle events with webhooks using the [JavaScript SDK](https://dev.wix.com/docs/sdk.md). If you're not using the JavaScript SDK, instead read [Handle Webhook Events 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/d19eefe7e16042e5720bc8c1dcac36e6.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 = `<YOUR_PUBLIC_KEY>`;
    const APP_ID = "<YOUR_APP_ID>";
    
    const client = createClient({
      auth: AppStrategy({
        appId: APP_ID,
        publicKey: PUBLIC_KEY,
      }),
      modules: { orders },
    });
    ```

    <blockquote class="tip">
    
    __Tip:__ Find your app ID on the **OAuth** page of your app's dashboard.

    </blockquote>

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"));
    ```

    <blockquote class="important">

    __Important:__
    You must return a 200 response upon successful receipt of the webhook.
    
    </blockquote>
  
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 = `<YOUR_PUBLIC_KEY>`;
const APP_ID = "<YOUR_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/api-integrations/events-and-webhooks/test-a-webhook-locally.md)