Merge Docs

Webhooks

Use webhooks when you want Merge to send POST requests to your API with updates regarding your data.

Overview

When you’ve connected to Merge, you’ll want to know when data in your linked integrations is updated so that you know when to sync data, keeping your own database up to date. Instead of polling for data on a recurring basis - which can be inefficient and result in timing conflicts - webhooks will push alerts to your API at the time that relevant data is updated.

In this guide, you’ll learn how to add and manage these webhooks. Webhooks will come in the form of inbound POST requests to your API, which you can use to trigger the creation, update, or deletion of data in your system to mirror some event in Merge, or any other action you want - you are only limited by the code you can write.

Webhooks are shared amongst your Merge organization.


Create webhooks

To create webhooks, go to the Webhooks management console under Configuration in the Merge application. Once there, press Add webhook.

Preview of webhooks list

On the next page, add the URL that you want Merge to send a POST request to. This URL should point to a POST route in your API that you’ll build to handle the incoming payload.

Make sure to select the event types that you want to trigger the webhook. We recommend selecting “All data types and events” and detecting the affected data models within your API by parsing the JSON payload.

Preview of adding webhooks

If you want to test your webhook, use the button labeled “Send test POST request”. This will cause Merge to send a POST request carrying a sample payload to the URL you’ve specified, where you can log the output and program your endpoint to do something in response to the payload.


Payload Properties


hookObject
The webhook that was triggered.

linked_accountString
The user whose data has changed.

dataObject
The affected data model. The structure of each model can be found in our API documentation

See an example of the JSON payload below:

Webhook Payload Example
JSON
1{
2  "hook": {
3    "id": "cb1fe0a7-c2a1-4bd6-8cf5-57e70c7f1d53",
4    "event": "Candidate.changed",
5    "target": "https://yoururl.com"
6  },
7  "linked_account": {
8    "id": "a3602c03-aba7-4d9d-a349-dbc338504092",
9    "integration": "Zenefits",
10    "end_user_origin_id": "23423464",
11    "end_user_organization_name": "Your Beautiful Customer",
12    "end_user_email_address": "hello@merge.dev"
13  },
14  "data": {
15    "id": "22582af6-b45e-4d34-bed6-77bb40effa97",
16    "remote_id": "97134123",
17    "first_name": "Gil",
18    "last_name": "Feig",
19    "company": "Columbia Dining App.",
20    "title": "Software Engineer",
21    "remote_created_at": "2020-11-11T00:59:25.309761Z",
22    "remote_updated_at": "2020-11-11T00:59:25.309761Z",
23    "last_interaction_at": "2020-11-11T00:59:25.309761Z",
24    "is_private": true,
25    "can_email": true,
26    "locations": ["San Francisco", "New York", "Miami"],
27    "phone_numbers": [
28      {
29        "value": "+1234567890",
30        "phone_number_type": "MOBILE"
31      }
32    ],
33    "email_addresses": [
34      {
35        "value": "hello@merge.dev",
36        "email_address_type": "PERSONAL"
37      }
38    ],
39    "urls": [
40      {
41        "value": "http://alturl.com/p749b",
42        "url_type": "BLOG"
43      }
44    ],
45    "tags": [
46      {
47        "remote_id": "4567",
48        "name": "High-Priority"
49      }
50    ],
51    "applications": [
52      "29eb9867-ce2a-403f-b8ce-f2844b89f078",
53      "b4d08e5c-de00-4d64-a29f-66addac9af99"
54    ],
55    "attachments": ["bea08964-32b4-4a20-8bb4-2612ba09de1d"]
56  }
57}

Security

You’ll want to ensure that your API endpoint is verifying that incoming POST requests are from Merge and not a malicious source, and that payloads haven’t been altered in transit.

The best way to do that is to check that the X-Merge-Webhook-Signature field in the header of the incoming request matches an encoded combination of your organization’s webhook signature and the payload attached to the incoming request.

In your Webhooks page under configuration, you should see a Security module with your signature. This signature is unique to your organization and can be regenerated if it ever becomes revealed.

Preview of webhooks security

Using this signature, calculate the HMAC-SHA256 of the byte-formatted payload and encode it to Base64 to get a digest. Ensure that the digest matches the X-Merge-Webhook-Signature found in the headers of the incoming POST request to confirm that the request is valid.

Securing Webhooks
1import base64
2import hashlib
3import hmac
4
5# Swap YOUR_WEBHOOK_SIGNATURE below with your webhook signature from:
6# https://app.merge.dev/configuration/webhooks
7
8signature = "YOUR_WEBHOOK_SIGNATURE"
9payload = request.body
10
11hmac_digest = hmac.new(signature.encode("utf-8"), payload, hashlib.sha256).digest()
12
13b64_encoded = base64.urlsafe_b64encode(hmac).decode()
14
15doesSignatureMatch = b64_encoded == request.headers["X-Merge-Webhook-Signature"]