Send new leads to Make
Receive each new lead in Make with the raw body and the headers, check the signature with a Hash module, and pass the lead on.
Make receives a Zapped lead as a custom webhook. With two settings turned on, the scenario sees the untouched body and the request headers, so it can prove the request came from Zapped before it creates anything.
Use this guide whenYou want new leads to appear in a CRM, a spreadsheet or a chat channel, and you build your automations in Make.
Before you start
- Professional includes lead webhooks. In your Personal workspace, open Lead webhooks to configure your first destination. If a previously revoked destination is blocked, contact support to restore access.
- Check your Make plan for the number of active scenarios it allows, because the scenario has to stay on to receive leads.
- Decide where the lead should end up. This guide uses a contact in a CRM as the example.
Steps
- In Make, create a scenario and add the Webhooks module, then choose Custom webhook. Add a new webhook and copy its address.
- Open the webhook's settings, turn on Advanced settings, set Get request headers to Yes, and set JSON pass-through to Yes. The first keeps the headers, and the second keeps the body as one text string instead of breaking it into fields.
- Open Account, then Lead webhooks, paste the address into Configure destination, tick the confirmation and choose Save destination.
- Copy the signing secret shown once. It starts with whsec_ and is never shown again.
- In Make, add a Tools module with the Set variable action and store the signing secret in a variable with a name such as signing_secret. Keep the whsec_ prefix off this copy and keep it out of any log.
- Add a Make Functions module with the Hash functions action. Set Operation to SHA256, put the raw body from the webhook into Data, put the secret variable into HMAC key, set Key encoding to Base64 and set Output encoding to Base64. The module now outputs the signature of the request.
- Add a filter on the connection after the Hash module. Continue only when the signature header contains the computed value: use the contains() function on the header and look for v1, followed by the module's Result. A header can hold more than one signature, so a contains test is safer than an equals test. Header names contain a hyphen, so read the header by its exact name with a function such as get() or map() instead of dot notation.
- Add a second condition to the same filter so an old request cannot be replayed later. Compare the webhook-timestamp header with the current time and allow no more than five minutes, which is the same window Zapped uses.
- Add a JSON module with the Parse JSON action and give it the raw body, so the lead fields become mappable again. Do this after the filter, so unverified text is never parsed into your scenario.
- Add your destination action, for example Create or Update a Contact in your CRM, and map the fields from the parsed body.
- Request one test from the Test history tab in Zapped. The scenario should pass the filter and reach your action. The test carries invented values and null identifiers, so route it to a test path or turn the scenario off again afterwards.
- Capture one lead through your own published card to confirm the whole path, then check the record your action created.
Make answers 200 Accepted as soon as the webhook module runs, before the rest of the scenario. A 2xx in Lead history means Make accepted the request, not that the CRM record exists. Check the scenario's run history for that. A request that your filter rejects still reaches Zapped as Delivered, because Make answered before your filter decided. Lead history tells you the request arrived, not that it was trusted. Use the scenario run history to see whether your check passed.
Why the signature check needs both settings
JSON pass-through keeps the body exactly as one text string. That is what the signature is computed over, so it is the only form that can match. The price is that the fields are no longer separate, which is why the Parse JSON module comes afterwards.
Get request headers adds the request's headers to the webhook output, including webhook-id, webhook-timestamp and webhook-signature. Without it the scenario cannot see the signature at all.
The filter must ignore the whsec_ prefix. Make sure the secret you paste into the variable already has it removed, and that Key encoding is Base64, because the secret is base64 text that has to be decoded before it is used as a key.
Which fields to map
After Parse JSON, the lead is under data.lead, the card that captured it is under data.card, the consent is under data.consent, and the answers to your own questions are under data.custom_fields. A missing answer arrives as null.
If you want the answers to your custom questions as one line, use the Array functions with map() and join() over data.custom_fields.answers, using question_label and value. A choice question carries selected_options instead of value.
The developer guide at /api-documentation/lead-webhooks documents every header, every payload field, the retry table, the test event and ready made PHP and Node.js verification snippets.
Stopping duplicates
A retry or a replay keeps the same event id, so the same lead can reach your scenario twice. Use a Create or Update action where your CRM offers one, and choose the email address as the matching field.
Where you add rows to a spreadsheet, use Search Rows to look for the event id or the email address first, and put a filter after the search that continues only when nothing was found.
A visitor who sends the form twice creates a second lead with a new event id and duplicate_of_lead_id set. That is a real second enquiry, not a retry, so decide from your own rules whether it needs a new record or a new note.
Different cards, different handling
data.card.id tells you which card captured the lead, and data.card.name gives its name. Put a filter on a connection and route leads from one card to one owner or one pipeline.
A test event has a null card id, so a rule built on a card id will not match a test. Test the card rule with a real lead from that card.
Plans and availability
Lead webhooks are included with Professional. Open Account, then Lead webhooks, and save your HTTPS destination to get started. Delivery begins only after you configure a destination and the service is available. Custom-plan access follows your agreement.
Good ways to use this
- Keep the Hash module and its filter at the very start of the scenario, so unverified text never reaches a module that writes something.
- Put the secret in a variable or a connection, not in the filter text, so replacing the secret is one change.
- Use a Create or Update action where the CRM has one, instead of a plain Create.
- Request one test after every change to the webhook settings, and watch the scenario's run history.
Common questions
Can I verify the signature without a Hash module?
Make's Hash functions module is the documented way, and it takes Base64 as both the key encoding and the output encoding. Some Make accounts show these fields differently by version, so confirm the first test event reaches your action, and compare the module's Result with the signature header once by eye before you rely on the filter. The sha256() formula in the mapping panel is not documented with a key encoding, so the module is the safer choice.
How do I check that verification really works?
Request one test and confirm the scenario passes the filter and reaches your action. Then temporarily put the wrong value into the secret variable and run the test again: the filter should stop it. Put the real secret back afterwards.
Does the scenario have to stay on?
Yes. A scenario that is off does not answer the webhook, and Zapped records a failed delivery that is not retried. Turn it on again and request one replay from Lead history.
What happens when many leads arrive at once?
Make queues webhook requests and answers 200 while they wait. A full queue answers 400 instead, and Zapped records a failed delivery. Its rate limit answers 429, which Zapped retries.
If something looks wrong
- If the filter never passes, JSON pass-through is off, so Data holds parsed fields rather than the raw text. Turn JSON pass-through on and use the webhook's text output instead of a mapped field.
- If verification failed after the test event but the test passed earlier, the signing secret was replaced, usually by saving the destination again. Copy the current secret into the variable.
- If the header value cannot be read, the hyphen in webhook-signature is the reason. Use get() or map() with the exact header name instead of dot notation.
- If the scenario stopped running, it was switched off, or your plan's limit on active scenarios was reached. Turn it on and check the run history.
- If the record is missing but the delivery says Delivered, open the scenario's run history. The failure is in a module after the filter.
- If a lead arrives twice, your action creates a new record each time. Switch to a Create or Update action, or add a search and a filter before the action.