For the complete documentation index, see llms.txt. This page is also available as Markdown.

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.

Start here if you are choosing an integration path. For Make-then-refresh setup, see Webhooks and Integrations. For generating a secret, URLs, and curl, see Webhook Technical Reference.

Short answer

If you need…
Use

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:

  1. Trigger: Webhook received — inbound. An external POST starts matching published workflows.

  2. Step: Notify → channel Webhook — outbound, fire-and-forget. The run POSTs to one or more URLs and continues without using the HTTP response.

  3. 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.

Surface
Label
Type

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:

  1. 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.

  2. Subscriber type: Webhook — outbound. When a message matches the subscription, NotionApps POSTs a messaging envelope to the destination URL.

Surface
Label

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

Surface
Product
Direction
Waits for response?
Starts
Updates open tab?

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_payload for that run.

Messaging inbound (POST /v1/webhooks/messaging-events or the app alias)

  • Requires a channel (and usually a topic).

  • 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 as cart_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

Call webhook and wait
Notify webhook
Messaging subscriber

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

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:

Workflow
Messaging

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 with channel/topic and 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 get message_id instead.

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

Need
Workflow inbound
Notify webhook
Call webhook and wait
Messaging inbound
Messaging subscriber

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

  1. 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.

  2. 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.

  3. 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.

  4. Messaging inbound, looking for runs_created. You will see message_id. If deliveries_created is 0, no subscriber matched — the workflow never ran.

  5. Workflow inbound body with only channel / topic. Workflow matching uses application/target/conditions, not Messaging routes.

  6. Assuming one kill switch. Workflow outbound off does not stop Messaging subscribers, and the reverse.

  7. Missing External API. Messaging webhook delivery needs Messaging External API. Workflow Notify / Call webhook and wait do not use that same gate.

  8. 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_key when 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.