Blog

Make7 min read

Send form submissions to Make

Start a Make scenario from every Ikiform submission with a custom webhook, and add a small relay when you want each delivery verified.

Preet SutharFounder, Ikiform

Make's custom webhooks accept any JSON, so Ikiform can post to them directly. This guide sets that up first, then shows how to add signature checks with a short relay, because Make can't read Ikiform's signature on its own without extra work.

Two routes from Ikiform to MakedirectverifiedIkiformstores it, signs awebhookMakecustom webhook,accepts any requestIkiformstores it, signs awebhookrelayverifies, addsx-make-apikeyMakewebhook with an APIkeysignedsignedsame bodyTwo routes from Ikiform to MakedirectverifiedIkiformstores it, signs a webhookMakecustom webhook, accepts anyrequestIkiformstores it, signs a webhookrelayverifies, adds x-make-apikeyMakewebhook with an API keysignedsignedsame body
  1. Direct route: Ikiform posts each signed submission straight to the Make custom webhook. Make can't check the signature, so anyone who learns the URL can start the scenario.
  2. Verified route: Ikiform posts to a relay. The relay checks the signature, then forwards the same body to Make with the x-make-apikey header.
  3. Make's webhook has an API key on the verified route, so it refuses anything without that header.
The direct route skips the relay. The verified route puts a relay between Ikiform and Make.

Before you start

  • An Ikiform form that already receives submissions.
  • A Make account. Each run uses operations from your plan.
  • For the verified route, somewhere to run the relay: a Cloudflare account with a domain on it, or a Next.js app.

What Ikiform sends

Every delivery is a POST with a JSON body. The body has the same shape for every endpoint, and you can't change it. A submission looks like this:

submission.created
{
  "id": "dlv_01k7v2d4n8r2p6s0w3y5b7c9e1",
  "type": "submission.created",
  "timestamp": "2026-10-23T12:00:00.000Z",
  "api_version": "2026-10-17",
  "data": {
    "submission_id": "sub_01k7v2c9t3e8m5q4x6z0a1b2c3",
    "form": { "id": "frm_xxxxxxxxxxxxxxxx", "name": "Contact" },
    "fields": { "name": "Ada", "email": "ada@example.com", "message": "Hello" },
    "meta": {
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
      "origin": "https://example.com",
      "referrer": "https://example.com/contact",
      "country": "GB",
      "subject": null,
      "reply_to": "ada@example.com"
    },
    "created_at": "2026-10-23T12:00:00.000Z",
    "truncated": false
  }
}

The form's values are in data.fields, keyed by the input name. A test from the dashboard sends an endpoint.test event instead, with data.endpoint_id and data.message and no fields. The full reference is on Webhooks.

Pick a route

RouteSetupWho can start the scenario
DirectPaste the Make URL into IkiformAnyone who learns the URL
VerifiedDeploy a 30-line relayOnly requests signed with your Ikiform secret

Start direct to build the scenario. Move to the verified route before the scenario writes anything that matters, such as CRM records or emails.

Direct route

  1. Add a custom webhook

    1. Create a scenario and add the Webhooks app with the Custom webhook trigger.
    2. Choose Add, name the webhook, for example Ikiform, and save.
    3. Copy the address. It looks like https://hook.eu1.make.com/abc123..., with the region of your Make account.
  2. Add the endpoint in Ikiform

    • In the Ikiform dashboard, open Webhooks and choose Add endpoint.
    • Paste the Make webhook address into URL.
    • Under Forms, pick one form, or All forms in the workspace.
    • Add a Description if you like, such as "Make", then choose Add endpoint.
    • Copy the signing secret. It starts with whsec_ and is shown in full only once.

    There's no event picker. An endpoint gets submission.created for every accepted submission on the forms you chose, and endpoint.test when you send a test. A workspace on Pro can have up to 3 endpoints.

  3. Teach Make the data structure

    Make learns the fields from the first request it sees. With the webhook module open and waiting, send one real submission from your form, not a dashboard test, because test events have no fields. If you add fields to the form later, open the module and choose Redetermine data structure, then send another submission.

  4. Filter and map

    Add your next module, such as Google Sheets or Slack. On the link between the two, add a filter where type equals submission.created. Then map values from data > fields, such as email and message.

    Turn the scenario on so it runs as soon as data arrives.

