Webhooks

In this guide, we will look at how to register and consume webhooks to integrate your app with Lightfunnels. With webhooks, your app can know when something happens in Lightfunnels, such as when a new order is created.

Registering webhooks

To register a new webhook, you need to have a URL in your app that Lightfunnels can call. You can configure a new webhook using the following GraphQL mutation:

GraphQL Query

# Query
mutation CreateWebhookMutation($node: WebhookInput!) {
 createWebhook(node: $node) {
	type
	settings
	url
 }
}
input WebhookInput {
  type: String!
  url: String!
  version: WebhookVersion 
  settings: WebhookSettings!
}
scalar WebhookSettings = {
	segments_uids?: string[] | undefined;
}

enum WebhookVersion {
  v1
  v2
}

GraphQL Variables

{
    "node": {
        "type": "order/confirmed",
        "url": "https://yourapp.com/webhooks/order-created/{{account-id}}",
        "settings": {}
    }
}

The type property refers to the event that you would like to listen to. Refer to event types for a list of available events.

In this example, we used the order/confirmed event. Now, whenever a new order is made, a webhook is fired off and your app receives all the information related to the new order. In the next section, we'll look at how to consume webhooks.

Consuming webhooks

When your app receives a webhook request from Lightfunnels, you should verify the authenticity of the request by validating the lightfunnels-hmac property from the header using your client secret.

Here is an exampe code on how to authenticate the request using Note.js.

import crypto from "crypto";

// This is an example of a webhook handler implemented in Node.js
const webhookHandler = async (req, res) => {
    try {
        if (!await verifyWebhook(req)) {
            return res.status(403).send("Invalid webhook");
        }

		// Webhook is valid, continue with your logic here

	} catch (error) {
		console.log(error);
		return res.status(500).send("Internal server error");
	}
}

// This function verifies the webhook using the lightfunnels-hmac header
const verifyWebhook = async (req) => {

    // calculate the hmac
    const localyCalculatedHmac = crypto
    .createHmac("sha256", process.env.LF_APP_SECRET)
    .update(JSON.stringify(req.body), "utf8")
    .digest("base64");

    // check if the hmac is the same as the one in the lightfunnels-hmac header
    const hmac = req.headers["lightfunnels-hmac"];
    if(localyCalculatedHmac != hmac){
        // this webhook is fishy, abort!
        return false;
    }

    return true;
}

Deleting webhooks

When your app no longer needs to receive a specefic webhook, you can delete it by its unique ID. This mutation permanently removes the specified webhook from Lightfunnels, preventing any further events from triggering it.

GraphQL Mutation

mutation webhooksDeleteMutation($id: ID!){
	deleteWebhook(id: $id)
}

Variables object will contain only the webhook id, here is an example:

GraphQL Variables

{
	"id": "webhook_id"
}

It will return the deleted webhook ID if the mutation was executed successfully, here is an example:

GraphQL Response

{
	"data": {
		"deleteWebhook" : "webhook_id"
	}
}

Event Types

Here are all the event types.

order/created, order/confirmed, order/fulfilled, order/cancelled, order/uncancelled, order/refunded, order-item/created, order/updated, payment/created, payment/paid, contact-form/created, contact/signup, contact/updated, checkout/created, checkout/updated, product/updated, product/created, product/deleted, funnel/created, funnel/updated, funnel/deleted, app/uninstalled

Order events

  • Name
    New order
    Type
    order/created
    Description

    This webhook is fired as soon as an order is created. Note that this may not include all items as it's fired before the customer is done purchasing the upsells & downsells.

  • Name
    Order confirmation sent
    Type
    order/confirmed
    Description

    This webhook is useful for getting all the order information including the upsells and downsells once the customer is done purchasing.

  • Name
    Order fulfillment update
    Type
    order/fulfilled
    Description

    This webhook is fired when the order fulfillment status is updated.

  • Name
    Order cancelled
    Type
    order/cancelled
    Description

    This webhook is fired when the order is cancelled.

  • Name
    Order uncancelled
    Type
    order/uncancelled
    Description

    This webhook is fired when the order is uncancelled.

  • Name
    Order refunded
    Type
    order/refunded
    Description

    This webhook is fired when the order is refunded.

  • Name
    Order item created
    Type
    order-item/created
    Description

    This webhook is fired when the order item is created.

  • Name
    Order updated
    Type
    order/updated
    Description

    This webhook is triggered whenever an update occurs on an order within the platform. It captures a wide range of modifications, including changes to tags, notes, items, refunds, cancellations, or marking an order as paid. Because this webhook is general, it provides notification of updates without specifying the exact nature of the change. To monitor specific order events, consider using the above webhooks.

