Our September 2026 position: keep intake narrow

On September 7, 2026, we compared the live public overview with the API Docs inside the current packaged plugin. The two surfaces describe different generations of the signing contract. The installed package specifies the timestamped contract shown below. That finding is the reason for this post and for the implementation rule that follows.

A webhook should mark the boundary where an upstream event becomes intended deal state. It should not become a hidden workflow engine. The sending system owns event capture and a stable external identifier; the request owns a deterministic payload and signature; Deal Flow owns turning that accepted payload into a deal create or update.

The design rule: one delivery should state the deal result you want, not ask the receiver to reconstruct a chain of upstream events.

Treat the installed in-app API Docs as the implementation authority for the URL and headers. That is why the worked request uses a configured WEBHOOK_URL rather than copying a fixed route from an editorial page. Confirm the signing section inside the Mautic instance that will receive production traffic.

Plan repeated delivery before the first request

Give each upstream opportunity one durable external_ref, such as the opportunity ID from a billing app, form service, or internal platform. Reuse it for the life of that opportunity. During ordinary sequential processing, the current intake path can use that reference to update a matching deal on a later delivery, or create a deal when no match is found.

A stable reference helps with deal matching; it is not a request idempotency key. If a deal-field request times out, send it again only when applying those intended field values a second time is acceptable. Do not mint a new reference for each attempt.

Notes and tasks need a different policy because they are additive. Repeating a payload that creates one can create another. Give the sender its own delivery ledger or deduplication rule for those operations, and reconcile an uncertain result before retrying it.

Prefer sending the full set of deal fields the upstream system intends to own. A partial sequence such as “create, then add context, then fix the stage” creates more points where delivery can stop halfway. A complete intended-state payload gives an operator one message to inspect and one result to reconcile.

Sign the bytes that leave the system

The current packaged contract signs the Unix timestamp, a period, and the exact raw body with the webhook source secret. The hexadecimal digest goes in X-DealFlow-Signature; the timestamp goes in X-DealFlow-Timestamp. This Bash example keeps one BODY value for both signing and sending:

TIMESTAMP=$(date +%s)
BODY='{"external_ref":"crm-123","title":"Renewal opportunity"}'

SIGNATURE=$(printf '%s.%s' "$TIMESTAMP" "$BODY" \
  | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -binary \
  | xxd -p -c 256)

curl --request POST "$WEBHOOK_URL" \
  --header "Content-Type: application/json" \
  --header "X-DealFlow-Timestamp: $TIMESTAMP" \
  --header "X-DealFlow-Signature: $SIGNATURE" \
  --data-raw "$BODY"

printf adds no trailing newline here. The sender signs BODY and then passes that same value to curl. Do not parse the JSON, reorder its keys, pretty-print it, or serialize it again between those steps. A semantically identical object can have different bytes and therefore a different digest.

Keep WEBHOOK_SECRET on the server that sends the request. Read WEBHOOK_URL from the configured source rather than assembling a route from an article, because the installed release is the authority for its own endpoint. Log the external reference and response outcome, but keep the signing secret out of application logs.

Choose n8n when the workflow owns decisions

A direct webhook fits when one code-controlled producer already has a durable queue, can preserve raw payload bytes, and needs one inbound deal operation. It keeps the path short: build the intended state, sign it, send it, and apply a repeat policy appropriate to the fields involved.

Use the Mautic and n8n workflow guide when the integration needs visual field mapping, conditional branches, data from several apps, or a sequence such as create a deal, attach a contact, add a note, and schedule a task. n8n is also the more practical boundary when the source tool cannot produce the required signature without custom code.

Operate the intake as a real boundary

Test with a source created for staging before connecting production events. Capture the upstream reference, send time, destination source, response status, and retry count so an operator can trace a delivery without exposing its secret. Test repeated deal-field delivery separately from the sender’s deduplication path for notes and tasks.

Frequently asked questions

How is a Deal Flow webhook signature generated?

For the current packaged contract, concatenate the Unix timestamp, a period, and the exact raw request body. Generate an HMAC-SHA256 digest with the source secret, encode it as lowercase hexadecimal, and send it in X-DealFlow-Signature with the timestamp in X-DealFlow-Timestamp.

How should I handle a repeated webhook delivery?

Reuse a stable external_ref to help Deal Flow match the deal, but do not treat it as a request idempotency key. Automatically retry deal-field payloads only when sending those values again is acceptable. Notes and tasks are additive, so deduplicate them at the sender or reconcile them before retrying.

Should the receiver sign parsed JSON?

No. Sign the exact bytes sent in the HTTP body and transmit those same bytes. Parsing and serializing JSON again can change whitespace or key order, which changes the digest.

When should I use n8n instead of a direct webhook?

Use n8n when the integration needs visual field mapping, branching, several Deal Flow actions, or a workflow-level retry path. Use a direct webhook when one code-controlled producer can build, sign, queue, and repeat deal-field delivery under an explicit policy.

If a focused webhook intake belongs in your revenue workflow, see how Deal Flow handles the deal record inside Mautic.

See Deal Flow pricing