Workflow vs Messaging Webhooks
Choose Workflow webhooks, Messaging webhooks, or both. Same token, different jobs.
There is no single product named “workflow webhooks” or “messages webhooks.” Both products expose inbound HTTP (external → NotionApps) and outbound HTTP (NotionApps → external). They look similar in a network log and share one per-app webhook secret, but they are different products with different jobs.
Short answer
A button or form to call Make/Zapier, wait for JSON, then refresh the already-open tab
Workflow: Call webhook and wait
An external system to start a specific workflow (create/update records, conditions, Notify)
Workflow: Webhook received
That workflow to tell another system “this run finished” (no response needed)
Workflow: Notify → Webhook
An event to fan out to several destinations (workflow + partner URL + linked app + screen)
Messaging: inbound webhook and/or webhook subscriber
Structured routing (channel, topic, contract, subscribers, request/reply)
Messaging
Both process logic and multi-subscriber routing
Both
Rule of thumb
Workflow is the process engine: decisions, waits, record writes, emails, and “do this then that.”
Messaging is the event bus: publish once, deliver to whoever subscribed.
Call webhook and wait is the only path that can update the same open portal tab after an external system returns JSON. Nothing inbound can do that.
The two products
Workflow Foundation
Workflow is a published graph: a trigger starts a run, then steps execute in order (conditions, Notion writes, Notify, waits, UI actions).
Webhooks appear in three Workflow places:
Trigger: Webhook received — inbound. An external POST starts matching published workflows.
Step: Notify → channel Webhook — outbound, fire-and-forget. The run POSTs to one or more URLs and continues without using the HTTP response.
Step: Call webhook and wait — outbound, synchronous. The run POSTs, waits for JSON, stores it on
context.<step_id>, then can Refresh / Open screen / Show message on the open tab.
Trigger
Webhook received
webhook_received
Step
Call webhook and wait
call_webhook_and_wait
Step
Notify, channel Webhook
send_notification + channel: "webhook"
Copy the intake URL and cURL from the Workflow builder when the trigger is Webhook received.
Messaging Foundation
Messaging is an app-level channel + topic + contract router. Something publishes a message; subscribers receive it.
Webhooks appear in two Messaging places:
Inbound messaging webhook — an external POST publishes a message. It does not start a workflow by itself. Workflows start only if a subscriber (or a Message received trigger) is wired.
Subscriber type: Webhook — outbound. When a message matches the subscription, NotionApps POSTs a messaging envelope to the destination URL.
Builder sidebar
Messaging
Subscriber type
Webhook
Automation recipes
Send event to webhook; External API/webhook → create record
Messaging inbound URLs are not copied from the Messaging builder today. Use the shapes in Webhook Technical Reference. Generate the secret in the Workflow builder; the same secret authenticates Workflow and Messaging inbound for that app.
Messaging is not SMS, email delivery, or the in-app inbox. Those are Workflow Notify (email / in-app) or Messaging screens (Conversation, Notification Center, Work Queue). A webhook is just one subscriber type on the bus. See Messaging and Notifications.
All webhook surfaces at a glance
Webhook received
Workflow
In
No
Workflow run
No
Notify → Webhook
Workflow
Out
No (10s timeout, result unused)
Nothing new; continues the run
No
Call webhook and wait
Workflow
Out
Yes (8s inline, then poll up to 45s)
Nothing new; continues the run
Yes, if Live screen updates is on
Messaging inbound
Messaging
In
No
A message, then subscribers
No
Messaging webhook subscriber
Messaging
Out
No (10s timeout)
Nothing; delivers the message
No
Legacy sheet automation still has Trigger Webhook / Trigger Integromat (Make)/Zapier. That is the old builder path, not Workflow Foundation.
How they actually differ
1. What a successful inbound “does”
Workflow inbound (POST /v1/webhooks/workflow-events or the app alias)
Matches published workflows whose trigger is Webhook received.
Success looks like:
{ accepted: true, runs_created, run_ids, intake_event_id }.The POST body becomes
trigger_payloadfor that run.
Messaging inbound (POST /v1/webhooks/messaging-events or the app alias)
Requires a
channel(and usually atopic).Publishes a message on that route.
Success looks like:
{ accepted: true, message_id, deliveries_created, intake_event_id, deliveries }.Workflows run only if something subscribed (workflow subscriber or Message received trigger).
Same per-app secret and header (x-notionapps-webhook-token). Different URL, different required body, different success metric.
2. What outbound POSTs look like
Workflow Notify → Webhook (User-Agent: NotionApps-Workflow/1.0)
This is “here is the run that just happened.” Good for Make/Zapier scenarios that need run identity and accumulated step context.
Call webhook and wait
POSTs either the configured JSON body or, if empty, the full
trigger_payload.Adds
Idempotency-Key: {run_id}:{step_id}.Expects Webhook response JSON back (Make’s Webhook response module).
Stores the parsed body on
context.<this_step_id>(http_status,timed_out, plus response fields such ascart_record_id).Downstream steps map those fields (Open screen
record_id, conditions, Show message).
Messaging webhook subscriber (User-Agent: NotionApps-Messaging/1.0)
payload is full, redacted, or empty (metadata_only) per subscription visibility. There is no run_id / subject / body unless you put them in the message payload yourself.
3. Fan-out vs single run
Workflow is one run, one graph. Multiple outbound URLs mean multiple Notify endpoints (or multiple steps).
Messaging is one publish, N subscribers. The same approval event can start a workflow, POST a partner webhook, hand off to a linked app, and land in Notification Center without duplicating the publisher.
4. Time, retries, and the open tab
Inline on button tap
Yes, if Live screen updates is on
No (background)
No
Sync wait
Default 8s, max 12s inline
—
—
Worker wait
Up to 45s
10s per URL
10s
Client poll after timeout
45s (“Working…”)
—
—
4xx/5xx
Fail, no retry, error toast if inline
Retryable queue error
Delivery retry / Activity status
Idempotency-Key
Yes
No
Message idempotency_key on ingest
Can refresh open tab
Yes
No
No
Live screen updates must be on for the app, or Refresh after Call webhook and wait will not update the open tab. The switch is off by default. NotionApps turns it on from Workflow Operations → Controls. See the 28 Aug 2026 Release and the Step catalog.
Inbound of either kind cannot refresh a tab that is already open. If Make must compute something and the user should see it without a manual refresh, the button must use Call webhook and wait, not “Make calls NotionApps back.”
5. Auth, plans, and monitoring
Shared: a per-app webhook secret you generate in the Workflow builder (x-notionapps-webhook-token; also Authorization: Bearer and x-workflow-webhook-token). Copy it once. After this app has an active secret, the old shared platform token stops working for it. How to generate and rotate: Webhook Technical Reference.
Independent:
Where makers configure it
Workflow builder
Messaging builder + subscriptions
Entitlement
Workflow on
Messaging External API for outbound webhook subscribers
Kill switches
Workflow Operations → Webhooks
Messaging Operations → Webhooks
You can disable Messaging outbound without touching Workflow Notify, and the reverse.
6. Gaps that cause the wrong pick
Workflow inbound URL is in the builder. Messaging inbound URL is not.
People paste a Workflow intake URL into a Messaging-style partner spec (missing
channel) or the reverse (Workflow body withchannel/topicand no matching workflow).People use Notify webhook when they needed Call webhook and wait, then wonder why the open tab did not refresh.
People use Messaging inbound and expect
runs_created— they will getmessage_idinstead.
When to use Workflow only
Use Workflow webhooks when the integration is the process.
Webhook received → steps → optional Notify webhook
Partner POSTs “new order / new ticket / status changed.”
You need conditions, create/update Notion records, email someone, then optionally ping another system.
One workflow owns the outcome. You do not need channel/topic routing or multiple subscribers.
The Webhook intake template is this pattern: receive → check → write record → Notify downstream.
Button / form → Call webhook and wait → Refresh / Open screen / Show message
User taps Request Revision, Build cart, Price this, or similar.
Make (or any webhook) must return JSON before the same tab updates.
Live screen updates must be on for that app.
Make must end with a Webhook response module.
Button / form → Notify webhook
User action should tell Slack/Make/a warehouse that something happened.
You do not need the HTTP response and you do not need the open tab to wait.
Do not use Workflow-only when the same event must go to several independent consumers, or when you want contracts, dry-run, linked-app handoff, or request/reply as the primary model.
When to use Messaging only
Use Messaging webhooks when the integration is the event.
Inbound messaging webhook
External system already thinks in events:
integrations / record.approved.You want NotionApps to accept the event even if today’s subscribers change tomorrow.
Webhook subscriber
An app event (form, button publisher, Workflow Publish message, inbound message) should POST to CRM / warehouse / Zapier / a custom API.
Visibility policy matters (
metadata_only/redacted/full).You may add a second subscriber later without changing the publisher.
Do not use Messaging-only when the open tab must update from Make’s JSON, when you need a copied intake URL in the maker UI today, or when you need the Workflow Notify envelope (run_id, subject, body, context) as the outbound contract.
When to use both
They are designed to stack. Shared token, separate policies.
Pattern A — External event → bus → process + partners
Use when the inbound event is a domain event, not “start this one workflow.”
Pattern B — Process first, then publish for routing
Use when Workflow owns the decision, but several systems should hear the result.
Pattern C — Workflow inbound + Workflow Notify (no Messaging)
This is both directions of Workflow, not “both products.” Fastest partner demo. No subscribers or linked-app fan-out.
Pattern D — Make-then-refresh, plus a bus event
Call webhook and wait is for the user. Messaging (or Notify) is for everyone else.
Pattern E — Automation recipe “External API/webhook → create record”
Guided Automation often wires Messaging inbound + contract + workflow subscriber. That is both products even if you only saw one recipe. See Start From a Wizard.
Decision tree
Worked examples
1. Approve on the open tab (no Make)
Workflow: Update / Change status → Refresh → Show message. No webhook. Live screen updates on. Messaging only if other apps or a warehouse must hear record.approved.
2. Request Revision via Make, then stay on the same screen
Workflow: Call webhook and wait → Refresh or Open screen. Not Notify webhook. Not Messaging inbound. Not “Make POSTs back to NotionApps.”
3. Partner sends “payment succeeded”
Workflow-only: Webhook received → create payment row → Notify email → optional Notify webhook.
Messaging (better if more consumers are coming): inbound on integrations / payment.succeeded → workflow subscriber writes the row → webhook subscriber to finance → later a linked-app subscriber without changing the partner.
4. Form submit should email a manager and ping Slack
Simple: Workflow on Form submitted → Notify email → Notify webhook.
Routable: Workflow Publish message → webhook subscriber does Slack. Use this if Slack is one of several listeners.
5. Two apps, one approval
Messaging: publish on a contract; linked_app subscriber plus optional webhook subscriber for a non-NotionApps system. Workflow in each app handles local writes. See Linked App Exchange.
Inbound request shapes (do not mix)
Workflow inbound
Messaging inbound
Production API host is https://api.notionapps.com unless support tells you otherwise. Do not mix staging tokens with production URLs. Full curl: Webhook Technical Reference.
What each cannot do
Start a specific workflow from a partner POST
Yes
—
—
Only via subscriber
—
Fan-out to N destinations from one event
No
Multiple URLs on one step only
No
Yes
Yes (as one of N)
Use Make’s JSON on the open tab
No
No
Yes
No
No
Return run_id / step context to a catcher
—
Yes
Custom body only
—
Only if you put it in payload
Contracts / dry-run / linked apps
No
No
No
Yes
Yes
Copy intake URL in maker UI
Yes
—
—
Not today
—
Simulator / builder preview does not prove live HTTP. Use a real inbound curl and an outbound catcher on the target environment.
Common mistakes
Treating Workflow and Messaging as two phases of one webhook. They are two products. A partner can call either URL; the wrong one “succeeds” with a different JSON shape and no visible workflow.
Notify webhook for Make-then-refresh. Notify does not wait and cannot refresh the open tab. Use Call webhook and wait; Make must respond with Webhook response JSON.
Inbound Make → NotionApps to update the tab. Inbound starts new work in the background. The tab that already sent the button tap will not refresh from that.
Messaging inbound, looking for
runs_created. You will seemessage_id. Ifdeliveries_createdis 0, no subscriber matched — the workflow never ran.Workflow inbound body with only
channel/topic. Workflow matching uses application/target/conditions, not Messaging routes.Assuming one kill switch. Workflow outbound off does not stop Messaging subscribers, and the reverse.
Missing External API. Messaging webhook delivery needs Messaging External API. Workflow Notify / Call webhook and wait do not use that same gate.
Using email, SMS, or Conversation screens as “message webhooks.” Unrelated. Conversation is an in-app screen.
Builder checklist
Workflow is published (drafts can accept HTTP and create zero runs).
Use a new
event_id/idempotency_keywhen retesting.Call webhook and wait has a URL; Make returns JSON via Webhook response.
Messaging subscriber destination is a real
https://URL.Messaging outbound needs External API entitlement.
If someone says “the webhook failed” or “the webhook worked but nothing happened,” ask which URL, which User-Agent, and what the success JSON was (runs_created vs message_id / deliveries_created). That identifies the product before you open the app.
Related
Webhooks and Integrations — Call webhook and wait setup
Webhook Technical Reference — URLs, tokens, curl
Messaging and Notifications — channels, topics, subscribers
Application Messaging Foundation Guide — contracts and External API
Workflow Foundation User Guide — steps and runs
Step catalog —
call_webhook_and_wait,send_notification,publish_message28 Aug 2026 Release — live screen updates