Order created/confirmed payload

	{
		"node": {
			"id": "order_qa6C9z7NCHScxJoewz8xK",
			"_id": 2554132,
			"name": "7799",
			"tags": [],
			"test": true,
			"email": "test@lightfunnels.com",
			"items": [
				{
					"id": "vars__DY-kzRSBh_2A3d38kZE7",
					"_id": 3050394,
					"sku": "",
					"image": null,
					"price": 35,
					"title": "Updated Product",
					"carrier": "",
					"options": [],
					"refund_id": null,
					"__typename": "VariantSnapshot",
					"payment_id": "pay_KvHYIzSxNZWnA2XRpHQnF",
					"product_id": "prod_L8WGlMDUfgM6LAivoCZhv",
					"removed_at": null,
					"variant_id": "var_nG3DGrAyPlG2VYqiv2reY",
					"tracking_link": null,
					"custom_options": [],
					"customer_files": [],
					"tracking_number": null,
					"fulfillment_status": "none"
				}
			],
			"notes": "",
			"phone": "",
			"total": 35,
			"custom": {},
			"currency": "GBP",
			"funnel_id": "fun_IuDsIzSnQiNA2XOpmS",
			"store_id": "store_89QSjazAzPmsUhsIQSNs",
			"customer": {
				"id": "cus_GsGlWiz-Tp1zRTOJf7Dkp",
				"avatar": "//www.gravatar.com/avatar/402c2d5ecacd869e2b977a4f4584d3fa",
				"location": "US, random city",
				"full_name": "Tester Test"
			},
			"payments": [
				{
					"id": "pay_KvHYIzSxNZWnA2XRpHQnF",
					"_id": 2498721,
					"total": 35,
					"source": {
						"payment_gateway": {
							"prototype": {
								"key": "cod"
							}
						}
					},
					"refunds": [],
					"refunded": 0,
					"sub_total": 35,
					"created_at": "a few seconds ago",
					"refundable": 0,
					"discount_snapshot": null,
					"price_bundle_snapshot": []
				}
			],
			"shipping": 0,
			"subtotal": 35,
			"__typename": "Order",
			"account_id": "acc_o5C60ZEzUTDmfB8WXSxnK",
			"created_at": "2024-03-18 14:20:37",
			"refundable": 0,
			"archived_at": null,
			"net_payment": 0,
			"cancelled_at": null,
			"client_details": {
				"ip": "105.158.83.57"
			},
			"discount_value": 0,
			"original_total": 35,
			"billing_address": {
				"zip": "10000",
				"area": "",
				"city": "random city",
				"email": "test@lightfunnels.com",
				"line1": "random address",
				"line2": "",
				"phone": "",
				"state": "random state",
				"country": "US",
				"last_name": "Test",
				"first_name": "Tester"
			},
			"refunded_amount": 0,
			"paid_by_customer": 0,
			"shipping_address": {
				"zip": "10000",
				"area": "",
				"city": "random city",
				"email": "test@lightfunnels.com",
				"line1": "random address",
				"line2": "",
				"phone": "",
				"state": "random state",
				"country": "US",
				"last_name": "Test",
				"first_name": "Tester"
			},
			"shipping_discount": 0,
			"bundle_discount_value": 0,
			"normal_discount_value": 0
		}
	}

Payment events

  • Name
    New payment
    Type
    payment/created
    Description

    A new payment was created.

  • Name
    Paid payment
    Type
    payment/paid
    Description

    Paid payment.

