Gareth Wilson Gareth Wilson

Guide to Make Webhooks: Features and Best Practices

Published


Make webhooks are the requests a Make scenario sends to your own systems. Make, formerly Integromat, is a no-code workflow automation platform, and when a scenario needs to hand data to a service you run, for example a new form submission, a CRM update or a row from a spreadsheet, the usual tool is the HTTP app's Make a request module pointed at your endpoint.

This guide covers how outbound Make requests are built, how to authenticate them with an API key keychain, how to give your receiver something to route on, and the best practices for running a Make receiver in production.

What are Make webhooks?

Unlike most webhook providers, Make doesn't define what arrives at your endpoint. The person building the scenario does. In the HTTP > Make a request module they choose the URL, the method, the headers, the query parameters, the body format and the body itself, usually by mapping values from earlier modules in the scenario. Make adds no event name, no envelope and no signature.

That means two things for a receiver. First, the request has whatever shape the scenario gives it, so agree on a body format with whoever builds the scenario, and include a field that says what the event is. Second, authentication is something you add, using one of the module's authentication types.

The module supports No authentication, API key, Basic Auth and OAuth 2.0. Make recommends defining credentials in the module's dedicated Credentials field, which stores them in a keychain, rather than typing them into headers or query parameters. For a webhook receiver, an API key keychain placed in a header is the simplest choice.

Make webhook features

FeatureDetails
SenderThe HTTP app's Make a request module in a scenario
URLHTTPS only. Self-signed certificates are rejected
MethodsGET, HEAD, POST, PUT, PATCH, DELETE or OPTIONS, chosen per module
BodyJSON (a string or a data structure), multipart/form-data, application/x-www-form-urlencoded, or a custom content type
Event identifierNone from Make. Add one to the body yourself
AuthenticationAPI key, Basic Auth or OAuth 2.0 credentials. No signature
API key keychainName, Key (sent exactly as entered), placement (header or query) and parameter name
Timeout1 to 300 seconds, set on the module
RedirectsOptionally followed, up to 10
ErrorsReturn error if HTTP request fails stops the scenario on a 4xx or 5xx
RetriesNo retry policy documented for the module

Common events

Make has no event catalogue for outbound requests, because every request is built in a scenario. The events are whatever your scenarios report: "lead created", "invoice paid", "row added". Put the name in the body, and keep the shape the same across scenarios so one receiver can handle them all:

{
  "event": "lead.created",
  "occurred_at": "2026-10-22T09:15:00Z",
  "id": "{{1.id}}",
  "data": {
    "email": "{{1.email}}",
    "company": "{{1.company}}"
  }
}

The {{1.id}} placeholders stand for values mapped from earlier modules. With the JSON string input method, you're responsible for producing valid JSON. With Data structure, Make escapes JSON reserved characters in values for you, which avoids broken bodies when a mapped value contains a quote.

Include a stable id, taken from the record the scenario is handling, so the receiver can recognise a repeat.

Setting up Make webhooks

  1. Generate a long random value, for example with openssl rand -hex 32.
  2. In your scenario, add HTTP > Make a request and set Authentication type to API key.
  3. Under Credentials, create a keychain. Enter a name, put your value in Key (with a prefix such as Bearer only if you want one, since the whole value is sent), set API key placement to In the header, and set API key parameter name to the header you want, such as X-Make-Secret.
  4. Enter your HTTPS endpoint as the URL, choose the method, set Body content type to application/JSON, and build the body.
  5. Set a Timeout that fits your endpoint, and decide whether Return error if HTTP request fails should stop the scenario.

You can edit a keychain later under Keys, and every module that uses it picks up the change, which makes rotation straightforward.

In Hookdeck. Create a source with the Make type. Enter the API key parameter name in API Key Header and the exact Key in API Key, including any prefix, and use the source URL as the module's URL. Hookdeck matches the header name case-insensitively and the value exactly. The source type pre-selects POST. If your module uses GET, PUT, PATCH or DELETE, allow that method on the source too. Don't use OPTIONS: Hookdeck answers it as a CORS preflight and never turns it into an event. A keychain placed in the query parameters, Basic Auth and OAuth 2.0 can't be checked by this source type.

Securing Make webhooks

Compare the header the keychain sends with your stored value in constant time, and reject requests where it's missing or different.

const crypto = require('crypto');
const express = require('express');

