---
title: "Automations"
description: "Draft a workflow and open the canvas."
canonical: https://docs.notifiable.sh/automations
source: https://docs.notifiable.sh/automations.md
---

# Automations

A developer, admin, or owner can create a workflow for the active environment. A viewer can read the list and open a workflow.

## How it works

New workflow opens `/workflows/editor/new`, stores a draft, and redirects to `/workflows/editor/{id}`. The name is `Untitled project #1`, then the next number after the highest `Untitled project #N` already stored for this app and environment. Opening the canvas shows the Notifiable mark and a spinner in the center for a few seconds, then the board. The board starts empty. The first step is a trigger, drawn a little larger than the steps after it. The trigger list shows each trigger a little larger, with a light glass surface and a short explanation. Search in that list focuses with Command-K. Click to run has a play button on the top edge of the step, in the same shape as the gear, and a label. Labels use sentence case. Schedule can repeat every few seconds or every few minutes, or every hour, every day, every week, or every month. Seconds are 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, or 60. Minutes are 1, 2, 3, 4, 5, 8, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, or 60. Every hour, day, week, and month use a time in UTC, plus the weekday or the day of the month. Event opens a menu of `started` and the event names recorded for this app and environment, including `notification_opened` and `notification_clicked`. One or more can be chosen. That choice is saved on the workflow. A published workflow starts when one of those events is recorded. Subscriber created starts when a subscriber is saved for the first time. The trigger item is that subscriber: id, name, email, tags, platform, and country. Tag added starts when a subscriber gains a tag, including a tag added by a workflow, or only the tag named on the trigger. That item is the same subscriber, plus the tag. Notification outcome starts when a notification is delivered, fails, is opened, or is clicked, for the outcomes chosen on the trigger. Stripe and RevenueCat start from a signed call to `/wh/provider/{id}/stripe` or `/wh/provider/{id}/revenuecat`. Stripe checks the `Stripe-Signature` header with the signing secret on the trigger. RevenueCat checks `Authorization: Bearer` against that secret. The secret stays on the workflow. A run and the canvas leave it blank. Stripe can be limited to Payment failed, Invoice paid, or Subscription cancelled. An empty list starts on any event for that workflow only. A draft or a workflow whose trigger is not that provider returns 204. An empty secret or a bad signature returns 401. The same body does not start a second run. Webhook received opens on Test URL and Production URL. Test is `https://wh.notifiable.sh/wh/test/{id}` and production is `https://wh.notifiable.sh/wh/prod/{id}`. Each address sits in a glass field with copy. The method opens as a menu of DELETE, GET, HEAD, PATCH, POST, and PUT. A sample body can be pasted so later steps can read that example. Invalid JSON is an error on that box. An empty sample does not mark a later path as broken; it asks for a sample. Authentication and when to respond can be set. Options can add allowed origins, a binary field name, ignore bots, an IP whitelist, no response body, raw body, a response code, response data, and response headers. There is no path field. Those choices are saved on the workflow. A call is accepted only for this workflow's environment. A draft returns 204 and does not run. A published workflow checks the saved method, basic or header authentication, and an IP whitelist when that option is on, then starts a run. The response uses the saved code and body. When the workflow waits for the last step, that wait is at most 15 seconds. A gear on the trigger opens its settings in a window. OpenAI, OpenRouter, Anthropic, and Google Gemini use that same gear. The window says AI Provider, then the provider name beside its logo. Each one opens a menu of this workspace's keys for that provider. A key shows its name and the first 8 characters of its value, then asterisks. A pen on a key opens its name and value for editing, and can delete it. Create API key, inside that menu, asks for a name and a value and adds another key. The step remembers which key was chosen, and that choice is saved on the workflow. A viewer can choose a saved key and sees the name, not the value. A developer, admin, or the owner can create a key. The same keys can be created from workspace settings, under Connections. OpenAI, Anthropic, and Google Gemini choose a model from a short list. OpenRouter chooses from its text models. Add system prompt opens that field, and it can be removed. Messages each have a type, a role, and a prompt, and another message can be added. Simplify output can be switched on. Temperature and max tokens stay hidden until they are added from options, and then they sit on one line. The keys stay on the workspace. The model, messages, and options are saved on the workflow. A published run calls that provider with the saved key and stores the reply as text. A button on the wire between two steps unlinks them. A step that is not linked onward shows a wire ending in a plus. The plus opens the step list, grouped as Conditions / Logic, Subscribers, Notifications, Events, Request, AI Providers, and Apps & Third Parties. Request offers HTTP request, Call webhook, Parse response, and Code step. Code step is JavaScript. A published run sends the HTTP request or webhook call, reads a path from the response, or runs that JavaScript in Node with the filesystem, child processes, and workers denied. Apps & Third Parties offers RevenueCat, Stripe, Discord, Slack, and Resend. A published run calls them with the saved credential. Stripe looks up the latest event. RevenueCat looks up a subscriber and asks for an app user id. Neither one starts the workflow. Subscribers can get every subscriber, the subscribers in one segment, or one subscriber. A published run loads them for this app and environment, and later steps can read that result. Every step opens a settings window from the gear. The window shows the step name and its short id. The name can be changed. A subscriber, segment, event, or notification can be chosen from the list, typed as a custom value, or read with an expression such as `{{node["n4k2"].subscriber_id}}`. The picker inserts the short id. A name works when only one earlier step uses it. A step can only read steps that reach it. Title, message, URL, property value, tag, HTTP URL and body, and a transform value can include the same expression in the text. A path that matches turns green, and hovering it shows one value. A broken path or a missing field turns red and names the fix. A missing sample stays amber. Menus are custom, including multi-select. Subscriber choices search this environment. Segment choices use this environment's segments. Cancel chooses a draft or scheduled notification. RevenueCat, Stripe, Discord, Slack, Resend, and HTTP authentication use a named workspace credential. Those choices are saved on the workflow. Conditions / Logic offers Filter, If / Else, Switch, Wait, Rate limit, Stop flow, Merge, Transform data, Loop, and For each subscriber. Add to segment and Remove from segment are not in the list. If / Else uses the same rules as Filter and continues on two wires, If and Else. Filter has one wire. A notification named Schedule is a later step, so a trigger can connect to it. Loop runs the next step once for each item, up to 25. The list can be the same expression the picker inserts, such as `{{node["n4k2"].body}}`. A loop or For each subscriber runs at most 10 items in one pass, then the same step continues on the next job. The repeated step cannot be a wait, a branch, a switch, or a merge. Switch compares a value with each road's label and continues on the matching road. Each road is a wire, and the road's label is drawn on that wire. Wait counts a duration in seconds, minutes, hours, or days, or waits until an event, an open, or a click. That wait has two wires, Resumed and Timeout. The timeout is at least 60 seconds. Rate limit counts in seconds, minutes, hours, or days, and it is per subscriber when the item has a subscriber id. For each subscriber runs the next step once per subscriber in this environment, or in one segment, up to a cap of 100. The next step reads that subscriber. People past the cap are counted as omitted. Each send in that loop is its own message. Loop does the same for a list, up to 25 items. The default cap is 25. The next step cannot be a wait, a branch, a switch, or a merge. A send can use the audience This subscriber so it goes to the subscriber on the item. Quiet hours on a send, written as `HH:MM`, skip that one subscriber when the local time is inside the window, including a window that crosses midnight. Stop flow has no step after it. Merge takes many steps in and continues as one step. Transform data turns a value into another form, such as text to a number or JSON to text. Notifications offers Send now, Schedule, Save draft, Send test, and Cancel, the same actions as composing a notification. A published run performs that action. Send test sends to one subscriber and only while the app is in development. Events offers Record event: a name, one subscriber, and optional properties. A published run records it, and that event does not start the same workflow again. The new step connects to that one. A webhook wire shows its method. The circle sits on the right edge of the step, filled gray, and turns white on hover. The wire leaves the center of that circle. The circle can be dragged onto another step. Hover an unlinked left side to show its dot. A trigger has no left dot. Choosing a step that has no settings opens its configuration under it. Hold Command or Control and drag a step to move it, or drag the empty board to move the canvas. Control-Z or Command-Z undoes the last change to the steps. Select a step and press Delete to remove it. Command-A or Control-A selects every step, and Delete removes the selection. A keyboard button at the bottom right opens a glass list of those shortcuts. Each key is its own glass key, using Command on a Mac and Ctrl elsewhere. The steps, their settings, and a rename from the canvas are saved on the workflow. A save that is no longer the latest copy is rejected, and the board asks for a refresh. The name is at most 80 characters. Refresh returns that board. An empty board offers Trial ending, Payment failed, Opened but not clicked, Inactive for a day, and Webhook in, then push. Choosing one fills the Ask AI field. Sending that field asks OpenRouter, with Notifiable's key, to build the whole workflow: the trigger, each push, each wait, and the follow-up. A trigger and one send is kept only when the request is only that. A step the product does not have is skipped and named. A filter or If / Else with no rule is skipped and named. Ask AI asks before it replaces a board that already has steps. A send in a journey about one person goes to that subscriber. The draft is not published, and it does not send until Execute or a later publish. A key saved in Connections is not used. When Notifiable has no OpenRouter key, Ask AI says it is unavailable. Publish copies the board into the published graph, records that graph's trigger type, and numbers that version. A later draft edit does not change the trigger type until the next publish. An event, a schedule, a new subscriber, a new tag, and a notification outcome look up published workflows of that trigger type. Editing the draft does not change the published graph or a run that is already going. The board says when the draft is newer than the published graph. Unpublish stops new runs and leaves the history. A workflow can name another workflow in this app and environment to start when a run fails. That run carries the failed step and the error, and it does not start a further workflow if it fails too. A draft does not start on its own. Execute tests the draft on the board, saves that draft, and does not publish it. The play mark on Click to run does the same. That run is stored as a test. A schedule, event, webhook, new subscriber, new tag, notification outcome, or signed Stripe or RevenueCat webhook still uses the published graph. The board shows the run while it is going: a step that succeeded has a green outline, the step in progress has a light yellow outline with a soft shadow, and the step that failed has a light red outline with that same shadow. The shadow eases in and out. The run is failed, and later steps stay unmarked. Clicking a step shows the items that arrived and the response that step returned. Run this step runs the selected step on a pinned sample, including a draft, and does not continue. Continue from here starts at that step on the open run, including a draft, using the graph stored with that run. A step can stop the run when it fails, or retry up to three times and then stop. The wait between tries is 5 seconds, then 30, then 120. Executions opens a sheet on the right. Each run shows Draft or its published version, the trigger, the status, and the steps that ran as a stacked row. Choosing a run shows each step, the error, the items it received, and the response it returned. The board stays visible and marks the step. A schedule that failed on one tick days later is still in that history.