Payment payload

		{
			"node": {
				"id": "pay_fMQN57XdoYOjvy_2m3wfn",
				"items": [
					{
						"id": "vars_MW2k2nbw4q-nlfRUfYgCO",
						"_id": 3050426,
						"sku": "",
						"image": null,
						"price": 35,
						"title": "Test Product",
						"carrier": "",
						"options": [],
						"refund_id": null,
						"__typename": "VariantSnapshot",
						"payment_id": "pay_fMQN57XdoYOjvy_2m3wfn",
						"product_id": "prod_L8WGlMDUfgM6LAivoCZhv",
						"removed_at": null,
						"variant_id": "var_nG3DGrAyPlG2VYqiv2reY",
						"tracking_link": "",
						"custom_options": [],
						"customer_files": [],
						"tracking_number": "",
						"fulfillment_status": "fulfilled"
					}
				]
			}
		}

Contact events

  • Name
    New contact form
    Type
    contact-form/created
    Description

    A new contact form was created.

Contact form payload

		{
			"node":{
				"custom": {},
				"message": "Message goes here",
				"subject": "Subject goes here",
				"email": "no-reply@lightfunnels.com",
				"first_name": "Elhanan",
				"last_name": "Aljoša"
				...
			}
		}
  • Name
    New signup created
    Type
    contact/signup
    Description

    A new sign up was made.

  • Name
    Contact updated
    Type
    contact/updated
    Description

    An existing customer was updated.

Customer payload

		{
			"node": {
				"id": "cus_iH3ipbK4yMPPcnKudRRvb",
				"tags": [],
				"email": "Test@lightfunnels.com",
				"leads": [],
				"notes": null,
				"phone": "",
				"avatar": "//www.gravatar.com/avatar/9a7fcb37672ee218b4fc41bba4f7ad8c",
				"custom": {},
				"location": "",
				"full_name": "Random Buyer",
				"last_name": "Buyer",
				"__typename": "Customer",
				"first_name": "Random",
				"billing_address": {
					"zip": "",
					"area": "",
					"city": "",
					"email": "",
					"line1": "",
					"line2": "",
					"phone": "",
					"state": "",
					"country": null,
					"last_name": "",
					"first_name": ""
				},
				"shipping_address": {
					"zip": "",
					"area": "",
					"city": "",
					"email": "",
					"line1": "",
					"line2": "",
					"phone": "",
					"state": "",
					"country": null,
					"last_name": "",
					"first_name": ""
				},
				"accepts_marketing": false
			}
		}

Checkout events

  • Name
    New checkout
    Type
    checkout/created
    Description

    A new checkout was created.

  • Name
    Checkout updated
    Type
    checkout/updated
    Description

    An existing checkout was updated.

Checkout payload

		{
			"node":{
				"id": "ch_AfZvYYNDSXdWeXmqKig1C"
			}
		}

Product events

  • Name
    Product updated
    Type
    product/updated
    Description

    An existing product was updated.

  • Name
    Product created
    Type
    product/created
    Description

    A new product form was created.

Product created/updated payload

		{
			"node":{
				"id": "prod_tXbZBX43K2pBrmJ9UWTUf",
				"title": "My really great product",
				"description": "My product description"
			}
		}
  • Name
    Delete product
    Type
    product/deleted
    Description

    A product was successfully deleted.

Product deleted payload

		{
			"node":{
				"id": "prod_tXbZBX43K2pBrmJ9UWTUf",
			}
		}

Funnel events

  • Name
    Update funnel
    Type
    funnel/updated
    Description

    An existing funnel was updated.

  • Name
    Create funnel
    Type
    funnel/created
    Description

    A new funnel was created.

  • Name
    Delete funnel
    Type
    funnel/deleted
    Description

    A funnel was successfully deleted.

Funnel payload

		{
			"node":{
				"id": "fun_KpLWLA-B1QAWKfYj9ZOsz"
			}
		}

App events

  • Name
    Uninstall app
    Type
    app/uninstalled
    Description

    An app was successfully uninstalled.

App payload

		{
			"node":{
				"id": "id of the account that uninstalled the app"
			}
		}