> For the complete documentation index, see [llms.txt](https://docs.notionapps.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.notionapps.com/automation/advanced-reference/trigger-catalog.md).

# Trigger catalog

Canonical list of Workflow Foundation triggers. How-tos stay short and link here. Screen guides do not copy this table.

In the builder, a trigger is three fields on the **Build** bar:

1. **Trigger** — what kind of event can start a run.
2. **Where it happens** — how wide that event is allowed to be (entire app, one screen, one button, one data source, and so on).
3. **Target** — the exact screen, button, sheet, or record. Entire-app workflows leave Target blank.

Use the narrowest trigger that matches the real event. Prefer **Form or screen submitted** over **Record updated** when the app form is the source of truth — edits made only in Notion do not look like a form submit.

## What this is / when to use it

A trigger starts a workflow run. Type enum: `WorkflowTriggerType`. You attach it to a form, button, screen, data source, record, or the application (`WorkflowAttachmentTargetType`).

## Before you start

Workflow entitlement is on. The target form, button, or sheet exists. You have read [Which automation](https://docs.notionapps.com/automation/which-automation).

## Build it

1. Open **Automation → Workflows** (or the wizard, which picks a trigger for you).
2. Set **Trigger** to one type below.
3. Set **Where it happens**, then bind **Target** when the scope is not Entire app.
4. Add conditions if the run should skip some events.
5. Add steps from the [step catalog](https://docs.notionapps.com/automation/advanced-reference/step-catalog).
6. Save, publish the workflow, and publish the app.

## Every control

| Trigger                  | Enum               | Typical Where it happens | Typical Target                                | Fires when                                                     | Do not use when                                                                                            |
| ------------------------ | ------------------ | ------------------------ | --------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Form or screen submitted | `form_submitted`   | Screen                   | The screen that owns the form                 | A create/update/delete save on that screen succeeds            | You need Notion-only edits                                                                                 |
| Button or screen action  | `button_clicked`   | Button                   | The specific button                           | The user taps that control                                     | You meant a URL button (`OPEN_URL`) that is not bound here                                                 |
| Manual start             | `manual_start`     | Entire app               | Leave blank                                   | Someone starts it from Launcher, Test workflow, or Simulate    | Unattended intake from a form or webhook                                                                   |
| Record created           | `record_created`   | Data source              | The connected sheet/database                  | A new page appears in that source                              | You only care about the app form                                                                           |
| Record updated           | `record_updated`   | Data source              | The connected sheet/database                  | A watched page in that source changes                          | High-churn properties (you will over-fire)                                                                 |
| Status changed           | `status_changed`   | Data source              | The sheet that owns the status field          | Status/select moves (optionally to a named value)              | You need any field change — use Record updated                                                             |
| Scheduled                | `scheduled`        | Entire app               | Leave blank                                   | The schedule fires                                             | Immediate reaction to a submit                                                                             |
| Webhook received         | `webhook_received` | Entire app               | Leave blank                                   | HTTP intake is accepted                                        | You do not have a sender. See [webhooks](https://docs.notionapps.com/automation/webhooks-and-integrations) |
| Message received         | `message_received` | Entire app               | Leave blank unless you are scoping a contract | An inbound message matches channel/topic (and contract if set) | You do not have Messaging entitlement                                                                      |

Shared trigger fields: `target_type` (Where it happens), `target_id` (Target), `conditions`, `config` (for example **To status**, schedule, webhook intake).

***

## Each trigger, Where it happens, and Target

The labels below are the ones on **Build**. Hidden/internal screens can appear in Target because workflows can send people there on purpose.

### Form or screen submitted

**Trigger:** Form or screen submitted (`form_submitted`)

This is the usual trigger when a person in the published app fills a create or update form and saves. It fires **inside the app**, after that save succeeds. It does **not** fire when someone edits the same Notion database in Notion and never opens your app.

**Where it happens**

* **Screen** — use this almost always. The workflow listens only to form saves on one screen.
* **Entire app** — any form save in this app can start the run. Use this only when you truly want every form.
* **Form** — reserved for a form-specific id. Today’s app form saves are matched through the **screen** that owns the form, so choose Screen instead.

**Target**

Search for the screen that contains the form (for example `Client Intake` or `Assign Job`). The builder saves the screen id. Do not pick a different list or details screen that happens to use the same database.

**Example:** Client submits intake → Where it happens = Screen → Target = `Client Intake`.

**Do not use** if the work should start when a row is created in Notion by a person or another integration. Use **Record created** for that.

### Button or screen action

**Trigger:** Button or screen action (`button_clicked`)

This fires when an end user clicks a **workflow-aware** button or completes a screen action the builder attached to the workflow. A normal Open URL button does **not** start a run unless you bind this trigger to that control.

**Where it happens**

* **Button** — use this when only one control should start the workflow (Approve, Reject, Mark reviewed).
* **Screen** — use this when several buttons or screen actions on the same screen should share one workflow. Button-click events include the current screen id, so a screen-scoped workflow can see them.

**Target**

* If Where it happens is **Button**, search by the button label (and the screen it lives on). The builder saves the control id.
* If Where it happens is **Screen**, search for that screen. Every matching action on that screen can start the run.

**Example:** Reviewer clicks `Mark reviewed` → Where it happens = Button → Target = `Mark reviewed` on the review screen.

**Do not use** for “when they submit the form.” That is **Form or screen submitted**.

### Manual start

**Trigger:** Manual start (`manual_start`)

This does not watch the app. A person or a controlled test starts it on purpose: Automation Launcher **Target workflow**, **Test workflow** on Activity, or Simulate.

**Where it happens**

**Entire app.** There is no form or sheet to listen to.

**Target**

Leave Target blank. Entire-app workflows do not need a target. Publishing a scoped target here does not make the workflow start from a form.

**Do not use** for unattended intake (form, Notion row, webhook). Those need a real event trigger.

### Record created

**Trigger:** Record created (`record_created`)

This fires when a **new page** appears in a connected Notion source (app sheet / database), whether it was created in the app or in Notion, depending on what that source is watching.

**Where it happens**

**Data source** — listen to one connected sheet or database. Entire app is too wide for most production apps.

**Target**

Search by the data source name (the connected Notion database or sheet). The builder saves the source id. Pick the database that receives the new row, not a related child database unless that is truly what should start the run.

**Example:** A new Job page appears in `Jobs` → Where it happens = Data source → Target = `Jobs`.

**Do not use** if you only care that someone submitted **your** form. Two workflows (form submitted + record created) on the same write will double-run.

### Record updated

**Trigger:** Record updated (`record_updated`)

This fires when a watched page in the connected source changes — any property Notion reports as an update, from the app or from Notion.

**Where it happens**

**Data source** — one sheet/database.

**Target**

The same data source picker as Record created. Choose the database whose edits should start work.

**Warning:** If a later step writes the same sheet, this trigger can loop. Add a condition, or use **Status changed** so only one field matters.

**Do not use** for high-churn properties (last edited, counters, sync timestamps). You will over-fire.

### Status changed

**Trigger:** Status changed (`status_changed`)

This is a narrower record trigger. It fires when a status or select field **moves**, not when every property on the page changes.

**Where it happens**

**Data source** — the sheet that owns that status field.

**Target**

Pick that data source. Then fill **To status** when you only want one destination value (for example `With Client` or `Approved`). Leave **To status** blank only if any status move should run the workflow.

**Example:** Job status becomes `Assigned` → Where it happens = Data source → Target = `Jobs` → To status = `Assigned`.

**Do not use** if you need “any field on the row changed.” That is **Record updated**.

### Scheduled

**Trigger:** Scheduled (`scheduled`)

This starts from a clock (cron or interval), not from a user click. There is no form submit and no Notion event.

**Where it happens**

**Entire app.** The schedule belongs to the workflow, not to a screen.

**Target**

Leave blank.

**Do not use** when the next step should happen the moment someone submits. Use Form or screen submitted (and a **Wait** step if you need a delay after that submit).

Scheduled workflows need the matching entitlement. They are for reminders, nightly sweeps, and overdue checks.

### Webhook received

**Trigger:** Webhook received (`webhook_received`)

This starts when an external service **POSTs JSON** to this app’s workflow intake and the request is accepted. Generate a secret in **External webhook intake** and send it as `x-notionapps-webhook-token` (Bearer and `x-workflow-webhook-token` also work).

**Where it happens**

**Entire app.** Intake is per app, not per screen.

**Target**

Leave blank. The sender is Make, Zapier, or another HTTP client, not a builder picker object.

Copy the intake URL and token from the builder. After this app has an active secret, the old shared platform token stops working for it. Admins can inspect attempts in **Admin → Workflow Operations → Webhooks → Inbound**.

**Do not use** if you only need to send email. Use a **Notify** step on a form or button trigger.

Details: [Webhook Technical Reference](https://docs.notionapps.com/automation/webhooks-and-integrations/webhook-technical-reference), [Workflow vs Messaging Webhooks](https://docs.notionapps.com/automation/webhooks-and-integrations/workflow-vs-messaging-webhooks).

### Message received

**Trigger:** Message received (`message_received`)

This starts when Application Messaging routes a matching **channel**, **topic**, and optional **contract** into the workflow. External systems can POST JSON to the **messaging** intake URL with the same per-app token. This is not SMS and not the Notify email step.

**Where it happens**

Usually **Entire app**. The match is the messaging route, not a form screen.

**Target**

Leave blank unless you are deliberately scoping to a contract or related object the picker exposes. Messaging entitlement must be on.

**Do not use** if the event is “user submitted a form in this app.” Use Form or screen submitted, then a **Publish message** step if you also need the bus.

Topic names: [Topics that perform work](https://docs.notionapps.com/automation/topics-that-perform-work).

***

## What users see

Nothing at the trigger. They see later steps: a notification, a queue item, a status change, or a confirmation on the screen.

## Limits and plans

* Scheduled and webhook need entitlements and, for webhook, an external token. Makers copy the intake URL from the workflow builder; they do not handle ops env files.
* `record_updated` can loop if a step writes the same sheet. Add a condition or use `status_changed`.
* Simulate / test runs are for makers. They still create runtime items unless the tool says otherwise.

## Example

Inspection Assign Job form → `form_submitted` → Where it happens = Screen → Target = Assign Job screen → `create_related_records` photo slots → `send_notification` to the inspector. Do not also use `record_updated` on the same form’s writes.

## Fix problems

| Symptom                     | Likely cause                                              | What to do                                                                                                         |
| --------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Submit does not start a run | Trigger bound to the wrong screen, or draft not published | Confirm Where it happens = Screen and Target is the form screen. Publish workflow and app.                         |
| Button does nothing         | URL button, or Target is a different control              | Bind **Button or screen action** to that control. Open URL alone does not start a run.                             |
| Double runs                 | Two triggers on the same save                             | Remove form submitted **or** record created/updated, not both.                                                     |
| Webhook 401                 | Token / URL mix-up                                        | [Webhook reference](https://docs.notionapps.com/automation/webhooks-and-integrations/webhook-technical-reference). |

## Related

[Step catalog](https://docs.notionapps.com/automation/advanced-reference/step-catalog). [Start From a Wizard](https://docs.notionapps.com/automation/start-from-a-wizard). [Workflow Foundation User Guide](https://docs.notionapps.com/automation/workflow-foundation-user-guide). [Workflow How-To Guide](https://docs.notionapps.com/automation/notionapps-workflow-how-to-guide).
