> For the complete documentation index, see [llms.txt](https://docs.thx.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thx.network/developers/webhooks.md).

# Webhooks

Implement a public endpoint in your app and receive campaign events. Verify requests using the signing secret as in the given example. This is what protects the endpoint!

You can register your webhooks and view the requests we made to them in Developer -> Webhooks.

<figure><img src="https://1499671166-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fda0CPvFjFKQsHDL5o9xa%2Fuploads%2FSnGbm4nxEjvHOBcxUeLx%2FScreenshot%202023-12-21%20at%2013.52.51.png?alt=media&amp;token=30a9ea42-ecd9-4cc1-b6db-202a3324aeb2" alt=""><figcaption><p>Example of a registered webhook for a Custom Reward</p></figcaption></figure>

Webhook are great tools for setting up integrantions with your app using webhook quests and custom rewards.

{% content-ref url="/pages/7lZv6qsXC4ugmCXKKR9L" %}
[Webhook Quests](/campaign-managers/quests/webhook-quests.md)
{% endcontent-ref %}

{% content-ref url="/pages/ucb8l0lOBPMYkdp7lFvS" %}
[Custom Rewards](/campaign-managers/rewards/custom-rewards.md)
{% endcontent-ref %}

### Example Webhook

This is an example implementation of a webhook for a NodeJS express server.

```javascript

// Helper method to verify payload signature
function constructEvent(payload, signature, secret) {
	const hmac = crypto.createHmac('sha256', secret);
	hmac.update(payload);
    const calculatedSignature = hmac.digest('base64');
	if (signature !== calculatedSignature) throw new Error('Failed signature verification')
    return JSON.parse(payload);
}

// Sample endpoint controller (Express)
app.post('${path}', (req, res) => {
    let event;

    try {
        // Veries and parses the payload using the WEBHOOK_SIGNING_SECRET which you can get in Developer -> Webhooks
        event = constructEvent(req.body.payload, req.body.signature, WEBHOOK_SIGNING_SECRET);
    } catch (error) {
        return res.status(400).send("Webhook Error: " + err.message);
    }

    switch(event.type) {
        case 'reward_custom.paid': {
            // Handle the event
            // ...
            break
        }
        default : {
            console.log("Unhandled event type " + event.type)
        }
    }

    res.send();
});`;
```