function safeEqual(received, expected) {
  const a = Buffer.from(received, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on buffers of different lengths
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

const app = express();

app.post('/webhooks/make', express.raw({ type: '*/*' }), (req, res) => {
  const expected = process.env.MAKE_WEBHOOK_SECRET;
  if (!expected) return res.sendStatus(500); // fail closed when unconfigured

  const received = req.get(process.env.MAKE_WEBHOOK_HEADER || 'X-Make-Secret');
  if (typeof received !== 'string' || !safeEqual(received, expected)) {
    return res.sendStatus(401);
  }

  let payload;
  try {
    payload = JSON.parse(req.body.toString('utf8'));
  } catch {
    return res.sendStatus(400); // the scenario sent something other than JSON
  }
  // Route on payload.event, deduplicate on payload.id, process async.
  res.sendStatus(200);
});

The same check in Python:

import hmac
import os


def verify_make_request(headers) -> bool:
    expected = os.environ.get("MAKE_WEBHOOK_SECRET")
    if not expected:
        return False  # fail closed
    header_name = os.environ.get("MAKE_WEBHOOK_HEADER", "X-Make-Secret")
    received = headers.get(header_name)  # Starlette and Flask headers are case-insensitive
    if not received:
        return False
    return hmac.compare_digest(received.encode("utf-8"), expected.encode("utf-8"))

A matching header shows that the caller has the key. It doesn't show that the body is intact, and a captured request still passes if it's sent again. Make only calls HTTPS URLs, which protects the header in transit. Keep the key long and random, don't place it in query parameters, where it ends up in access logs, and rotate it in the keychain and your configuration if it may have leaked.

Make your Make scenarios production-ready. Hookdeck Event Gateway checks the keychain header on every request, answers the module straight away, and queues each event durably with retries and replay.

Make webhook limitations and pain points

Every scenario invents its own payload

The Problem: Your receiver has to cope with as many body shapes as there are scenarios, and a scenario edit can change the shape without warning.

Why It Happens: Make sends whatever the module is configured to send. There's no fixed envelope or event field.

Workarounds:

  • Agree on one body format, with event, id and data, and use a Data structure in the module so it's enforced.
  • Validate the body on arrival and return 400 for anything that doesn't match, so the scenario's error shows up in Make.

How Hookdeck Can Help: Hookdeck stores every request with its full body, so you can see exactly what each scenario sends, and transformations can normalise different shapes into one before they reach your service.

No retry policy of its own

The Problem: If your endpoint is down when the module runs, the data may never arrive.

Why It Happens: Make documents a timeout and an option to stop the scenario on a 4xx or 5xx, but no automatic retry policy for the module. What happens after a failure depends on the error handling built into the scenario.

Workarounds:

  • Add error handling to the scenario around the HTTP module, and test what it does when your endpoint returns a 500.
  • Turn on Return error if HTTP request fails so failures are visible in the scenario's history rather than silently ignored.

How Hookdeck Can Help: Hookdeck accepts each request as soon as it arrives and stores it, then delivers it to your service with retries on a schedule you control, so an outage on your side doesn't depend on how each scenario handles errors.

A static key, not a signature

The Problem: Anyone who learns the key can send requests that look like they came from your scenarios.

Why It Happens: An API key keychain sends the same value on every request. Make doesn't sign the body.

Workarounds:

  • Use a long random key, header placement only, and a separate keychain per environment.
  • Deduplicate on a stable id in the body, so a replayed request has no further effect.

How Hookdeck Can Help: Hookdeck's Make source type compares the header you name with the exact value you enter. Hookdeck answers the module with a 200 either way, then records a request without the right header as failed verification, so it never reaches your destination.

Failures behind Hookdeck aren't visible in Make

The Problem: With Hookdeck in front of your endpoint, a scenario shows every run as successful, even when your service later rejects the event or the key is wrong.

Why It Happens: Hookdeck answers the module itself, before your service sees the request, so Return error if HTTP request fails never triggers for problems downstream.

Workarounds:

  • Watch Hookdeck rather than the scenario history for delivery problems and failed verification.
  • Send a test run after any change to the keychain.

How Hookdeck Can Help: Hookdeck issues alert you when deliveries to your service fail, and every request, including those that failed verification, is listed with its headers and body.

Best practices

Use the keychain, not a raw header

Put the secret in an API key keychain rather than in the module's Headers field. Make recommends this because it avoids exposing keys in requests, centralises control of credentials, and makes rotation safe and easy.

Send JSON with an event name and ID

Use application/JSON with a Data structure, and include event and a stable id in every body. Routing and deduplication both depend on them. See our guide to webhook idempotency.

Keep one method per endpoint

Choose POST for event delivery unless you have a reason not to, and allow other methods on the receiver only where a scenario uses them.

Acknowledge fast and process asynchronously

A slow response holds up the scenario until the module's timeout. Verify, store the event, return 200, and do the work afterwards. See why to process webhooks asynchronously.

Conclusion

Make sends exactly the request your scenario builds, with an API key keychain header as the credential you add. Place the key in a header, compare it in constant time, give every body an event and an id, and plan your own error handling, because the module has no retry policy of its own.

Hookdeck Event Gateway sits in front of your receiver, checks the keychain header, answers the module at once, and keeps every event until your service has processed it.

Get started with Hookdeck for free and receive Make scenario requests reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.