A published run walks the graph copied at publish time. The trigger item is the event, the webhook body, or the manual payload, and later steps read that list. The trigger is recorded, then each following step runs in that same pass until a wait. If / Else takes the matching wire. A filter or If / Else with no rules does not match, so the filter stops and If / Else takes the Else wire. Filter with no match ends that path. A duration wait is saved, with the cursor already on the next step, before the later job can run. A run that is still going and has no job is queued again. A step whose type is not one of these fails the run. A wait until an event, an open, or a click stays waiting until that fact arrives for the same subscriber, or until the timeout wire runs. A merge that cannot receive every incoming path that started fails the run. When it is set to the first path, the first arrival continues and a later arrival ends. A step on a wait's Timeout wire is a child of that wait, so a later step can read it. Stop ends the run. A step that fails marks the run failed, stores the message on that step, and does not continue, unless that step is set to retry. Each step keeps the items it received and the response it returned. It does not fail the event or webhook that started the run. Add to segment and Remove from segment fail the run, because a segment is a set of rules. A second or minute schedule starts one run for each matching UTC bucket. Locally, `composer run dev` runs that check and the queue that sends the steps. Hour, day, week, and month start one run in the matching UTC minute. A matching event, a new subscriber, a new tag, a notification outcome, a Stripe or RevenueCat webhook, and a workflow webhook each start a run. Execute starts one too.

The list uses the same table as the other app pages. Columns are the workflow, status, runs, and the created time. Draft stays light gray. Published is green. Runs shows never run until a run finishes, then how many finished runs there are: 1 time, or 3 times. When any of those runs failed, a red badge after that count shows the percentage, such as 20% failed. A row opens that workflow. The row menu can rename it, duplicate it as another draft with the same steps, or delete it. Duplicate stops at the workspace workflow cap. A viewer does not see New workflow or the row menu.

Creating stops at the workspace workflow cap. Free allows 3, Starter allows 10, and Pro is unlimited. The usage page counts stored workflows, including one badge per app.

An automation saved earlier still sends when its event is recorded and the subscriber is in its segment. The automations page lists those automations and can pause or resume them. It no longer creates that kind of automation. A paused automation does not send.