On the direct route, keep the Make address out of public code and screenshots. Make's own API key option for webhooks expects an x-make-apikey header, and Ikiform can't add custom headers, so the verified route below is how you lock it down.

Verified route

The relay checks Ikiform's signature, then forwards the exact same body to Make with an API key header. The scenario stays the same, and Make refuses anything that doesn't carry the key.

  1. Add an API key to the webhook

    In Make, open the webhook's settings and add an API key. Make then only accepts requests that send that key in the x-make-apikey header. Copy the key.

  2. Write the relay

    import { verifyWebhook, type WebhookEvent, WebhookVerificationError } from "@ikiform/sdk/webhooks";
    
    interface Env {
      IKIFORM_WEBHOOK_SECRET: string;
      MAKE_WEBHOOK_URL: string;
      MAKE_API_KEY: string;
    }
    
    function forward(url: string, apiKey: string, payload: string) {
      return fetch(url, {
        method: "POST",
        headers: { "content-type": "application/json", "x-make-apikey": apiKey },
        body: payload,
      });
    }
    
    export default {
      async fetch(request: Request, env: Env) {
        if (request.method !== "POST") return new Response(null, { status: 405 });
        const payload = await request.text();
        let event: WebhookEvent;
        try {
          event = await verifyWebhook({ payload, headers: request.headers, secret: env.IKIFORM_WEBHOOK_SECRET });
        } catch (error) {
          if (error instanceof WebhookVerificationError) return new Response(error.reason, { status: 400 });
          throw error;
        }
        const response = await forward(env.MAKE_WEBHOOK_URL, env.MAKE_API_KEY, payload);
        if (response.status === 429) {
          const retryAfter = response.headers.get("retry-after") ?? "30";
          return new Response("Make rate limit", { status: 503, headers: { "retry-after": retryAfter } });
        }
        if (!response.ok) return new Response(`Make answered ${response.status}`, { status: 502 });
        return new Response(null, { status: 204 });
      },
    };
    • The relay forwards payload, the raw string it verified, so Make sees exactly what Ikiform sent and the data structure doesn't change.
    • A 429 from Make becomes a 503 with Make's Retry-After, and any other error becomes a 502. Ikiform retries both.
  3. Deploy it

    Cloudflare Worker

    Terminal
    mkdir ikiform-make && cd ikiform-make
    npm init -y
    npm install @ikiform/sdk
    npm install -D wrangler
    wrangler.jsonc
    {
      "$schema": "node_modules/wrangler/config-schema.json",
      "name": "ikiform-make",
      "main": "src/index.ts",
      "compatibility_date": "2026-10-01",
      "routes": [{ "pattern": "hooks.example.com", "custom_domain": true }]
    }
    Ikiform refuses workers.dev URLs, so the Worker needs a hostname on a domain you have on Cloudflare, like hooks.example.com. The custom_domain route creates the DNS record and certificate for you on deploy.
    Terminal
    npx wrangler secret put IKIFORM_WEBHOOK_SECRET
    npx wrangler secret put MAKE_WEBHOOK_URL
    npx wrangler secret put MAKE_API_KEY
    npx wrangler deploy

    Next.js

    Add @ikiform/sdk, save the route handler, and set IKIFORM_WEBHOOK_SECRET, MAKE_WEBHOOK_URL and MAKE_API_KEY in your host's environment variables. Use the production domain, not a protected preview URL.

  4. Point Ikiform at the relay

    Open the endpoint in Ikiform, choose Edit, and change URL to the relay URL. The signing secret stays the same; put it in IKIFORM_WEBHOOK_SECRET on the relay.

Ikiform only delivers to public https:// URLs on port 443. IP addresses, localhost, internal hostnames, workers.dev and pages.dev are refused when you save the endpoint.

Test it

