Skip to content

Latest commit

 

History

History
149 lines (101 loc) · 4.69 KB

webhooks.mdx

File metadata and controls

149 lines (101 loc) · 4.69 KB
title description
Overview
A guide to using webhooks for real-time notifications and integrations

Webhooks are a way for an application to provide real-time notifications to other systems when certain events occur. They allow you to build integrations that respond to specific events in a more efficient and scalable way than constantly polling an API for updates.

In this guide, we'll explore how to set up and implement webhooks, including establishing a webhook endpoint, configuring your webhooks, and handling webhook notifications. We'll also provide examples in both JavaScript and Python.

Use cases

Webhooks can be utilized for various purposes, such as:

  • Automatically crediting a user's account when they make a purchase.
  • Displaying a banner on your website when a user's subscription is nearing expiration.
  • Adding new subscribers to a custom mailing list when they sign up for a subscription.

Webhook Types

If you are not developing an app, you can skip this section.

For apps, there will be two types of webhooks. One is for when a business signs up and purchases your app, and the second is when a user performs an action on a product that uses your app.

To differentiate, we have added an extra value to the webhook payload. If the webhook has to do with a user performing an action, you will see this a company ID:

{
  "action": "",
  "company": "biz_id",
  "data": {}
}

However, if it is trigged by a business that owns your app, it will be null.

{
  "action": "",
  "company": null,
  "data": {}
}

Creating a webhook

Depending on your use case, you can create a webhook for a company or an app.

Access the Whop Business dashboard and navigate to the [**developer settings page**](https://dash.whop.com/settings/developer). Here, you can configure your webhook endpoint URL, as well as manage all other aspects of the Whop API.

Head to the Apps Dashboard and navigate to the Integration page for the app. Here, you can configure your webhook endpoint URL, as well as manage all other aspects of your Whop App.


Webhook Secrets

For enhanced security, you can validate that the webhook is being sent by Whop. This is a string that gets sent in the headers and is used to allow your server to verify that the request is coming from Whop. To get the signature, you need to get the webhook secret from the webhook settings.

Company Webhooks

If you are using a company webhook, you can get the secret from the developer settings page.

Access the Whop Business dashboard and navigate to the [**developer settings page**](https://dash.whop.com/settings/developer). Here, you can configure your webhook endpoint URL, as well as manage all other aspects of the Whop API.


App webhooks

Head to the App Dashboard, and then select the app that has the webhook. Navigate to the Integration page for the app.

Verify the signature

The webhook secret signature will be sent in the X-Whop-Signature header. This then needs to be verified using the following code, passing in the value of the header, and the request body.

async function verifyWebhook(header, body) {
  if (!header) return null;
  const [timestampStr, signatureStr] = header.split(",");
  const [, timestamp] = timestampStr.split("=");
  const [version, sentSignature] = signatureStr.split("=");

  const now = Math.round(Date.now() / 1000);

  if (
    Number.isNaN(parseInt(timestamp)) ||
    Math.abs(now - parseInt(timestamp)) > 300
  )
    return null; // 5 minutes buffer interval

  const stringToHash = timestamp + "." + body;

  const cryptoKey = await crypto.subtle.importKey(
    "raw",
    textEncoder.encode(key),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );

  const signatureBuffer = await crypto.subtle.sign(
    { name: "HMAC", hash: "SHA-256" },
    cryptoKey,
    textEncoder.encode(stringToHash)
  );
  const signature = buf2hex(signatureBuffer);

  if (signature !== sentSignature && version !== "v1") return null;
}


`version` is meant to equal `v1`. It is not a typo.