Docs
Features
Webhooks

Webhooks

Webhooks allow you to build or set up integrations, such as Make or Pabbly workflows or Slack notifications, when certain events occur in your CheckoutJoy account.

When one of those events is triggered, we'll send a HTTP POST payload to the webhook's configured URL.

Creating a webhook

Webhooks are configured in Settings > Webhooks (opens in a new tab) in your CheckoutJoy Dashboard.

Webhook Security

To verify that a webhook was sent by CheckoutJoy, you can check the request signature that is sent with each webhook.

The signature is sent in a HTTP header named x-cj-signature, and it's an HMAC hash of the request payload hashed using your secret key.

To verify the signature, you need to:

  1. Get the x-cj-signature header from the webhook request
  2. Hash the request payload using sha256 and your secret key
  3. Compare the hash with the signature from x-cj-signature

Here is an example of how to verify the signature in your app:

Verifying a request

 
const signature = req.headers['x-cj-signature']
const hash = require("crypto")
                 .createHmac("sha256", SECRET_KEY)
                 .update(JSON.stringify(req.body))
                 .digest("hex")
 
if (hash === signature) {
  // Request is verified
} else {
  // Request could not be verified
}

Events

Purchase Completed

The purchase.completed event is triggered when an order is completed. The order is completed and product access can be granted to the customer.

{
  "event": "purchase.completed",
  "data": {
    "id": "1685958796591237c8f84-7c5a-405e-8961-02a691deffc7",
    "affiliate_code": null,
    "status": "COMPLETED",
    "country_code": "ZA",
    "completed_at": "2023-06-05T09:53:34.991Z",
    "customer": {
      "email": "mollie@checkoutjoy.com",
      "first_name": "Koos",
      "last_name": "Mollie",
      "billing_address": {
        "first_name": "Koos",
        "last_name": "Mollie"
      }
    },
    "products": [
      {
        "id": "27bPgEHKrwtHlaP2JsyNt9rb6z9",
        "name": "My First Digital Product",
        "total": 21.8,
        "sub_total": 20,
        "tax_total": 1.8,
        "discount_total": 0,
        "charge_type": "immediate",
        "price": {
          "id": "price_id",
          "currency": "USD",
          "amount": 20,
          "billing_type": "once",
          "recurring": {
            "type": "once",
            "interval": null,
            "period": "month",
            "cycles": null,
            "trial_period_days": null
          }
        },
        "tax": {
          "name": "BTW",
          "rate": 9,
          "region": null,
          "country": "NL",
          "tax_class": "reduced",
          "behaviour": "exclusive"
        }
      }
    ],
    "ref": "000186",
    "payment": {
      "id": "1aceda64-5a4b-4741-a2b0-4c933a600b09",
      "status": "COMPLETED",
      "currency": "USD",
      "amount": 21.8,
      "amount_fee": 0,
      "total_net": 21.8,
      "processor_id": "123456789",
      "created_at": "2023-06-05T09:53:29.086Z"
    },
    "processor_id": "Stripe",
    "currency": "USD",
    "total": 21.8,
    "discount_total": 0,
    "tax_total": 1.8
  }
}

Recurring Payment Received

This event is triggered when a recurring subscription payment is processed and completed.

{
  "event": "subscription.payment_received",
  "data": {
    "purchase_id": "1685958796591237c8f84-7c5a-405e-8961-02a691deffc7",
    "id": "1aceda64-5a4b-4741-a2b0-4c933a600b09",
    "status": "COMPLETED",
    "currency": "USD",
    "amount": 21.8,
    "amount_fee": 0,
    "amount_net": 21.8,
    "created_at": "2023-06-05T09:53:29.086Z",
    "processor_id": "pi_3NFa1IIocmTNbZyh2aEImwUE",
    "processor": "Stripe"
  }
}

Subscription Cancelled

The subscription.cancelled event is triggered when a payment subscription failed or is cancelled by the merchant or the customer.

A cancelled subscription is final and can’t be fixed or restarted.

All product access must be revoked when this event is received.

{
  "event": "purchase.completed",
  "data": {
    "id": "1685958796591237c8f84-7c5a-405e-8961-02a691deffc7",
    "affiliate_code": null,
    "status": "CANCELLED",
    "country_code": "ZA",
    "completed_at": "2023-06-05T09:53:34.991Z",
    "customer": {
      "email": "mollie@checkoutjoy.com",
      "first_name": "Koos",
      "last_name": "Koekies",
      "billing_address": {
        "first_name": "Koos",
        "last_name": "Mollie"
      }
    },
    "products": [
      {
        "id": "27bPgEHKrwtHlaP2JsyNt9rb6z9",
        "name": "My First Digital Product",
        "total": 21.8,
        "sub_total": 20,
        "tax_total": 1.8,
        "discount_total": 0,
        "charge_type": "immediate",
        "price": {
          "id": "price_id",
          "currency": "USD",
          "amount": 20,
          "billing_type": "once",
          "recurring": {
            "type": "once",
            "interval": null,
            "period": "month",
            "cycles": null,
            "trial_period_days": null
          }
        },
        "tax": {
          "name": "BTW",
          "rate": 9,
          "region": null,
          "country": "NL",
          "tax_class": "reduced",
          "behaviour": "exclusive"
        }
      }
    ],
    "ref": "000186",
    "payment": {
      "id": "1aceda64-5a4b-4741-a2b0-4c933a600b09",
      "status": "COMPLETED",
      "currency": "USD",
      "amount": 21.8,
      "amount_fee": 0,
      "total_net": 21.8,
      "processor_id": "123456789",
      "created_at": "2023-06-05T09:53:29.086Z"
    },
    "processor_id": "Stripe",
    "currency": "USD",
    "total": 21.8,
    "discount_total": 0,
    "tax_total": 1.8
  }
}