Open the endpoint in Ikiform and choose Send test. Ikiform sends one endpoint.test event with no retries, and the result shows up in the endpoint's delivery log within a few seconds. Then send a real submission from your form, or from a terminal:

Terminal
curl https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada","email":"ada@example.com","message":"Hello from curl"}'

A 201 with "ok": true means Ikiform stored it. The delivery appears on the endpoint page, and the message lands in Make's scenario History.

If the form has a human check or allowed domains turned on, a post from curl is refused or marked as spam, and spam never sends a webhook. Test from your real site instead.

The test event runs the scenario and stops at the filter. A real submission continues through it.

How delivery works

The receiver answersIkiform
Any 2xx within 15 secondsMarks the delivery succeeded
A redirectDoesn't follow it, and counts a failure
429 or 503 with Retry-AfterWaits that long, up to the next step of the schedule
410 GoneFails the delivery and disables the endpoint
Anything else, or no answer in 15 secondsRetries

Failed deliveries are retried 8 times over about 3 d 6 h, with the same webhook-id each time. If every delivery to an endpoint fails for 5 days, Ikiform disables it and emails the workspace owners.

What the relay tells Ikiform when Make answers2xxok204no contentdonedelivery succeeded429rate limited503same retry-afterwaitsthen tries againother error4xx or 5xx502bad gatewayretries8 retries over about3 d 6 hMake answersrelay answersIkiformWhat the relay tells Ikiform when Make answers2xxok204nocontentdonedeliverysucceeded429ratelimited503sameretry-afterwaitsthentriesagainothererror4xx or5xx502badgatewayretries8 retriesoverabout3 d 6 hMake answersrelayanswersIkiform
  1. Make accepts the request: the relay answers 204, and Ikiform marks the delivery succeeded.
  2. Make is rate limited (429): the relay answers 503 with Make's Retry-After, and Ikiform waits that long before it tries again.
  3. Make answers with any other error: the relay answers 502, and Ikiform retries, 8 retries over about 3 d 6 h.
On the verified route. On the direct route, Make answers Ikiform itself.

Without a Webhook response module, Make answers 200 Accepted as soon as the request is queued, before the scenario runs. Ikiform counts that as delivered. If a later module fails, rerun it from Make's history; Ikiform won't retry it. If you add a Webhook response module, place it early, so Make answers within Ikiform's 15 seconds.

Troubleshooting

ProblemWhat to do
400 with Queue is fullThe scenario is off or slow, and Make's webhook queue filled up. Turn the scenario on; Ikiform retries the deliveries.
502 with Make answered 4xx on the verified routeMake refused the request, most often because MAKE_API_KEY doesn't match the key on the webhook. Copy it again and update the relay.
New form fields don't show up in the mappingOpen the webhook module, choose Redetermine data structure, and send a submission that includes the new fields.
Endpoint disabled right after you deleted or changed the scenarioIkiform disables an endpoint at once if it answers 410 Gone, which can happen when nothing listens on a Make address anymore. Create a new webhook, update the endpoint URL, and turn Enabled back on.
400 no_matching_signatureThe secret is wrong, or the body was parsed and re-serialized before verifying. Use the whsec_ secret of this endpoint and the raw body exactly as received. After Roll secret, update it within 24 hours.
Delivery log shows timeoutNothing answered within 15 seconds. Answer first and do slow work after, or make sure the tool responds right away.
Endpoint is disabledEvery delivery failed for 5 days, the URL answered 410, or its hostname started resolving to a private address. Fix the cause, then turn Enabled back on and Retry now the failed deliveries.
No delivery at allCheck that the endpoint covers this form, that it's enabled, and that the submission wasn't marked as spam or held because the workspace is over its monthly limit.

Next steps

Want toRead
Add each submission as a sheet rowSend form submissions to Google Sheets
Verify inside the workflow tool itselfSend form submissions to n8n
See every header and retry ruleWebhooks

Make's own reference: Webhooks and the Webhooks app.

Stuck on a step, or want a guide for another tool? Email hello@ikiform.com.