Webhooks in FilaForms: Send Submissions Anywhere | FilaForms                                 [ ![Filaforms Logo](https://filaforms.app/logo.svg)FilaForms

 ](https://filaforms.app)  [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app)  [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

 [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app) [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

   ![FilaForms](https://filaforms.app/logo.svg) FilaForms

 IntegrationsWebhooks in FilaForms: Send Submissions Anywhere
================================================

 filaforms.app/blog

  [    Back to blog ](https://filaforms.app/blog) [ Integrations ](https://filaforms.app/blog/category/integrations)

Webhooks in FilaForms: Send Submissions Anywhere
================================================

 Manuk Minasyan ·  May 19, 2026  · 8 min read

 Someone fills out a form on your site. Now what?

Maybe it needs to drop into Slack so your support team sees it within thirty seconds. Maybe it has to land in your CRM as a new lead. Maybe it kicks off a background job that provisions a trial account.

You have three options. Wire up Laravel form webhooks and let the form POST the submission directly to whatever endpoint cares. Build the integration yourself — OAuth flows, API clients, retry logic, and a new thing to maintain forever. Or pay for a SaaS bridge like Zapier or Make and eat the monthly bill, the rate limits, and the extra hop.

Webhooks are the universal escape hatch. One HTTP POST, your endpoint, do whatever you want with the payload. They're not glamorous. They don't show up in marketing screenshots. But they're the reason FilaForms can talk to systems we've never tested against and never will.

This post is the hub for everything else I'm writing about integrations. Slack, Notion, CRM, Discord, internal APIs — most of those posts will end up referencing the webhook flow described here, because once you understand it, the rest is mostly about which URL to point at.

What a webhook actually is
--------------------------

Strip away the jargon and a webhook is just an HTTP request you didn't initiate.

Normally your app makes requests to other services. You call Stripe, you call SendGrid, you call OpenAI. A webhook flips that around. Some external event happens — a form gets submitted, a payment clears, a customer cancels — and the system where the event happened reaches out to *you* with a POST request. JSON body, a URL you control, your code handles it.

There's a distinction worth getting right early. People use "webhook" to mean two different things, and they get mixed up constantly.

An **outgoing webhook** is what FilaForms sends. Your form is submitted, FilaForms makes a POST request to a URL you provided, and your endpoint decides what to do.

An **incoming webhook** is a URL that some other service hands you. Slack and Discord are the classic examples. They give you a URL, and anything you POST to it shows up as a message in a channel. From FilaForms' perspective, posting to a Slack incoming webhook is still an outgoing webhook on our side. The direction is always relative to whose code is doing the sending.

For form submissions, you almost always want outgoing. FilaForms sends, you receive.

How FilaForms sends webhooks
----------------------------

When someone submits a form, a `FormSubmitted` event fires. The integration manager listens for that event, looks up which integrations are configured for that form, and queues a job for each one. The job picks up the submission, builds the payload, and makes the POST request.

The reason it's queued is uptime. Your customer is still sitting on the success page. They don't need to wait while we try to reach a third-party URL that might be slow, broken, or behind a tunnel that fell asleep. The form returns instantly. The webhook delivery happens in the background.

If the request fails — non-2xx response, timeout, DNS error, anything — the job is retried with exponential backoff. First retry after a minute, then a few minutes, then longer, up to a configurable ceiling. Every attempt writes a row to the delivery log so you can see exactly what was sent, what came back, and which try succeeded.

Here's what a delivery payload looks like:

```
{
  "event": "form.submitted",
  "form_id": "01HX8K2P9Z3RTQVQX7N9YEFM7C",
  "submission_id": "01HX8K3F4N6WJ8B5VCXKD2GAHB",
  "submitted_at": "2026-05-19T14:32:18Z",
  "fields": {
    "full_name": "Jordan Hayes",
    "email": "jordan@example.com",
    "company_size": "11-50",
    "message": "Interested in a demo."
  }
}

```

Fields are keyed by their slug, not their display label, so a label change in the admin doesn't break your downstream parser. That mattered to me. I've been on the wrong end of webhooks where someone edits a field title and three of my Zaps quietly stop working.

The payload shape
-----------------

The body is always JSON. The top-level keys you can rely on are `event`, `form_id`, `submission_id`, `submitted_at`, and `fields`. The first four are stable. The contents of `fields` change per form, but the keys are stable per field — they're the slugs you set when building the form, not the human labels.

Standard headers go out with every request:

- `Content-Type: application/json`
- `User-Agent: FilaForms/x.x`
- `X-Filaforms-Signature` — HMAC signature for verification (more on this in a second)
- `X-Filaforms-Delivery` — a unique ID for the delivery attempt, useful for deduplication on your side

To check whether a request came from us — or from someone who guessed your endpoint — verify the signature header.

Verifying it's really us
------------------------

Webhooks are public URLs. Anyone who learns your endpoint can POST to it. The fix is HMAC: we sign every payload with a shared secret you configured, and you verify the signature on receipt before trusting anything in the body.

The verification is short. In PHP it looks roughly like this:

```
$payload = $request->getContent();
$signature = $request->header('X-Filaforms-Signature');
$secret = config('services.filaforms.webhook_secret');

$expected = hash_hmac('sha256', $payload, $secret);

if (! hash_equals($expected, $signature)) {
    abort(401);
}

```

`hash_equals` matters there. Don't compare signatures with `===` — it's vulnerable to timing attacks. `hash_equals` does the constant-time comparison this kind of check needs.

If the signatures match, you trust the payload. If they don't, treat the request as hostile and drop it.

What you can do with it
-----------------------

Once you have a verified payload, you can do anything PHP can do. A few obvious ones, each of which I'll cover properly in its own post:

**Post to a Slack incoming webhook.** Format the submission as a Slack message, POST it to the channel URL, and your team sees a real-time feed of submissions without anyone logging into the admin. *Coming up: a dedicated post on Slack delivery, including how to format Block Kit nicely.*

**Trigger a Zapier, Make, or n8n workflow.** Use the webhook as the input step for any of those platforms. From there, anything they connect to is one click away. Useful when the destination is a tool we don't (and won't) integrate with directly. *Coming up: walking through a Make scenario end to end.*

**Call your own internal API.** Provision an account, write to a database we can't see, kick off a queued job in another service, send a templated email through your own infrastructure. The webhook becomes the bridge between FilaForms and whatever else your stack does.

There's a generic version of all of these: webhook payload arrives, your code decides, your code acts. The integration manager doesn't care what's on the other end.

What we got wrong the first time
--------------------------------

The first version of FilaForms webhooks was synchronous. Form gets submitted, controller fires the request, waits for the response, then returns success to the user.

It worked great in development. Every endpoint I tested against responded in under fifty milliseconds. The code was simpler. There was no queue worker requirement, no delivery log table, no retry logic to write.

Then a real user pointed their webhook at a Zapier endpoint, and Zapier had a slow morning. Their form started timing out. Users saw the spinner for eight seconds, then a generic error page. Submissions were still being saved — that part happened before the webhook — but as far as the person filling out the form knew, the whole thing was broken.

We pulled it apart and rebuilt it as queued, retried, and logged. The form response happens instantly. The webhook delivery happens whenever the worker gets to it, and the user never sees the latency of someone else's server.

The lesson, which I've now re-learned in a few different projects: never put someone else's uptime on your hot path. If a third party can take your form submission flow down by being slow, your architecture is wrong, not theirs.

Try it
------

Webhooks are part of the integrations package in FilaForms. Configure a URL, set a secret, point the form at it, and you have a delivery pipeline that retries when things go sideways and logs every attempt so you can debug them after the fact.

If you want to try it, you can [grab FilaForms here](https://filaforms.app) and follow the [webhook setup walkthrough in the docs](https://docs.filaforms.app). More posts in the Connect series are coming — Slack, Notion, CRM destinations, and the no-code bridges — and they all build on the foundation in this one.

 Related posts
-------------

 [  Integrations   Apr 27, 2026

 Sending Form Submissions to Google Sheets Automatically
---------------------------------------------------------

Your marketing person doesn't want to log into your admin panel. Your sales lead doesn't care about Filament. They want a spreadsheet. And honestly, that's

 ](https://filaforms.app/blog/sending-form-submissions-to-google-sheets-automatically) [  Integrations   Apr 20, 2026

 Collecting Payments with Stripe Connect in FilaForms
------------------------------------------------------

Sometimes a form needs to collect money, not just data. Registration fees, order payments, donation amounts. If you're running FilaForms on your own server, you probably don't want to bolt on a separate payment system and duct-tape it to your form submissions. Stripe Connect lets you handle the w...

 ](https://filaforms.app/blog/collecting-payments-with-stripe-connect-in-filaforms)

    ![FilaForms Logo](/logo.svg) FilaForms

 Laravel form infrastructure for Filament. Stop rebuilding forms on every project.

 ### Product

 [ Features ](https://filaforms.app#features) [ Documentation ](https://docs.filaforms.app) [ Blog ](https://filaforms.app/blog) [ Pricing ](https://filaforms.app#pricing) [ Contact ](mailto:hello@filaforms.app)

 ### Legal

 [ Terms of Service ](https://filaforms.app/terms-of-service) [ Privacy Policy ](https://filaforms.app/privacy-policy)

  © 2025-2026 FilaForms. All rights reserved.

 [    ](mailto:hello@filaforms.app) [    ](https://x.com/MinasyanManuk)
