# Branch Workflows Source: https://learn.workflow.dog/building/branching Choose values, route execution, and combine conditions without hiding control flow. Branching in WorkflowDog is data-driven. Conditions produce Boolean values, and control actions either choose a value or emit data along one path. ## Choose a value or choose a path The two basic patterns look similar on the canvas but behave differently: [Choose Value](/reference/actions/control/mux) receives **If True**, **If False**, and a **Boolean Condition**, then emits exactly one value through **Result**. Both candidate inputs are dependencies of the action. Use this when the upstream values are already available and only the selected result matters downstream. [Route Value](/reference/actions/control/demux) receives one **Value** and a **Boolean Condition**. It emits the value from either **If True** or **If False**. The other output emits no signal. A downstream node connected only to the unselected output is not attempted. Use this when different actions should run on different branches. For a value choice, connect approved text, rejected text, and the condition to **Choose Value**, then send its single **Result** to the message action. For an execution choice, connect the record and condition to **Route Value**; use **If True** to create the approved record and **If False** to request review. If both branches ultimately feed the same action, choose a value first and connect one result. If the branches perform different work, route the value. ## Build conditions Logic actions turn comparisons and checks into Boolean values: | Need | Action | Behavior | | ---------------------- | ------------------------------------------------- | -------------------------------------------------------------- | | Values are identical | [Equal](/reference/actions/logic/equal) | Uses strict equality; values of different types are not equal. | | Values differ | [Not Equal](/reference/actions/logic/not-equal) | Uses strict inequality. | | Every condition passes | [And](/reference/actions/logic/and) | Returns true only when every input is truthy. | | At least one passes | [Or](/reference/actions/logic/or) | Returns true when any input is truthy. | | Reverse a condition | [Not](/reference/actions/logic/not) | Negates the input's truthiness. | | Inspect truthiness | [Is Truthy](/reference/actions/control/is-truthy) | Converts truthiness to an explicit Boolean. | | Inspect falsiness | [Is Falsy](/reference/actions/control/is-falsy) | Returns true for a falsy value. | Strict equality makes type conversions important. The number `1` and the string `"1"` are different values. Convert first when data from an external system represents numbers or booleans as text. ## Route by case [Choose Value by Case](/reference/actions/control/mux-case) maps text keys to values. It is useful for statuses, categories, event types, or any branch with more than two outcomes. Connect the text to compare, such as `priority` or `event_type`. Add one key and value for each recognized case. Provide **Default** for everything not listed. Without a default, an unmatched case returns `null`. Connect **Result** to the common downstream action. Case keys are exact and case-sensitive. `"High"` and `"high"` are separate cases. Choose Value by Case selects data; it does not create multiple execution outputs. To run different actions, compare the case and use [Route Value](/reference/actions/control/demux), or add a **Conditional** meta control to each branch. ## Supply fallback values [Fallback](/reference/actions/control/coalesce) evaluates candidates in their configured order and returns the first one that qualifies: * **Non-Null** skips `null` values but keeps other values, including `false`, `0`, and an empty string. * **Truthy** skips every falsy value. Use **Non-Null** for optional fields where `false` or `0` is meaningful. Use **Truthy** only when those values should also fall through. ## Gate one action When a separate branch node would add noise, enable the **Conditional** meta control on the action. Connect a Boolean condition to the new **Condition** input. The action runs only when the value is truthy. This is particularly useful for optional side effects: For example, save every order but connect **amount exceeds review threshold** to the **Condition** input on **Notify reviewer**. The notification becomes an optional side effect without affecting the save path. If the condition is false, the action is not attempted and its ordinary outputs emit no signal. Downstream nodes that depend on those outputs will also be skipped unless another path supplies their inputs. See [Meta Controls](/building/meta-controls) for status outputs that report whether a gated action was attempted or succeeded. ## Avoid ambiguous branches * Name the condition in a nearby [Comment](/reference/actions/core/comment), especially when `true` and `false` are not self-explanatory. * Normalize text before exact comparisons when capitalization or whitespace comes from users. * Prefer one clear multi-case mapping over a long chain of nested binary choices. * Preserve `false` and `0` with a non-null fallback when they are valid business values. * Test both selected and unselected paths. A skipped node is different from a node that ran and returned `null`. # Connect Data Source: https://learn.workflow.dog/building/connect-data Pass values between actions, configure fixed inputs, and expose the exact outputs you need. Every connection in a workflow carries a value from an output on one node to an input on another. The connection also creates an execution dependency: the receiving action waits for the connected output before it runs. ## Static and dynamic inputs Most inputs can receive their value in one of two ways: Enter a fixed value directly in the node's configuration. The same value is used on every run. Static inputs are a good fit for constants such as a model name, status, email subject, or other fixed configuration. Connect an output from another node. The input receives the value produced during the current run. Dynamic inputs are required when a value comes from trigger data, an API response, a calculation, or any other action. For an input that supports both modes, use **Configure dynamically** to switch between them. Starting a connection to the input switches it to dynamic mode automatically. Switching a connected input back to static configuration removes the connection to that input. Confirm the fixed value before changing modes. Some settings are configuration-only and cannot be connected. They define the shape or behavior of the node itself rather than data for a run. ## Match data types Handles indicate the kind of value they accept, such as String, Number, Boolean, List, Object, File, or a package-specific type. Connect compatible types whenever possible. An **Any** handle accepts any value, but the receiving action still decides what values are meaningful. For example, [Parse JSON](/reference/actions/core/json-parse) accepts a String containing JSON; connecting an arbitrary value does not make it valid JSON. Use conversion actions when the types differ: * [To Number](/reference/actions/core/to-number) converts compatible values to a number. * [To Boolean](/reference/actions/core/to-boolean) converts a value using boolean semantics. * [Convert to JSON](/reference/actions/core/json-stringify) serializes a value as JSON text. * [Parse JSON](/reference/actions/core/json-parse) turns JSON text back into a structured value. Preserve a value's native type for as long as possible. Convert objects or lists to text only when the next system actually requires text. ## Select part of an object Object-producing actions can expose the whole object and selected properties. When the node shows **Select Property**, add only the properties downstream actions need. Each selected property becomes its own output handle. You can also select a nested property from a completed run: A real output gives the editor the object's current shape. Choose the property path from the run result. The editor exposes that path as a connectable output. For outputs that do not support property handles directly, it can route the value through [Get Properties](/reference/actions/objects/get-properties). Property selection keeps the rest of the workflow readable and avoids passing a large object into an action that needs only one field. A property can be absent in a later run even if it appeared in the run you inspected. Validate optional or external data before relying on it. ## Repeatable inputs Some nodes accept a variable number of values. Examples include items in [Create List](/reference/actions/arrays/build), values in [Fallback](/reference/actions/control/coalesce), and properties in [Create Object](/reference/actions/objects/build). Repeatable inputs support two common layouts: * **Individual items** — Add, remove, and reorder entries, then configure or connect each one separately. * **Entire list at once** — Connect one List whose items become the repeatable input. Use individual items when the workflow has a small, known set of sources. Use an entire list when the number of values comes from runtime data. For key/value inputs, each repeatable row contributes a property to an object. Keys should be unique; a later duplicate key replaces the earlier property when the object is assembled. ## Repeatable outputs Some actions can expose either a complete collection or selected entries. In individual mode, each configured output corresponds to one position or property in the result. In whole-list mode, one output carries the collection. Choose based on what happens next: * Connect the whole list to actions such as [Loop Workflow](/reference/actions/core/loop-workflow), [Join Lists](/reference/actions/arrays/join), or [Filter With Workflow](/reference/actions/arrays/filter-with-workflow). * Select individual items when later branches need separate values. For position-based access, [Get Items by Index](/reference/actions/arrays/get-items) makes the intended indexes explicit. ## Design reliable connections Treat a node's outputs as a small contract with its downstream consumers: 1. Connect the narrowest useful value. 2. Keep structured values structured. 3. Convert types at a clear boundary. 4. Account for `null`, missing properties, and empty lists. 5. Run the workflow once and inspect the actual output before building a long downstream chain. For data that may be missing, [Fallback](/reference/actions/control/coalesce) can choose the first non-null or truthy candidate. For a hard requirement, [Throw Error](/reference/actions/core/throw-error) can stop the run with a clear message. # Files and Structured Data Source: https://learn.workflow.dog/building/files-and-structured-data Move between files, text, objects, JSON, YAML, and data URLs without losing the intended format. WorkflowDog treats files, strings, and structured values as different data types. Keep them distinct until a system boundary requires a conversion. ## Know what you have | Value | Contains | Typical use | | ------------------ | ----------------------------------------------------- | ---------------------------------------------------- | | **File** | A name, MIME type, encoding, and base64-encoded bytes | Uploads, attachments, downloads, images, PDFs | | **String** | Text | Prompts, messages, CSV text, JSON text, HTML | | **Object or List** | Structured workflow data | API payloads, records, branching, property selection | | **Data URL** | A string containing a MIME type and base64 data | Embedded browser or API content | Changing a filename does not convert bytes, and serializing an object does not create a File. Use an explicit conversion action so the boundary is visible on the canvas. ## Create and download files Use [Create Text File](/reference/actions/files/create-text-file) when the content already exists as a String. Supply the complete filename, including an extension. To deliver structured data as a file, convert the value to JSON, create `report.json` from that text, then upload, attach, or return the resulting File. The filename extension is used to infer the MIME type when recognized. Use [Download File from URL](/reference/actions/files/download-from-url) to retrieve a public resource. You can provide a filename or let the action derive one from the URL path. It uses the response's content type when available and fails for non-success responses. Download File from URL blocks local, internal, and private network addresses. It is for public resources, not for reaching services inside a private network. ## Rename without converting [Rename File](/reference/actions/files/rename) returns a copy with a new name while preserving its bytes and MIME type. Renaming `invoice.png` to `invoice.jpg` still leaves PNG image data inside the file and preserves the original MIME type. Use a format-specific conversion action when the content itself must change. ## Convert files to and from data URLs [Convert File to Data URL](/reference/actions/files/file-to-data-url) creates a String in this form: ```text theme={null} data:image/png;base64,iVBORw0KGgo... ``` This is useful when HTML or an API requires embedded content. Base64 increases the representation's size, so prefer a File when the receiving action accepts one. [Convert Data URL to File](/reference/actions/files/data-url-to-file) performs the reverse operation. Its input must use the exact `data:MIME_TYPE;base64,DATA` form. The output is named `converted.EXTENSION`, with the extension derived from the MIME type. A normal `https://` URL is not a data URL. Download it with **Download File from URL** instead. ## Parse JSON text [Parse JSON](/reference/actions/core/json-parse) converts a valid JSON String into its native value: an Object, List, String, Number, Boolean, or `null`. ```json theme={null} { "customer": { "id": "cus_123", "active": true }, "tags": ["new", "priority"] } ``` After parsing, select the properties downstream actions need. See [Connect Data](/building/connect-data#select-part-of-an-object) for property outputs. Malformed JSON causes the action to fail. JSON requires double-quoted strings and does not allow comments or trailing commas. ## Serialize values as JSON or YAML [Convert to JSON](/reference/actions/core/json-stringify) serializes a workflow value as JSON text. Enable pretty formatting for human-readable output; compact output is usually better for API requests or storage. [Convert to YAML](/reference/actions/core/yaml-stringify) emits YAML using two-space indentation. Its **Use references?** option represents repeated objects with YAML anchors and aliases. Leave references off when every section should be standalone and easy to copy. Serialization is useful at an external boundary: For example, build an Object, convert it to JSON, then create `payload.json` from the serialized text. Do not serialize only to parse the value again in the next node. Connect the original Object or List directly and preserve its types. ## Validate structured data [Validate JSON Schema](/reference/actions/utilities/validate-json-schema) checks any value against a JSON Schema and returns: * **Is Valid**, a Boolean; * **Errors**, a list containing every validation error found; and * the original validated value or top-level property outputs, depending on the schema. For an object schema, the node exposes properties declared under the schema's top-level `properties`. Connect **Is Valid** to [Route Value](/reference/actions/control/demux) or a **Conditional** meta control before using those values. One safe pattern is: 1. Parse the JSON text. 2. Validate the parsed value against the schema. 3. Connect both the validated object and **Is Valid** to **Route Value**. 4. Continue processing from **If True**. 5. Use **If False** to record the validator's **Errors**. Validation does not coerce types. The String `"18"` does not satisfy an `integer` schema. It also does not strip extra properties, and property outputs remain the supplied values even when validation fails. An ordinary schema mismatch returns **Is Valid: false**. Malformed JSON or an invalid schema fails the action itself. Handle those as separate failure cases. ## Choose the right conversion Use **Convert to JSON**. If the API action accepts a structured body directly, connect the Object instead. Use **Parse JSON**, then select properties from the resulting value. Use **Create Text File** and give it the correct filename extension. Use **Download File from URL**. Use **Convert File to Data URL**. # Work With Lists and Loops Source: https://learn.workflow.dog/building/lists-and-loops Build, transform, inspect, and process collections without losing order or type information. A List is an ordered collection of values. Lists can contain text, numbers, objects, files, or mixed values, and they can be passed between actions as one value. ## Create a list Choose the source that matches how the collection is produced: | Source | Use it when | | ----------------------------------------------- | ---------------------------------------------------------------------- | | [Create List](/reference/actions/arrays/build) | You have a known set of individual values. | | [Create Range](/reference/actions/arrays/range) | You need a numeric sequence. | | [Append](/reference/actions/arrays/append) | You need to add one value to an existing list. | | [Join Lists](/reference/actions/arrays/join) | You need to concatenate multiple lists. | | An integration action | An API already returns records, messages, rows, or another collection. | On repeatable list inputs, add and reorder individual items or switch to providing an entire List at once. Individual inputs are best for a fixed set; the whole-list input is best for runtime collections. ## Inspect and reshape lists List actions transform a collection without requiring a sub-workflow: * [Get Items by Index](/reference/actions/arrays/get-items) exposes selected positions as separate outputs. Index `0` is the first item, and `-1` is the last. * [Slice](/reference/actions/arrays/slice) returns a contiguous section. * [Chunk](/reference/actions/arrays/chunk) splits a list into smaller lists. * [Flatten](/reference/actions/arrays/flatten) removes nested list levels. * [Unique](/reference/actions/arrays/unique) removes repeated values. * [Sort](/reference/actions/arrays/sort) reorders the items. * [Length](/reference/actions/arrays/length) returns the item count. Use these focused actions before reaching for a loop. They make the workflow easier to read and avoid starting a child workflow for work a single action can perform. ## Process every item [Loop Workflow](/reference/actions/core/loop-workflow) runs a callable workflow once for each item in **Payloads**. Give the child workflow the [Sub-Workflow trigger](/reference/triggers/core/callable). Read the current item with [Data from Trigger](/reference/actions/core/trigger-data). Connect the transformed value to [Return Data](/reference/actions/core/return-data). In the parent workflow, select the child in **Loop Workflow** and connect the source list to **Payloads**. **Results** contains one child result for each input item, in the same order. Iterations run sequentially. This preserves ordering and avoids overlapping child runs, but the total runtime grows with both the number of items and the duration of each child workflow. A child that finishes without **Return Data** contributes `null` at its position. If a child run fails, the loop action fails instead of returning a partial results list. Loop Workflow accepts up to 1,000 payloads. Split larger collections into batches before invoking it. ## Filter with a predicate workflow [Filter With Workflow](/reference/actions/arrays/filter-with-workflow) runs a callable workflow for each item and keeps the original items whose returned value is truthy. The predicate workflow should: 1. Read the item from **Data In**. 2. Compare or validate it. 3. Return the decision through **Return Data**. The output keeps matching items in their original order. The returned decision does not need to be a Boolean, but an explicit Boolean makes the predicate's intent clearer. For example, filter a list of orders with a **Needs review?** predicate, then send the matching orders to a **Create review task** loop workflow. Like Loop Workflow, filtering is sequential, accepts at most 1,000 payloads, and fails if any child run fails. ## Find the first match [Find With Workflow](/reference/actions/arrays/find-with-workflow) tests items from the beginning and returns the first original item whose predicate result is truthy. It stops testing after a match and returns `null` when none match. Use it instead of filtering when: * only one item is needed; * list order defines priority; or * avoiding unnecessary child runs matters. ## Preserve the difference between an item and a result The three workflow-backed list actions return different things: | Action | Output | | ------------------------ | ----------------------------------------------------- | | **Loop Workflow** | The value returned by the child for every item. | | **Filter With Workflow** | The original items whose child result is truthy. | | **Find With Workflow** | The first original item whose child result is truthy. | If you need both an original item and derived fields, have the loop child return an object containing both. [Create Object](/reference/actions/objects/build) can assemble a predictable result such as: ```json theme={null} { "source": { "id": "order_123", "total": 249 }, "requires_review": true, "reason": "Order total exceeds threshold" } ``` ## Choose a list strategy Use a dedicated Arrays action. It runs in the current workflow and communicates the operation directly. Use **Loop Workflow** and put the per-item sequence in a callable child workflow. Use **Filter With Workflow** with a predicate child workflow. Use **Find With Workflow**. Put the highest-priority candidates first. External side effects completed by earlier iterations are not rolled back if a later child fails. Design loop children so they can be retried safely when they create records, send messages, or modify remote state. # Use Meta Controls Source: https://learn.workflow.dog/building/meta-controls Gate, order, observe, and debug any action without changing its core behavior. Meta Controls add execution inputs and diagnostic outputs to an action. Select one node and open **Meta Controls** from its selection toolbar or configuration panel. They are available independently of the action's package, so the same control patterns work across integrations and built-in actions. ## Available controls | Meta Control | Adds | Behavior | | ----------------------- | ---------------------------- | -------------------------------------------------------- | | **Conditional** | **Condition** input | Runs the action only when the connected value is truthy. | | **Wait For** | **Wait For** input | Delays the action until the connected output emits. | | **Did Action Attempt?** | **Attempted?** output | Reports whether the action itself was invoked. | | **Did Action Succeed?** | **Succeeded?** output | Reports whether it ran without an error. | | **Error** | **Error** output | Exposes the action's error message when it fails. | | **Outputs As Object** | **Outputs As Object** output | Collects all ordinary action outputs into one object. | Turning off a control removes its handle and any connection attached to that handle. ## Run an action conditionally Enable **Conditional** and connect a condition to **Condition**. For example, connect an **Is order total greater than 500?** result to the **Condition** input on **Notify reviewer**. When the condition is falsy, the action is not attempted. Its ordinary outputs emit no signal, so nodes that depend on them do not run. This differs from an action that runs successfully and returns `null`: a `null` result is still a value, while a skipped action produces no ordinary output signal. Use [Route Value](/reference/actions/control/demux) instead when both the true and false paths should perform visible work. See [Branch Workflows](/building/branching) for the choice between gating and routing. ## Add an ordering dependency Connections normally carry both data and execution order. Sometimes one action must wait for another even though it does not need the earlier action's value. Enable **Wait For** and connect any output from the prerequisite: In a customer-onboarding workflow, connect an output from **Create customer** to **Wait For** on **Send welcome email**. Connect the email address separately to the send action's **To** input. The connected output's value is not passed into the action's ordinary inputs. It only establishes that the output must emit first. Wait For requires an emitted value. If the upstream node is disabled, skipped, fails, or takes an unselected routing path, the waiting action is not attempted. ## Observe whether an action ran **Attempted?** and **Succeeded?** answer different questions: | Outcome | Attempted? | Succeeded? | | ------------------------------------------------------------------------ | ---------- | ---------- | | Action completed successfully | `true` | `true` | | Action ran and threw an error | `true` | `false` | | Action was disabled, skipped by a condition, or lacked a required signal | `false` | `false` | These status outputs are useful for reporting and cleanup paths that must distinguish “did not run” from “ran and failed.” Because meta-control outputs are settled even when ordinary outputs are not, they can drive downstream diagnostics after a failure or skip. ## Capture an error message Enable **Error** to expose the formatted error from the action: * a failed action emits its error message; * a successful attempted action emits `null`; and * an action that was not attempted emits no error value. Pair it with the status outputs when the distinction matters: Connect **Attempted?**, **Succeeded?**, and **Error** to **Create Object**, then send that object to the action that records the result. This keeps the three diagnostic values together without hiding which signal each field represents. Exposing **Error** does not turn a failed action into a successful one or retry it. It makes failure data available for diagnostic paths. ## Collect outputs for inspection **Outputs As Object** bundles the action's ordinary returned outputs into one Object. It is primarily useful for: * inspecting a node with many outputs; * passing a complete result into a log or sub-workflow; or * capturing a snapshot while debugging. On success, the object contains the outputs returned by the action. When the action does not produce results, it emits `null`. Prefer named output handles for long-lived production connections. They make dependencies explicit and avoid coupling downstream nodes to every field the action returns. ## Disable nodes temporarily Disabling is a selection action rather than a Meta Control, but it participates in the same execution semantics. Select one or more nodes and choose **Disable**; choose **Enable** to restore them. Disabled nodes are not attempted, and their ordinary outputs emit no signal. On macOS, the shortcut is `⌘ ⇧ E`. Use disabling to isolate part of a workflow during development. Before shipping, check every downstream dependency: disabling a producer can skip more than the selected node. ## Debug a branch deliberately For an action whose execution is unclear, temporarily enable: 1. **Did Action Attempt?** 2. **Did Action Succeed?** 3. **Error** 4. **Outputs As Object** Run representative true, false, successful, and failing cases. The four outputs reveal whether the action was eligible, whether it completed, why it failed, and what it returned. Remove diagnostic controls you no longer need so the production graph keeps a clear contract. # Organize the Canvas Source: https://learn.workflow.dog/building/organizing-the-canvas Select, arrange, label, highlight, and pin nodes as workflows grow. A readable canvas makes execution order, data ownership, and failure paths visible. WorkflowDog provides selection tools, automatic layout, comments, highlights, and pinned actions for keeping large workflows navigable. ## Select the nodes you mean to change | Action | Result | | ------------------------------------ | ------------------------------------------------ | | Click a node | Selects that node. | | Shift-click a node | Adds it to or removes it from the selection. | | Hold Option and drag on empty canvas | Selects nodes whose centers fall inside the box. | | `⌘ A` | Selects every node. | | `⇧ ←` | Adds the selected nodes' direct incomers. | | `⇧ →` | Adds the selected nodes' direct outgoers. | | Click empty canvas | Clears the selection. | Dragging one selected node moves the whole selection. Once selected, the floating toolbar provides layout, alignment, highlight, duplicate, copy, cut, disable, extraction, and deletion actions. Keyboard shortcuts above use macOS symbols. The corresponding modifier keys may differ on another operating system. ## Lay out a selection Select at least two nodes and choose **Auto Layout**, or press `⌘ ⇧ L`. The layout follows graph connections and arranges the selected actions from left to right. Use the additional selection tools for smaller adjustments: * **Auto align top/left** — `⌘ ⇧ A` * **Auto align center** — `⌘ ⇧ S` * **Auto align bottom/right** — `⌘ ⇧ D` The editor chooses horizontal or vertical alignment based on the shape of the selection and keeps at least a small gap between aligned nodes. Auto-layout the functional nodes first, then adjust comments and explanatory spacing. Repeated manual pixel adjustments are rarely worth preserving. ## Lay out the entire workflow Choose **Auto Layout Entire Workflow** in the main toolbar or press `⌘ ⇧ G`. The full layout uses the graph's dependencies and keeps visual groups together. If a group includes a [Comment](/reference/actions/core/comment), the upper-left comment acts as a heading above the group's functional nodes. This makes a consistent pattern effective: * Add a **Validate order** comment above the actions that parse input, validate the schema, and route valid and invalid data. * Add a **Fulfill order** comment above the actions that create the shipment and notify the customer. Automatic layout is deterministic from the graph and current groups, but it is still a structural tool. Review long edge crossings and adjust the few places where business meaning benefits from extra space. ## Add comments [Comment](/reference/actions/core/comment) displays Markdown directly on the canvas. It has no runtime output and never affects execution. Use comments for: * a section heading; * the business rule behind a condition; * the expected shape of a sub-workflow payload; * an important external-system assumption; or * a maintenance note that belongs with the graph. Comments support left, center, or right alignment and small, medium, or large text. Comments are visible to people who can view the workflow. Never place API keys, passwords, access tokens, or other secrets in them. Write comments about intent rather than narrating an obvious node. **Orders over \$500 require manual review before fulfillment** is more useful than **Checks if amount is greater than 500** because it records the business rule, not merely the comparison. ## Highlight related nodes Select nodes and choose **Highlight Color** from the selection toolbar. Nearby nodes with the same color form a dashed visual group. Highlights are most useful when each color has a stable meaning within one workflow, such as: * blue for input normalization; * violet for AI processing; * green for successful side effects; and * red for validation or failure handling. Clicking a group border selects the group. Shift-clicking toggles it alongside the current selection, and dragging the border moves the grouped nodes together. Auto-layout treats nearby groups as units, which helps preserve sections while rearranging the full workflow. Color is organizational metadata, not execution logic. Use connections, branching actions, and meta controls to define actual behavior. ## Pin frequently used actions Open action search with `/`, `⌘ K`, or `⌘ P`. In the search results, pin an action to place it in the main toolbar. Pinned actions can be reordered with the left and right controls in the search result. From the toolbar: * click a pinned action to add it at the center; * drag it onto a specific canvas position; or * press its slot number, from `1` through `9`, to add it at the pointer. Pins are stored for the current browser, so they personalize the editor rather than changing the workflow for collaborators. Keep the set small and focused on the primitives you actually repeat. Text, Number, Create Object, Comment, and the control actions you use most often are good candidates. ## Refactor a dense section When a section is internally coherent but makes the parent workflow hard to scan: 1. Select its functional nodes. 2. Choose **Extract to Sub-Workflow**. 3. Inspect the new payload and result boundary. 4. Give the child a specific name. 5. Add a comment beside the caller describing the contract. The extraction works most cleanly with one incoming and one outgoing boundary connection. See [Build Sub-Workflows](/building/sub-workflows#extract-selected-nodes) before extracting a selection with several independent inputs or outputs. ## A practical organization pass For an existing workflow, use this order: Identify the trigger data, primary transformations, and final side effect. Make that path easy to read from left to right. Place validation, fallback, and failure paths consistently above or below the main path. Select connected sections and use Auto Layout before arranging the entire workflow. Add comments for rules and contracts that the node names cannot explain. Group nodes by responsibility, not by package or arbitrary visual variety. Move a sequence into a sub-workflow when it has a clear interface or is used from more than one place. A well-organized canvas should let a reader answer three questions quickly: what starts the workflow, what decisions it makes, and what external changes it can perform. # Build Sub-Workflows Source: https://learn.workflow.dog/building/sub-workflows Extract reusable workflow logic, define its input and output, and call it safely. A sub-workflow packages a reusable sequence behind one input and one returned value. It can be called from another workflow, used as the body of a loop, or used as a custom list predicate. ## The callable workflow contract * The [Sub-Workflow trigger](/reference/triggers/core/callable) allows another workflow to start it. * [Data from Trigger](/reference/actions/core/trigger-data) exposes the caller's payload as **Data In**. * Reusable actions transform or act on that input. * [Return Data](/reference/actions/core/return-data) sends one value back to a waiting caller. The input and output can be any supported value. For a stable interface, prefer an object with named properties over a positional list or an undocumented block of text. ## Create one manually Choose **When another workflow calls this one** as its trigger. Add **Data from Trigger** and connect **Data In** to the actions that need the caller's payload. Add validation, integrations, and transformations as you would in any workflow. Add **Return Data** and connect the result. A waiting caller receives `null` if the child finishes without returning data. Add [Run Workflow](/reference/actions/core/run-workflow) to the parent, select the child, and connect its payload. ## Call once [Run Workflow](/reference/actions/core/run-workflow) starts the selected callable workflow and waits for it to finish. | Parent input or output | Child meaning | | ---------------------- | ----------------------------------------------------------- | | **Payload** | Becomes **Data In**. | | **Result** | Receives the value sent through **Return Data**, or `null`. | If the child fails, Run Workflow fails with the child's failure message. This makes validation and errors in the child visible to the parent. ## Call for a list Use [Loop Workflow](/reference/actions/core/loop-workflow) when the same child should process multiple payloads. It starts one child at a time and returns one result per item in the same order. Custom list predicates use the same interface: * [Filter With Workflow](/reference/actions/arrays/filter-with-workflow) keeps items whose child returns a truthy value. * [Find With Workflow](/reference/actions/arrays/find-with-workflow) returns the first item whose child returns a truthy value. See [Lists and Loops](/building/lists-and-loops) for the behavioral differences and limits. ## Select a workflow dynamically The **Selected Workflow** input can be fixed in the node or supplied as a Workflow value. [Workflow](/reference/actions/core/workflow) resolves a callable workflow from the current project and exposes that typed value. Dynamic selection is useful when an earlier branch chooses among several implementations with the same input/output contract. Keep the contract consistent; the editor cannot prove that two arbitrary workflows return the same shape. ## Extract selected nodes The canvas can turn an existing selection into a sub-workflow: Select the connected actions you want to move. The editor creates and enables a callable workflow, moves the selected actions into it, and adds a configured **Run Workflow** node in their place. When the selection has exactly one connection entering and one leaving, the editor bridges them through the new payload and result. Rename the new workflow and add a [Comment](/reference/actions/core/comment) describing its expected input, returned output, and failure behavior. Review extracted workflows before relying on them. Selections with multiple inbound or outbound boundary connections cannot be represented by one automatic payload or result connection. Package multiple values into an object before extraction, or reconnect the interface manually afterward. ## Design a durable contract Use an object for any interface likely to grow: ```json theme={null} { "customer_id": "cus_123", "order_id": "ord_456", "notify": true } ``` Return a similarly named object: ```json theme={null} { "status": "processed", "record_id": "rec_789" } ``` This makes call sites self-describing and lets you add optional properties without changing the meaning of existing positions. ## Failure and recursion behavior * A failure propagates through callers that wait, including **Run Workflow**, **Loop Workflow**, and workflow-backed filter/find actions. * A child with no **Return Data** produces `null`; that is a successful run, not a failure. * Loop and predicate callers fail rather than returning partial results when a child fails. * Recursive workflow calls are rate-limited to prevent infinite recursion. Put reusable business logic in a sub-workflow, but leave orchestration in the parent. A focused child with a clear input, output, and error contract is easier to test and reuse than a large child that controls the entire process. # Actions Source: https://learn.workflow.dog/essentials/actions Add, configure, and connect the nodes that perform work in a workflow. Actions are the working parts of a workflow. An action can call a service, transform text, make a decision, wait for a dependency, run another workflow, or return a result. Each action appears as a node on the canvas. ## Add an action Press /, ⌘ K, or ⌘ P to open action search. Search by action name, package, or related keyword, then select a result to add it to the canvas. The picker groups actions by package. For example, **Core** contains general workflow tools, while Gmail, HTTP, and Google Sheets contain service-specific operations. You can pin actions you use frequently so they stay available in the editor toolbar. Search for the outcome you want, such as `respond`, `format date`, or `get row`. You do not need to know the package first. ## Configure an action Select one node to open its configuration panel. Inputs can appear in the panel, on the node, or in both places depending on how the action is designed. There are three common input modes: | Mode | Use it for | | ---------------------- | -------------------------------------------------------------------------- | | **Fixed value** | Text, numbers, choices, and other values that stay the same between runs. | | **Connected value** | Data produced by the trigger or another action during the current run. | | **Fixed or connected** | Inputs with a function control that can switch between the two approaches. | Required inputs must receive a valid value before the action can succeed. Optional inputs may have a default or may be omitted. Hover an input handle to see its description, declared data type, requirement, and connection state. The editor can connect values whose declared types do not match. A connection may therefore look valid on the canvas but fail when the action validates its inputs at runtime. Check the input and output types before testing. ## Connect actions Drag from an output handle to an input handle. The connection passes the value and makes the target action wait for that source. * An input accepts one connection. * An output can feed several actions. * Independent branches are eligible to run concurrently. Object outputs can expose the entire object and selected properties. Choose the properties you need instead of passing a large object into an action that expects one field. Some repeatable inputs also let you switch between separate entries and one entire list. During an inspected run, output handles can show the actual value that action produced. This is useful for finding the right object property before wiring the next action. See [Workflow runs](/essentials/workflow-runs) for the run inspection tools. ## Control the node Select one or more actions to access common canvas operations: * enable or disable the selection, * duplicate, copy, cut, or delete it, * align or automatically lay out several nodes, * select connected upstream or downstream actions, and * extract a selection into a sub-workflow. A disabled action is skipped. Its normal outputs do not produce values, so downstream actions that require those outputs are skipped as well. For per-run control, an action can expose meta controls such as **Conditional** and **Wait For**, plus outcome values such as **Did Action Succeed?** and **Error**. Learn how to build those branches in [Meta controls](/building/meta-controls). ## Choose the right action The action picker gives a short description. The [Actions reference](/reference/actions) provides the full contract for every built-in action: * what the action does, * each input and its type, * each output and its type, * relevant limits and edge cases, and * setup or troubleshooting details when needed. Use the exact name shown in the picker to find the corresponding reference page. For events that begin a workflow, use the [Triggers reference](/reference/triggers) instead. # Enable and pause workflows Source: https://learn.workflow.dog/essentials/enable-and-pause Control whether new trigger events are allowed to execute a workflow. A workflow is either **Live** or **Paused**. * **Live** workflows accept trigger events and queue runs when project usage requirements are satisfied. * **Paused** workflows reject newly created runs before execution. New workflows start Paused so you can configure the trigger and graph before allowing events to execute actions. ## Enable a workflow Open the trigger drawer, select any required account, and complete the trigger-specific settings. Confirm the editor shows **Saved**. Enabling does not force a pending graph save to finish first. Confirm selected accounts are healthy. For billable triggers, confirm the project has run credits or active usage billing. Open the status menu at the top of the editor and choose **Enable Workflow**. The status changes to **Live**. Trigger the workflow and inspect its new run in **Run History**. ## Pause a workflow Open the **Live** status menu and choose **Pause Workflow**. The status changes to **Paused**. Pausing is immediate for runs created after the status update, but it is not a subscription teardown or queue purge. Pausing does not cancel runs that are already Scheduled. Those delayed runs remain queued and can execute at their scheduled time. Cancel each Scheduled run from run history when it must not execute. ## What happens to events while paused External trigger subscriptions remain configured while the workflow is paused. When a trigger event tries to start the workflow: 1. WorkflowDog creates a run record from the event. 2. The eligibility check sees that the workflow is paused. 3. The run is marked **Failed** with **The workflow is paused**. 4. The event is not queued for later execution. Enabling the workflow later does not replay these paused-event failures. The same rule applies to manually choosing **Re-run** while the workflow is paused: the new run fails the paused eligibility check. Keeping the external subscription configured makes pause and resume fast and avoids repeatedly creating provider webhooks or watches. It also means run history can show failed paused events. ## Pausing and scheduled work A Schedule Workflow action reserves and queues its delayed run when the parent workflow executes. The destination workflow's Live or Paused state is checked at that queueing moment. If the destination is Live when the run is scheduled and becomes Paused later, the existing Scheduled run is not checked again before execution. Cancel it explicitly if the pause should include already scheduled work. ## Pausing and integrations Pausing does not: * Disconnect integration accounts. * Revoke provider permissions. * Remove Gmail watches, Microsoft subscriptions, or other external event sources. * Clear trigger configuration. Use [Integrations](/essentials/integrations) to replace or disconnect an account. See [External triggers](/essentials/external-triggers) for the subscription lifecycle. ## Billing can still stop a Live workflow **Live** means the workflow is allowed to run; it does not bypass project usage checks. A Live workflow can create a Failed run when: * The project has no run credits and no usage subscription. * The subscription exists but its payment state does not allow new usage. Resolve the project issue under [Usage and billing](/essentials/usage-and-billing), then send a new event or manually re-run the saved payload. ## When to pause Pause a workflow when: * Editing actions that send messages or change external data. * Rotating an integration account. * Investigating repeated bad inputs. * Preventing new work while you cancel already Scheduled runs. For a planned account migration, pause first, swap action usages, reconfigure the trigger, confirm the new account is healthy, and then enable the workflow. ## Troubleshooting Check whether it was already in Scheduled status before the pause. Pausing blocks newly queued work but does not cancel delayed runs that were already accepted. The trigger subscription is still receiving events. This is expected while paused. Enable the workflow when ready, or reconfigure/disconnect the trigger source when you need events to stop at the provider. Open the failure tooltip. Out-of-credit and invalid-payment failures are project billing problems, while a worker failure is an execution-system problem. Confirm the workflow is Live and the project can accept billable runs. A manual re-run goes through the same pause and billing checks as a trigger event. # External triggers Source: https://learn.workflow.dog/essentials/external-triggers Configure and operate provider-backed event subscriptions safely. An **external trigger** listens for events from another service, such as a new Gmail message, a Google Forms response, a Microsoft Outlook message, or a TidyCal booking. The trigger's account and settings describe the event source. When the provider sends an event, WorkflowDog converts it into one or more workflow runs. ## Configure an external trigger Create a workflow and choose the provider event that should start it. Open **Configure Trigger**, select a healthy integration account, and approve any required permissions. Choose the mailbox, label, form, or other trigger-specific source. See that trigger's reference page for its exact fields. Wait for the trigger configuration to finish updating. WorkflowDog creates or adopts the required provider subscription during configuration. Set the workflow Live, send a new provider event, and inspect the resulting run. External event sources are configured even while the workflow is Paused. Live or Paused controls run eligibility; it is not the switch that creates or removes the provider subscription. ## How subscriptions are reused WorkflowDog creates a deterministic identity for each logical event source. If multiple workflows need the same underlying source, they can share one provider subscription instead of creating duplicates. For example, two workflows can listen to different event types delivered by the same account-backed provider subscription. WorkflowDog tracks which workflow and trigger type should receive each event. This sharing affects cleanup: * Changing one workflow removes only the source relationship it no longer needs. * If another workflow still uses the source, the provider subscription stays active. * If no workflow uses it, WorkflowDog cleans up the external resource and deletes the source. ## Change trigger configuration Saving a new trigger configuration performs a reconciliation: 1. WorkflowDog derives the event sources required by the new settings. 2. It creates or adopts those sources. 3. It removes obsolete relationships from the workflow. 4. It tears down an obsolete provider subscription only when nothing else uses it. This is why account and source changes should be made through **Configure Trigger** instead of by editing raw workflow data. After a material change, send a new event that matches the new configuration. Changing the source does not replay events that occurred under the old configuration. ## Pause without removing the subscription When a workflow is Paused, external subscriptions continue receiving events. Each attempted run is recorded as Failed with **The workflow is paused** and is not queued for later. Use Paused for temporary execution control. If you need the provider subscription itself removed, change the trigger configuration, disconnect the account, or delete the workflow. Read [Enable and pause workflows](/essentials/enable-and-pause) for scheduled run behavior and other pause caveats. ## Reconnect an account-backed trigger Provider credentials can expire, be revoked, or lose permissions. WorkflowDog marks an account unhealthy when it can no longer use it and notifies Editors of projects linked to that account. Reconnecting updates the credentials and starts best-effort background recovery for account-backed event sources. A source that needs fresh setup is torn down and recreated while preserving the workflows and event types that used it. Recovery is asynchronous and is not a guarantee that events missed during an account or provider outage will be replayed. After reconnecting, verify the trigger and send a new event. If a provider renewal worker exhausts its retries, the event source is marked unhealthy. A later setup or account-recovery cycle can rebuild it from scratch. ## Disconnect an account Disconnecting an account from a project clears matching account values from trigger configurations. WorkflowDog processes those trigger updates normally, so obsolete event-source links and unused provider subscriptions are cleaned up. Before disconnecting: 1. Connect the replacement account. 2. Pause workflows that can cause side effects. 3. Reconfigure every trigger that uses the old account. 4. Send a test event through the replacement. 5. Disconnect the old account. The Integrations page's **Swap Accounts** tool does not update trigger configurations. See [Integrations](/essentials/integrations). ## Delete workflows and projects Deleting a workflow removes its event-source relationships. Shared sources stay active for other workflows; unshared sources are cleaned up. Deleting a project cleans up event sources for its workflows before the project and its data are deleted. ## Operate triggers reliably * Use a dedicated service account when employee access may change. * Grant every permission required by the trigger, not only by its downstream actions. * Treat a **Needs Reconnecting** badge as an operational incident. * Send a new test event after changing an account or event filter. * Inspect run history for Paused, billing, or node errors before assuming the provider subscription is broken. * Do not rely on automatic backfill unless the individual trigger reference explicitly documents it. ## Troubleshooting Confirm the workflow is Live, then inspect history for a Paused or billing failure. Check the integration account for **Needs Reconnecting**, review the trigger filters, and send a new event after correcting the issue. This is expected. Pausing rejects new runs but keeps the provider subscription configured. Reconfigure or disconnect the trigger source when you need the external subscription removed. Accounts are project resources, and disconnecting an account clears its references across the project. Reconfigure affected workflows with a replacement account before disconnecting. Open and save the trigger configuration to run source reconciliation, then send a new matching event. Also verify provider-side filters and permissions. If the issue continues, reconnect the account. # Integrations Source: https://learn.workflow.dog/essentials/integrations Connect, select, reconnect, swap, and disconnect external accounts. An **integration account** lets actions and triggers access an external service, such as Google, Microsoft, Airtable, or OpenAI. Accounts are linked to a project, then selected on the nodes and triggers that use them. ## Connect an account The first connection starts inside the workflow editor, not on the project's **Integrations** page. Add an action that uses the service, or open a trigger that requires the service. Find **Third-party account** and choose **Connect new account**. OAuth integrations open the provider's authorization page. API-key integrations open a credential dialog in WorkflowDog. Approve the permissions required by the current action or trigger. After a successful connection, the new account is selected automatically. It also appears on the project's **Integrations** page. The first account connected for a provider in a project becomes that provider's default account. ## Select the right account Each account selector lists accounts for the current provider and project. A node can use an account only when it is healthy and has every permission the node requires. When an account input has never been set, WorkflowDog selects the healthy default account if it has the required permissions. An explicit account selection is preserved until it is cleared, disconnected, becomes unhealthy, or no longer satisfies the node's permission requirements. Use **Clear Selection** when a node should not inherit or retain the current account. ## Manage connected accounts Open **Integrations** from the project dashboard to see accounts grouped by provider. For each account, you can: * **Set as Default** — Make it the automatic choice for unset account inputs from the same provider. * **View Account Usage** — Find action nodes whose saved graph contains the account. * **Swap Accounts** — Replace the account on selected action-node usages with another account from the same provider. * **Disconnect** — Remove the account from the current project and clear its saved references. Defaults are project-specific. Setting a Google account as the default in one project does not make it the default in another. ## Swap action nodes to another account Account swapping is useful before disconnecting an old employee account or rotating a service account. Connect the new account to the project and ensure it has the permissions required by the affected actions. On **Integrations**, open the old account's menu. Under **Account Usage**, select the workflow and action-node locations to update. The replacement must belong to the same provider. Select it and choose **Swap Accounts**. Open any trigger that uses the old account and select the replacement manually. **Account Usage** and **Swap Accounts** cover action nodes only. Trigger configurations are not listed or swapped by this tool. ## Approve missing permissions Different nodes from the same provider can require different OAuth scopes. If an existing account is missing a required permission, click it in the account selector and complete authorization again. WorkflowDog requests the new permissions together with the account's existing permissions. Google reconnections show the consent screen again so Google can issue refreshed credentials. After reconnecting, review the node selection. An account that lacked required permissions may have been cleared from the input before the reconnection. ## Reconnect an unhealthy account An account marked **Needs Reconnecting** has credentials that WorkflowDog can no longer use. Actions using it can produce node errors, and account-backed triggers can stop receiving new events. Open an account selector and click the unhealthy account. OAuth providers take you through authorization again. Refresh the account list and confirm the warning is gone. Open each account-backed trigger and confirm its configuration. Reconnection starts background recovery for event subscriptions that need rebuilding. Test with a new email, form response, or provider event. Do not assume an event missed during the outage will be replayed. If reconnection continues to fail, revoke WorkflowDog from the provider's own connected-app settings, then connect the account again. ## Disconnect an account Disconnecting performs more than removing an account from the list: * The project-to-account link is removed. * Matching account selections in action-node graphs are changed to no selection. * Matching account selections in trigger configurations are cleared. * Trigger event sources are reconciled, including cleanup of external subscriptions that are no longer used. Disconnecting does not revoke WorkflowDog at the external provider. Use the provider's security or connected-app settings when you also need to revoke the authorization itself. Swap action usages and reconfigure triggers before disconnecting when workflows must continue without interruption. ## Troubleshooting The account is unhealthy or lacks a permission required by that node. Click the account to reconnect and approve the missing permissions, then refresh the selector. Connect the first account from an action or trigger in the workflow editor. The Integrations page manages accounts after they have been linked to the project. Swapping is limited to action-node usages. Open the trigger configuration and choose the replacement account manually. Account links are project-specific. Connect the account from a workflow in the second project before trying to select it there. Learn how account-backed event subscriptions behave in [External triggers](/essentials/external-triggers). # Projects Source: https://learn.workflow.dog/essentials/projects Organize workflows, data, integrations, and teammates in a project. A **project** is the top-level container in WorkflowDog. Its workflows, workflow runs, variables, connected accounts, team, and billing settings are kept together. WorkflowDog does not have a separate workspace layer. When you choose a project, you are choosing the complete working context for everything in the project dashboard. ## Create a project Use the project switcher and choose the option to view your projects. Select **Create Project**, enter a name, and confirm. The person who creates the project starts with Editor access. Open **Workflows**, select **Create a Workflow**, and choose the trigger that should start it. Workflow creation is trigger-first; there is not a workflow template picker. ## What belongs to a project | Project resource | Scope | | --------------------- | --------------------------------------------------------------------- | | **Workflows** | Can use other workflows and variables in the same project. | | **Workflow runs** | Appear in the project's combined run history. | | **Project variables** | Can be read or changed by any workflow in the project. | | **Integrations** | Accounts are linked to the project before its workflows can use them. | | **Team and roles** | Access is granted per project. | | **Usage and billing** | Run credits, usage charges, and seats are tracked per project. | Moving a workflow between projects is not available. Create the workflow in the project whose integrations, variables, team, and billing it should use. ## Switch projects Open the project switcher from the dashboard sidebar, search by project name, and choose a project. When possible, the switcher keeps you on the equivalent dashboard section—for example, switching from one project's **Variables** page opens **Variables** in the destination project. The P shortcut opens the project switcher when focus is not inside another input. ## Organize workflows with folders The **Workflows** page supports nested folders. Create a folder, create subfolders from its menu, and drag workflows between folders or back to the project root. Deleting a folder does not delete its workflows: * Workflows in a nested folder move to the deleted folder's parent. * Workflows in a top-level folder move back to the project root. * Nested folders inside the deleted folder are removed. Workflow folders are stored in the current browser's local storage. Folder names, nesting, collapsed state, and workflow assignments are not shared with teammates or synchronized to another browser or device. The workflows themselves remain project data. If folders disappear after clearing browser data or changing devices, the workflows are still available at the project root. ## Rename a project Open the project overview, select the project name or its menu, and choose **Rename Project**. Renaming changes the project label without changing its workflows, integrations, or URL identifier. Only an Editor can rename a project. See [Team and permissions](/essentials/team-and-permissions) for role details. ## Delete a project Project deletion permanently removes the project and its associated workflows, runs, variables, integration links, invitations, and other project data. It also cancels an active usage subscription for that project. Project deletion cannot be undone. Confirm that you no longer need the project's run history or variable values before deleting it. An Editor can delete the project from the project overview menu. Because Editors have broad project control, grant that role only to trusted teammates. ## Troubleshooting The switcher lists only projects where your account is a member. Confirm that you accepted the invitation while signed in with the invited email address and that another Editor has not removed you. This is expected. Folder organization is local to each browser. Search for the workflow by name, then recreate any local folder structure you want on that device. Those actions require Editor access. A Viewer can inspect project resources but cannot change project settings. # Team and permissions Source: https://learn.workflow.dog/essentials/team-and-permissions Invite teammates and control who can view or change a project. Project membership controls access to every workflow, run, variable, and integration linked to a project. WorkflowDog currently has two project roles: **Viewer** and **Editor**. ## Roles | Capability | Viewer | Editor | | ----------------------------------------------- | :----: | :----: | | View workflows and project settings | ✓ | ✓ | | Inspect workflow runs, outputs, and errors | ✓ | ✓ | | View project variables and integration accounts | ✓ | ✓ | | Build, rename, enable, or delete workflows | | ✓ | | Clear variables or manage integrations | | ✓ | | Invite, remove, or change teammate roles | | ✓ | | Manage billing or delete the project | | ✓ | Editor is a fully trusted role. There is no separate Owner or Admin permission tier: project creation does not give the creator protected permissions that other Editors lack. The server checks permissions for project, workflow, and workflow-run operations. Hiding a control in the dashboard is not the only access check. ## Invite a teammate From the project dashboard, open **Team**. Select **Invite someone to your project**, enter their email address, and send the invitation. The project must have an available seat. The recipient follows the link in the invitation email. If they do not have a WorkflowDog account, they must create one first. They must be signed in with the exact email address that received the invitation. New invitations currently join as **Editors**. If the teammate only needs read access, change them to **Viewer** after they accept. A pending invitation remains on the Team page until it is accepted or an Editor cancels it. Sending a second invitation to the same address while one is pending is not allowed. ## Change a role Open a teammate's menu on the **Team** page and choose **Make Viewer** or **Make Editor**. Role changes take effect at the project boundary: * A Viewer retains access to project data but loses write access. * An Editor gains write access across workflows, variables, integrations, billing, and team management. * Roles in one project do not grant access to another project. You cannot change your own role from your own member card. Ask another Editor to change it. ## Remove a teammate Choose **Remove from project** from the member's menu and confirm. Removal revokes their project access; it does not delete workflows or other resources they created. To restore access later, send a new invitation. ## Manage seats The Team page compares accepted members with the project's seat allowance. Pending invitations do not replace an existing member. When the project has reached its limit, use **Usage & Billing** or contact WorkflowDog about additional team seats. ## Protect sensitive project data Viewers can inspect variable values, run inputs and outputs, and connected account metadata. Do not use project membership as a way to expose only one workflow or only part of a workflow. For the same reason: * Do not store API keys or passwords in project variables. * Review run outputs before inviting someone who should not see processed customer data. * Give Editor access only when the person should be able to alter or delete project resources. ## Troubleshooting Sign in with the exact email address that was invited. The invitation also becomes invalid after an Editor cancels it or after it has already been accepted. You need Editor access and an available project seat. The invite also fails when the email is already a member or already has a pending invitation. This is expected. Viewer access is read-only at the API layer. Change the teammate to Editor only if they should be able to modify the entire project. # Triggers Source: https://learn.workflow.dog/essentials/triggers Choose, configure, and use the event that starts a workflow. A trigger defines the event that creates a workflow run. It may listen for an email, expose an HTTP endpoint, watch a connected service, follow a schedule, or allow another workflow to call this one. Every workflow has exactly one trigger. ## Choose the trigger first You select a trigger when creating a workflow. Choose the event that most closely represents the boundary of the automation: | Need | Trigger family | | ------------------------------------- | ---------------------------------------- | | Receive a request from another system | URL, Webhook, or Form Submission | | React to a connected app | Gmail, Outlook, Google Forms, or TidyCal | | Run repeatedly | Schedule | | Start from an inbound email address | Email Hook | | Reuse a workflow from another graph | Sub-Workflow | The trigger type cannot be swapped in the editor. You can reopen and change its configuration, but changing the kind of event requires another workflow. See [Service triggers](/guides/service-triggers) for account-backed events, [HTTP endpoints and webhooks](/guides/http-webhooks) for inbound requests, and [Scheduling workflows](/guides/scheduling) for time-based automation. ## Configure the event source Select the trigger button in the editor header to open its configuration. Settings vary by trigger and may include: * a connected account, * a subject, label, form, or booking filter, * one or more schedules and timezones, or * a unique URL to copy into another system. When you change a configurable trigger, use **Save** to apply it. **Reset** discards the unsaved fields. Closing a dirty trigger panel also saves the changes before it closes. A broad trigger can create many runs. Configure the narrowest useful account, source, and filter before enabling the workflow. ## Use trigger data New workflows include a **Data from Trigger** node. On the canvas it takes the name and color of the selected trigger, and its outputs match that trigger's event payload. For example: * an email trigger exposes message and sender fields, * a URL trigger exposes the method, path, headers, query, and body, * a schedule exposes its timestamp, and * a sub-workflow exposes the value passed as **Data In**. Connect only the outputs the workflow needs. Object and list outputs may let you select a property or pass the complete value. The [Triggers reference](/reference/triggers) documents the exact outputs, filters, request limits, and setup requirements for every trigger. ## Test with the real event WorkflowDog does not currently provide a generic **Test Run** button. To get representative trigger data, save the workflow, enable it, and cause the actual event: * send the matching email, * submit the configured form, * call the endpoint, * create the booking, or * wait for the configured schedule. Then inspect the resulting run and its trigger outputs. Follow [Testing workflows](/guides/testing-workflows) for the complete loop. ## Trigger configuration and workflow state Trigger configuration decides which events match. Workflow state decides whether matching events are accepted as new runs. A correctly configured but paused workflow will not process new events. See [Enable and pause](/essentials/enable-and-pause) for lifecycle behavior and [Workflow runs](/essentials/workflow-runs) for observing what a trigger created. # Usage and billing Source: https://learn.workflow.dog/essentials/usage-and-billing Understand run credits, pay-as-you-go usage, seats, and billing failures. Usage and billing are managed per project. A project's run credits are used first; after they are gone, an active pay-as-you-go subscription allows billable workflows to continue running. The current pay-as-you-go rate shown in WorkflowDog is **$1 per 100 workflow runs**, or **$0.01 per run**. A run can contain any number of actions. ## How a run is charged When WorkflowDog receives a billable run: 1. It checks whether the workflow is Live. 2. It uses one project run credit when a credit is available. 3. If no credits remain, it checks for an active project subscription. 4. With valid usage billing, it records a \$0.01 usage charge. 5. Without valid billing, it marks the run Failed instead of executing it. New projects currently begin with 100 introductory workflow-run credits. The current balance appears under **Usage & Billing**. The **Callable Workflow** trigger does not consume a credit or create a usage charge. It is the current free trigger type. The Usage page can still include free and failed runs in activity counts even when they contribute no cost. ## Credits before pay-as-you-go Run credits are always depleted before paid usage accrues. Connecting a subscription does not discard the remaining balance. When a project has neither credits nor usable pay-as-you-go billing, billable runs fail with: ```text theme={null} The project is out of workflow runs and isn't set up for usage billing. ``` Enable billing, then send a new trigger event or [re-run](/essentials/workflow-runs#re-run-with-the-same-trigger-data) a saved payload. The failed run is not resumed automatically. ## What counts as a run Billing eligibility is decided when the run is queued, before its nodes execute. Therefore: * A run that later completes with a node error still consumes its reserved credit or paid usage. * A run that fails the initial Paused, out-of-credit, or invalid-payment check does not execute nodes. * A Scheduled run reserves its credit or usage when it is scheduled. * Cancelling a Scheduled run restores its credit or reverses its usage charge. * The number of actions in the graph does not change the per-run price. A Completed run can contain node errors and still be billable. Use the cost card for billed usage and run history for execution quality; the raw run count is not the same as the bill. ## Enable pay-as-you-go Choose the project, then open **Usage & Billing** from the dashboard. Check **Workflow Run Credits**, the current billing period, and recent usage by workflow. Select the upgrade option and complete the hosted checkout. Billing belongs to this project only. Return to the project and confirm the billing warning is gone. Live billable workflows can now continue after credits reach zero. Only an Editor can start checkout or open the billing-management portal. ## Read the Usage & Billing page The page includes: | Section | Meaning | | ------------------------- | ---------------------------------------------------------------------- | | **Usage Cost** | Sum of paid run charges in the selected billing period. | | **Workflow Run Credits** | Prepaid or introductory runs remaining before paid usage accrues. | | **Team Members** | Accepted project members compared with the project's seat allowance. | | **Breakdown by Workflow** | Run activity attributed to each workflow, including deleted workflows. | Use the period arrows to inspect an earlier billing period. A future period cannot be selected. Deleted workflows can remain in the breakdown because project-level run records are preserved for usage tracking. ## Manage the subscription When the project has an active subscription, **Manage** opens the billing portal. Use it to update the payment method or subscription. If WorkflowDog cannot accrue new usage, the project shows a billing warning and new billable runs fail with: ```text theme={null} The payment is invalid. ``` Fix the payment issue in the billing portal. Existing failed runs remain in history; send a new event or re-run them after billing is healthy. ## Team seats Seats are also tracked per project. When accepted members reach the seat allowance, Editors cannot send another invitation. Removing a member frees a seat. For a larger team plan, use the contact link shown on **Usage & Billing**. ## Troubleshooting Activity counts can include free Callable Workflow runs and runs that failed before billing. Use **Usage Cost** for the amount accrued, not the total activity count alone. Credits and usage are reserved when the run is accepted, before node execution. A node-level error does not refund the run automatically. Cancellation restores a credit-backed run or records a negative usage adjustment for a paid run. The history row remains with Cancelled status. Open the billing portal and resolve the payment issue. A subscription identifier alone is not enough; the project must also be allowed to accrue usage. # Project variables Source: https://learn.workflow.dog/essentials/variables Persist values between workflow runs and share them across a project. **Project variables** store values between workflow runs. Every workflow in the same project can read or update a variable by its key. Use project variables for state that must outlive one run, such as the last processed identifier, a routing preference, or a list accumulated over time. Project variables are not secrets. Every project member with Viewer or Editor access can inspect their values from the dashboard. Do not store passwords, API keys, or access tokens in them. ## Set and read a value Add [Set Project Variable](/reference/actions/core/set-project-var). Provide a **Key** and the **Value** to store. Setting an existing key replaces its previous value. In the same or another workflow, add [Get Project Variable](/reference/actions/core/get-project-var) and use the exact same key. Set **Default Value** when the workflow needs a fallback. Without a default, a missing variable returns `null`. Open **Variables** in the project dashboard to view the stored key, value, and last update time. ## Variable behavior | Operation | Existing key | Missing key | | ---------- | --------------------------------------------------- | ------------------------------ | | **Set** | Replaces the stored value. | Creates the variable. | | **Get** | Returns the stored value with its WorkflowDog type. | Returns the default or `null`. | | **Append** | Adds items when the current value is a list. | Starts with an empty list. | | **Clear** | Deletes the variable record. | Makes no change. | Keys are scoped to the project and matched exactly. `lastCustomerId` and `LastCustomerId` are different variables. The Variables dashboard search helps locate similar keys, but it does not change exact key matching inside workflows. ## Append to a stored list [Append to List in Project Variables](/reference/actions/core/append-to-project-var-list) loads the current list, appends the supplied values in order, and stores the combined list. If the key does not exist, the action starts from `[]`. If the existing value is not a list, the node reports **Value is not a list**. A value that can no longer be decoded reports **Variable is corrupted**. Append reads the existing list and writes a replacement; it is not an atomic concurrent append. If parallel runs append to the same key at nearly the same time, both can read the same old list and the later write can overwrite the other run's additions. Serialize those writes or give parallel work separate keys. ## Inspect and clear variables Open **Variables** from the project dashboard to: * Search keys. * Preview simple values. * Expand lists and objects in the data navigator. * See when a value was last updated. * Choose **Clear Value** to delete a variable. The dashboard does not create or edit values directly. Use workflow actions to set or append values. Clearing a variable deletes it rather than storing `null`. The next **Get Project Variable** returns its configured default, or `null` if no default was set. ## Example: remember the last processed item 1. Start the workflow with a schedule trigger. 2. Get the `last_processed_id` project variable. 3. Fetch and process items created after that ID. 4. Set `last_processed_id` to the newest successfully processed item. Set the variable only after the workflow successfully processes the item you want to mark. If a node earlier in the path errors and the Set node does not run, the previous checkpoint remains available for the next run. ## Choose stable keys Good keys state both the value and its purpose: ```text theme={null} support_last_processed_message_id daily_report_recipient crm_pending_record_ids ``` Avoid reusing one key for unrelated data types. A key that sometimes contains a number and sometimes a list makes downstream workflows harder to reason about and can break list-specific actions. ## Troubleshooting Confirm the key matches exactly, including capitalization and whitespace, and that the workflow is in the same project as the variable. Also check whether someone cleared the value from the Variables page. The key currently contains another type. Inspect it on the Variables page, then clear it or use **Set Project Variable** to initialize it with a list. Multiple runs are replacing the same list concurrently. Route updates through one sequential workflow, avoid parallel execution for that key, or store each run under a separate key. The dashboard is for inspection and clearing. Add **Set Project Variable** to a workflow to create or replace the value. # Workflow runs Source: https://learn.workflow.dog/essentials/workflow-runs Inspect run history, understand statuses, replay inputs, and cancel scheduled work. A **workflow run** is one execution attempt created from trigger data. Each run stores its input payload, status, node outputs and errors, and a snapshot of the workflow graph selected when the run was queued. ## Open run history WorkflowDog provides two views: | View | Best for | | --------------------------- | ---------------------------------------------------------------- | | **Project → Workflow Runs** | Reviewing activity across every workflow in a project. | | **Editor → Run History** | Inspecting runs and node-level results for the current workflow. | Both views update active **Pending** and **Running** rows automatically. The project view shows the workflow name, date, duration, status, and run actions. The editor history lets you select a run and display its data directly on the canvas. ## Run statuses | Status | Meaning | | ------------- | ---------------------------------------------------------------------------- | | **Pending** | Accepted and waiting for execution to start. | | **Scheduled** | Accepted for a future time and waiting in the queue. | | **Running** | The workflow runner has started processing the graph. | | **Completed** | The runner finished the graph. One or more individual nodes may still error. | | **Failed** | The run could not execute or the workflow runner itself failed. | | **Cancelled** | An Editor cancelled the run while it was still Scheduled. | **Completed** does not mean every node succeeded. A completed run with an amber warning icon contains one or more node errors. Open the run and inspect the affected nodes. Common run-level **Failed** reasons include: * The workflow was paused. * The project had no remaining run credits and no active usage billing. * The project's payment state did not allow new usage. * The execution worker encountered an unrecoverable error. See [Troubleshoot workflow runs](/guides/troubleshooting-runs) for a diagnostic flow. ## Inspect a run on the canvas Select a row from **Run History** in the workflow editor. Node outputs and errors become available for that run, and the editor offers two canvas modes. Shows the saved graph snapshot associated with the run. Use this mode to answer: “What graph actually ran?” The snapshot cannot be edited. It remains stable even after you change the current workflow. Keeps the current workflow graph editable while applying the selected run's results where node and handle identifiers still match. Use this mode to fix the current workflow while referring to a recent run. If nodes were deleted, replaced, or rewired after the run, some historical results may not line up with the current graph. Use **Newer** and **Older** to move between the runs loaded by the editor. This navigation operates on the latest 100 runs fetched for the workflow. Open the history drawer and scroll when you need an older entry. ## Star an important run Use the star action to mark an incident, representative payload, or run you want to find again. Stars are stored with the run and are visible to project members. Starring does not change retention, execution, or billing. ## Re-run with the same trigger data Choose **Re-run** to queue a new run using the selected run's saved trigger payload. A re-run is not an exact replay of the historical snapshot. It uses the same trigger data against the workflow's **current saved graph**, then creates a new snapshot for that graph. Review unsaved changes and wait for **Saved** before re-running. A re-run can also fail immediately when the workflow is paused, the project is out of credits, or billing is invalid. It creates a separate history entry and does not modify the original run. ## Cancel a scheduled run Only a run in **Scheduled** status can be cancelled. Choose **Cancel Run** from its actions. Cancellation: * Changes the run to **Cancelled**. * Prevents the delayed execution from starting. * Restores the run credit or usage charge reserved when the run was scheduled. Pending and Running runs cannot be cancelled from the dashboard. ## Run history after deletion Deleting a workflow removes its workflow graph, trigger configuration, event sources, and snapshots. Project-level run records remain for usage tracking and appear as **Deleted Workflow**. A preserved run row from a deleted workflow cannot be re-run, and its historical canvas snapshot is no longer available. Deleting the entire project removes its run history. WorkflowDog currently does not expose a configurable run-history retention setting in the dashboard. ## Troubleshooting The workflow runner completed, but at least one node reported an error. Select the run, inspect the red or warning-marked nodes, and read their stored error messages. This is expected. Re-run preserves the old trigger payload, not the old graph. Use **Snapshot (Read-Only)** to inspect the original graph and **Overlay** to repair the current one. Cancellation is limited to Scheduled runs. A Pending or Running run has already moved beyond the cancellable delayed state. The snapshot can be unavailable if its workflow was deleted. Check the project-wide history for a **Deleted Workflow** label. # Workflows Source: https://learn.workflow.dog/essentials/workflows Understand the graph, editing model, and execution rules behind every WorkflowDog automation. A workflow turns one incoming event into a graph of actions. Its trigger decides **when** a run begins, its actions decide **what** happens, and its connections decide which values and dependencies move through the graph. Unlike a checklist, a workflow does not run from top to bottom. Position on the canvas is only for readability. The connections between nodes determine execution order. ## Anatomy of a workflow | Part | Purpose | | --------------------- | ------------------------------------------------------------------------ | | **Trigger** | Creates a run when its configured event occurs. | | **Data from Trigger** | Exposes the event's fields as outputs on the canvas. | | **Action** | Performs work, transforms data, or controls part of the run. | | **Connection** | Passes an output into an input and creates a dependency between actions. | | **Static input** | Supplies a fixed value from an action's configuration. | Every workflow has one trigger. You choose it when creating the workflow, then configure it from the trigger button in the editor header. If you need a different kind of trigger, create another workflow and move or recreate the relevant actions there. ## Build on the canvas Create a workflow from the project's **Workflows** page and choose the event that should start it. The new graph includes **Data from Trigger**, displayed with the selected trigger's name and outputs. Press /, ⌘ K, or ⌘ P to open action search. Select an action to add it near the center of the canvas. Select an action to open its configuration panel. Enter fixed values there, or connect values from other nodes to its inputs. Drag from an output handle to an input handle. A connected action waits for that upstream value before it can run. Graph changes save automatically. Check the header for **Saved** before sending a test event, closing the page, or relying on the new version. See [Actions](/essentials/actions) for node configuration and [Triggers](/essentials/triggers) for choosing and configuring the event source. ## How the graph runs When a trigger creates a run, WorkflowDog starts every action whose dependencies are ready. This has several consequences: * Actions on independent branches can run at the same time. * An action with two connected inputs waits for both upstream values. * A fixed value does not add an upstream dependency. * Moving a node left, right, above, or below another node does not change execution order. * A circular set of dependencies is invalid and cannot be saved. For example, if **Fetch Customer** and **Fetch Orders** both depend only on trigger data, they can run concurrently. An action connected to both waits until both branches resolve. If one action must wait for another without consuming its value, add the **Wait For** meta control. Conditions and error-handling outputs are covered in [Meta controls](/building/meta-controls). ## What happens when a branch stops Connections carry execution signals as well as values. If an upstream action is disabled, skipped by a condition, or fails, its normal outputs do not produce values. Actions that require those outputs do not run. Other branches that do not depend on the stopped action can still finish. This is why a run can complete with one or more action errors rather than failing as one indivisible transaction. Use the action's **Did Action Succeed?**, **Error**, and related meta outputs when another branch should react to that outcome. See [Meta controls](/building/meta-controls) for the complete pattern. ## Edit safely WorkflowDog keeps a short local undo history while you edit: * ⌘ Z undoes the latest graph change. * ⌘ Y or ⌘ ⇧ Z redoes it. * Selecting multiple nodes exposes alignment, layout, enable/disable, duplicate, and deletion tools. * Automatic layout is available from the editor toolbar. Each run keeps a snapshot of the workflow graph it started with. Editing the workflow affects future runs, not the historical graph attached to an existing run. Learn how those snapshots appear in [Workflow runs](/essentials/workflow-runs). ## Next steps Once the graph is ready, [test it with a real trigger event](/guides/testing-workflows). Then use [Enable and pause](/essentials/enable-and-pause) to control whether it accepts new events. # HTTP endpoints and webhooks Source: https://learn.workflow.dog/guides/http-webhooks Receive requests with URL, Webhook, or Form Submission triggers and return a response. HTTP triggers give a workflow a unique public endpoint. Choose the trigger based on the request shape you control: | Trigger | Accepted request | Body and data | Best for | | ------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------- | | **URL** | Common methods including `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` | Text up to 10 MB; binary bodies become base64 strings | General HTTP integrations and custom clients | | **Webhook** | `POST` only | Parsed JSON up to 100 MB | Services that send JSON webhooks | | **Form Submission** | `GET` or `POST` | Query fields on `GET`; multipart fields and files on `POST` | Browser forms, Webflow, Framer, and file forms | Open the trigger configuration to copy its endpoint. Treat this URL like an unguessable integration address: share it only with the systems that should start the workflow. ## URL trigger Use **URL** when you need control over the request method or body type. Its trigger data includes: * **Path** * **Method** * **Headers** * **Query** * **Body** Header names are lowercase. Cookie, Cloudflare-prefixed, and forwarded-address headers are omitted. Query values are exposed as strings. Text bodies remain text; binary bodies are exposed as base64 text. The URL shown in the trigger panel can be opened directly for a quick `GET` test. ## Webhook trigger Use **Webhook** for an external service that sends a JSON `POST`. Its trigger data includes: * **Data** — the parsed JSON value, * **Path**, * **Query**, and * **Headers**. Requests with another method receive `405 Method Not Allowed`. Invalid JSON is rejected before the workflow receives trigger data. ## Form Submission trigger Use **Form Submission** as an HTML form's target. A `POST` parses multipart form fields and files. Repeated field or file names may produce lists rather than single values. The trigger can also serve configured HTML on `GET`. When **HTML Response** is enabled, opening the endpoint returns that HTML and does **not** create a workflow run. A `POST` to the same endpoint still submits the form and starts the workflow. If the HTML response is disabled, a `GET` starts the workflow with its query parameters exposed as **Fields**. ## Return a custom response Add one response action to the branch that should answer the caller. **Respond Text**, **Respond JSON**, **Respond Status**, and **Redirect** are available for all three HTTP triggers. The browser-oriented **Respond HTML**, **Respond File**, and **Close Window** actions are intended for URL and Form Submission workflows. Connect every value that must be computed before the response. The HTTP request waits for a response-capable action when an enabled one exists anywhere in the run's graph snapshot. Only the first response action that executes can answer the request. If several response branches are eligible concurrently, their canvas position does not decide which wins. Make the branches mutually exclusive or route them into one response action. ## Default response behavior The caller receives different defaults depending on the saved graph: | Workflow outcome | HTTP result | | --------------------------------------------------------------------- | -------------------------------------------------------------------------- | | No enabled response-capable action exists in the run snapshot | Immediate `202` explaining that the workflow is running without a response | | A response action exists and runs | Its configured status, headers, and body | | A response action exists, but the workflow completes without using it | `200` explaining that the workflow finished without a response | | The run cannot be queued or fails at the worker level | `400` with the workflow failure message | An action error does not automatically become an HTTP error response. A dependent response action may be skipped because the failed action produced no normal output, which leads to the generic completed-without-response result. Use **Did Action Succeed?** and **Error** to build an explicit error response branch. See [Meta controls](/building/meta-controls) for that pattern. ## Test the endpoint Save the graph, enable the workflow, and send a representative request. For repeatable testing, keep an example `curl` command or request fixture with the method, headers, query, and body your integration actually sends. Then inspect both sides: 1. Confirm the caller received the expected status, headers, and body. 2. Open the workflow run and inspect **Data from Trigger**. 3. Check any decoded object properties, files, or base64 body before passing them downstream. Follow [Testing workflows](/guides/testing-workflows) for the full edit-test loop and [External triggers](/essentials/external-triggers) for other ways systems can start workflows. # Scheduling workflows Source: https://learn.workflow.dog/guides/scheduling Choose between recurring schedules and one-time delayed sub-workflow runs. WorkflowDog has two different scheduling tools: | Goal | Use | | --------------------------------------------------- | ----------------------------------------------------- | | Run this workflow repeatedly | **Schedule** trigger | | Run another workflow once at a future date and time | **Schedule Workflow** action with a callable workflow | They are not interchangeable. The trigger owns recurring automation for its current workflow. The action queues one child run and continues without waiting for that child to execute. ## Create a recurring schedule Choose **Schedule** when creating the workflow, then open its trigger configuration. Select **Add Schedule**. A new schedule starts at 9:00 AM every day in your browser's current timezone. Set an exact time or interval, then narrow it by day of month, day of week, or month. Presets include Hourly, Daily, Daily at 9 AM, Weekdays at 9 AM, and Monthly. Choose the IANA timezone that should own the wall-clock time. The schedule follows that timezone through daylight-saving changes. Save the trigger configuration, wait for the graph to show **Saved**, and make the workflow live when it is ready. A workflow can contain multiple recurring schedules. Each recurrence-and-timezone pair must be unique. Every event exposes a **Timestamp** through **Data from Trigger**. The timestamp records when the scheduled event was emitted. Queue load or retries can make the run begin slightly later. ## Schedule a one-time child run Use **Schedule Workflow** inside a parent workflow when an event should queue follow-up work for one specific future time. The selected child must use the **Sub-Workflow** trigger. Configure: * **Selected Workflow** — the callable child to run, * **Date & Time** — at least 10 seconds in the future, and * **Payload** — optional data exposed as **Data In** inside the child. The action queues the child and has no result output. It does not wait until the scheduled date and does not wait for the child to complete. Use [Run Workflow](/reference/actions/core/run-workflow) instead when the parent needs the child's returned result immediately. The child workflow must be enabled when **Schedule Workflow** queues it. Pausing the child later does not cancel a delayed run that is already scheduled. Cancel that run from workflow runs if it should no longer execute. The delayed run captures the child's graph snapshot when it is queued. Later edits apply to newly queued runs, not that already scheduled run. Learn the complete callable-workflow pattern in [Sub-workflows](/building/sub-workflows). ## Choose a timezone deliberately Recurring schedules store an explicit timezone. Use the timezone of the business event, not necessarily the timezone of the person configuring it. For example, a daily storefront report should normally follow the storefront's zone. A connected **Date & Time** value for **Schedule Workflow** represents one specific instant. If you build that value from text, include or intentionally convert its timezone before scheduling it. ## Verify scheduled work Scheduled runs appear with a scheduled status before they start. Use [Workflow runs](/essentials/workflow-runs) to inspect or cancel them. There is no generic Test Run button for schedules. For a recurring workflow, temporarily add a near-future schedule, enable the workflow, wait for one event, and remove the temporary recurrence after verification. Do not leave a high-frequency test schedule attached to a live workflow. # Service triggers Source: https://learn.workflow.dog/guides/service-triggers Start workflows from Gmail, Outlook, Google Forms, and TidyCal events. Service triggers watch an account in another product and create a workflow run when a matching event arrives. Configure the account and filters in the trigger panel; configure downstream service actions separately on their own nodes. ## Available service events | Service | Trigger | Configurable scope | | ------------ | -------------------- | ------------------------------------------------------------------------- | | Gmail | New Email | Google account and case-sensitive subject text | | Gmail | Sent Email | Google account, case-sensitive subject text, and automated email behavior | | Gmail | Label Added to Email | Google account and optional case-insensitive label name | | Outlook | New Email | Microsoft account and case-sensitive subject text | | Google Forms | Google Form Response | Google account and the form's editing URL | | TidyCal | New TidyCal Booking | TidyCal account | See the [Triggers reference](/reference/triggers) for the exact output fields from each event. ## Configure an account-backed trigger Select the trigger while creating the workflow. The editor opens its configuration automatically when setup is required. Choose a healthy account with the permissions required by that trigger. You can connect a new account directly from the selector. Add the available subject or label filter, or select the exact form. Start narrow; a broad inbox event can create many runs. Select **Save** and wait for the confirmation. WorkflowDog creates or updates the service watcher behind the trigger. Enable the workflow, then cause the event in the connected service. Inspect the resulting run before widening the filter. Account selection is project-scoped. The selector can use a healthy compatible default account automatically, but the saved trigger still monitors the specific account shown in its configuration. Use [Integrations](/essentials/integrations) to set defaults, reconnect an unhealthy account, see where an account is used, or replace it across nodes. ## Email filters and loops Gmail and Outlook subject filters match when the subject includes the entered text. The comparison is case-sensitive. Leave the field blank to accept every email for that event. The Gmail label trigger's label filter is case-insensitive. It reports labels that were newly added; it is not a query for all messages that already carry the label. By default, Gmail's **Sent Email** trigger ignores messages sent by WorkflowDog automations. Enabling **Trigger on automated emails?** includes them and can create an infinite loop if the workflow also sends email from the same account. Before allowing automated sent emails, draw the loop end to end. Add a strict filter or condition that guarantees an email produced by the workflow cannot trigger the same path indefinitely. ## Form and booking events For **Google Form Response**, paste the form URL shown while editing the form, not a response spreadsheet or unrelated sharing URL. Trigger data includes the response ID, respondent email when available, answers grouped by question, and quiz score when available. **New TidyCal Booking** monitors the selected account for newly created, non-cancelled bookings. It checks for new bookings on a one-minute interval, so a matching event may not appear immediately. Its outputs include booking time, timezone, contact details, meeting URL, booking type, and question answers. ## Test and troubleshoot There is no generic Test Run button. After the trigger is saved and the workflow is enabled, create a new matching event in the provider. If no run appears, verify: * the workflow is live, * the trigger panel shows the intended account, * the account is healthy and has the requested permissions, * capitalization matches a subject filter, * the label or form is the one the event actually used, and * enough time has passed for a polled service such as TidyCal. Continue with [Testing workflows](/guides/testing-workflows) and [Troubleshooting runs](/guides/troubleshooting-runs). For inbound URLs, webhooks, forms hosted by WorkflowDog, and email hooks, see [External triggers](/essentials/external-triggers). # Testing workflows Source: https://learn.workflow.dog/guides/testing-workflows Test a workflow with representative trigger data and verify each branch. Testing a workflow means sending a real event through its configured trigger, then inspecting what each action received and produced. WorkflowDog does not currently have a generic **Test Run** button. ## The test loop Finish the change, save any open trigger configuration, and wait until the editor header says **Saved!**. Sending an event earlier can start a run from the previous graph. A paused workflow does not accept new trigger events. Follow [Enable and pause](/essentials/enable-and-pause) if the workflow is not live. Cause the event the trigger is designed to receive. Use realistic values, including optional fields and attachments that matter to the automation. Open the workflow's runs, select the new run, and inspect trigger data, action outputs, and node errors. Deselect the historical run, edit the current graph, wait for **Saved**, and send another event. Compare the new result with the expected outcome. ## Send the right event | Trigger | Useful test event | | -------------------- | ----------------------------------------------------------------------- | | URL | Open its URL for a `GET`, or send the exact method and body you expect. | | Webhook | Send a `POST` with representative JSON. | | Form Submission | Submit the actual form, including a file if the workflow handles files. | | Gmail or Outlook | Send an email that matches the configured subject or label filter. | | Google Form Response | Submit the configured Google Form. | | TidyCal booking | Create a real test booking. | | Schedule | Temporarily use a near-future recurrence and wait for it to fire. | | Sub-Workflow | Run it from a parent workflow with a representative **Payload**. | For HTTP request formats and response behavior, see [HTTP endpoints and webhooks](/guides/http-webhooks). For provider account and filter setup, see [Service triggers](/guides/service-triggers). ## Inspect more than the final result A correct final value can hide a broken branch that happened not to affect this event. Check: * the **Data from Trigger** outputs, * each action that should have run, * values on output handles, * node-level errors, * branches intentionally skipped by conditions, and * side effects in the destination service. Actions on independent branches can run concurrently. Do not use their visual left-to-right order as evidence that one finished before the other. Add a data connection or **Wait For** dependency when order matters. Historical runs keep the graph snapshot used when they started. Use that snapshot to understand an old result; use the current graph for the next test. See [Workflow runs](/essentials/workflow-runs) and [Troubleshooting runs](/guides/troubleshooting-runs) for the detailed inspection workflow. ## Reuse an event after the first test After you have one representative run, **Rerun** can reuse its trigger payload against the workflow's current saved graph. This is useful when repeatedly tuning transformations or branch logic. Rerun repeats the stored trigger data; it does not recreate the external event. It may repeat side effects such as sending messages, creating rows, or calling APIs. Disable or isolate destructive actions before using it as a tight test loop. ## Test the unhappy paths Before relying on the workflow, send cases that exercise its boundaries: * a missing optional field, * an empty list, * a value in the wrong format, * a false condition, * an expired or disconnected service account, and * a downstream service error. An action error stops dependent actions from receiving its normal outputs, but independent branches can continue. Use [Meta controls](/building/meta-controls) when the workflow should recover, report, or clean up after a failed action. # Troubleshoot workflow runs Source: https://learn.workflow.dog/guides/troubleshooting-runs Find the cause of failed runs and node errors, fix the current workflow, and test safely. Start with the run's status and error location. A run-level **Failed** status and a node error inside a **Completed** run describe different problems and need different fixes. ## Diagnose the run Open **Workflow Runs** from the project, or open **Run History** inside the workflow editor and select the affected run. If the run is **Failed**, read the status tooltip for its run-level reason. If it is **Completed** with an amber warning, inspect the nodes that stored errors. Use **Snapshot (Read-Only)** to inspect the graph that actually executed. Do not assume the current canvas still matches an older run. Open the failed node's error and review upstream outputs. Confirm the input shape, account, identifiers, and values the node received. Switch to **Overlay** or deselect the run, make the correction, and wait until the editor says **Saved**. Choose **Re-run** to use the same trigger data with the current saved graph, or send a new representative trigger event. ## Run-level failures Run-level failures occur before node processing begins or when the workflow runner itself cannot complete its job. | Message or code | What to check | | --------------------------------------------------------------------------- | -------------------------------------------------------------------- | | **The workflow is paused.** | Enable the workflow, then create a new run. | | **The project is out of workflow runs and isn't set up for usage billing.** | Add credits or enable pay-as-you-go billing. | | **The payment is invalid.** | Resolve the project's payment issue in the billing portal. | | **The worker encountered an error.** | Re-run once; if it repeats, preserve the run ID and contact support. | A failed eligibility check is not retried automatically. Fix the cause, then send a new event or choose **Re-run**. A manual re-run goes through the same Live/Paused and billing checks as an external trigger event. ## Node errors in a Completed run WorkflowDog records node errors independently and continues settling the graph. The overall run can reach **Completed** even when one or more nodes failed. Check: * The failed node's exact stored message. * Whether its connected inputs produced values. * Whether a required static input is empty. * Whether an integration account is healthy and has the required permission. * Whether an external identifier still exists and belongs to that account. * Whether the value's type matches what the node accepts. Downstream nodes may not run when their required input path did not receive a value from the failed node. Diagnose the earliest error in the path first. ## Inspect the graph that actually ran This is the authoritative historical graph. Use it to confirm the node version, connections, static values, disabled nodes, and layout selected when the run was queued. This applies historical results to the current editable graph where IDs still match. Use it while implementing a fix, but switch back to Snapshot when you need to verify historical structure. If the workflow was deleted, the project can retain a **Deleted Workflow** run row for usage tracking while its snapshot is no longer available. ## Re-run safely Re-run copies the old run's trigger payload into a new run. It does not execute the old graph. Before re-running: * Confirm the editor shows **Saved**. * Confirm the workflow is Live. * Confirm integration accounts are healthy. * Consider whether the workflow sends messages, charges payments, creates records, or performs another non-idempotent action. * Check whether the original run partially completed before its node error. Re-running can repeat side effects that succeeded in the original run. A node error later in the graph does not roll back earlier emails, records, uploads, or provider changes. For risky workflows, temporarily disable side-effect nodes or route the payload through a test copy before replaying it. ## Integration errors When an account-backed node errors: Open **Integrations** and look for **Needs Reconnecting**. Open the node's account selector. Reauthorize the account if credentials are invalid or the node says required permissions are missing. Unhealthy or insufficiently scoped accounts can be cleared automatically from the node. Select the healthy account again. Confirm IDs, mailbox folders, labels, files, bases, tables, and other external resources still exist and are accessible to that account. For a trigger that stopped delivering events, continue with [External triggers](/essentials/external-triggers#troubleshooting). ## Variable errors For project variable problems: * A missing key returns its default or `null`; it is not a run-level failure. * Key matching is exact and project-scoped. * Appending requires the existing value to be a list. * Parallel append operations can overwrite one another because each operation reads and replaces the list. * Viewers can inspect values but only Editors can clear them. Inspect the current value under **Project → Variables** before changing the workflow. ## Scheduled runs A Scheduled run can be cancelled before execution. Pending and Running runs cannot be cancelled from the dashboard. If a delayed run executed after the workflow was paused, it was already accepted and scheduled before the pause. Pausing does not purge the delayed queue. ## Save failures The workflow editor shows **Waiting to save**, **Saving**, **Saved**, or **Failed to save**. Do not test a change until the status reaches **Saved**. WorkflowDog prevents normal navigation while a save is still pending, but a failed save means the current graph may not be on the server. A graph containing a circular dependency is rejected during save. Remove the cycle and wait for a successful save before re-running. ## Escalate a repeatable worker failure When **The worker encountered an error** repeats with the same saved graph and payload: 1. Star the representative run. 2. Record the workflow name, run date and time, and run ID from its URL or request data. 3. Note whether a new trigger event and a manual re-run fail the same way. 4. Contact WorkflowDog support without copying secrets into the message. The stored run gives support the execution context; the external account's credentials should never be pasted into a ticket. ## Quick symptom guide Verify the external trigger configuration, provider permissions, and account health. Then send a new matching event. A trigger filter mismatch can prevent WorkflowDog from producing a run. Read the run-level failure tooltip. Paused and billing failures happen before node execution. Look for an amber warning and inspect the earliest node error. Downstream nodes may not receive a signal after an upstream failure. Compare the saved trigger payload with the new event. Re-run preserves the old payload, which may reference an external resource that no longer exists or contain a value your new event does not. # Welcome to WorkflowDog Source: https://learn.workflow.dog/introduction Build automations by connecting triggers, actions, and data. WorkflowDog is a visual automation builder. A workflow starts with one **trigger**, passes data through connected **actions**, and records the result as a **run**. You can use workflows to receive webhooks, process email, update spreadsheets, call APIs, generate files, schedule work, run AI models, and connect those operations into one automation. Create a live HTTP endpoint and inspect its first run. Learn how triggers, actions, dependencies, and runs fit together. Add an external account, review its permissions, and see where it is used. Open the complete action and trigger reference. ## The core model ### Projects contain your automation system A project is the boundary around workflows, connected accounts, persistent variables, team access, run history, and billing. Data and accounts are scoped to a project, so choose the project before creating or connecting anything. ### A trigger starts each workflow Every workflow has one trigger. It might receive an HTTP request, observe a new email or form response, run on a schedule, or accept a call from another workflow. The trigger provides the first values in the graph. An incoming HTTP request, for example, can expose its method, path, query parameters, headers, body, and uploaded files. ### Actions run when their dependencies are ready Actions are nodes on the editor canvas. Connections carry values from outputs to inputs and establish execution dependencies. A workflow is not read from left to right or top to bottom. An action runs when the values it depends on are ready. Independent branches can run at the same time. ### Every execution becomes a run A run records the trigger data, status, node outputs, and node errors for one execution. Use Run History to understand what happened, inspect a historical snapshot, and rerun with the same trigger payload after making a change. ## A practical learning path Follow the [Quickstart](/quickstart) to receive a URL request, build a message, and return an HTTP response. Read [Connect data](/building/connect-data) before building larger graphs. It explains static and dynamic inputs, connections, lists, objects, and required values. Use [Meta controls](/building/meta-controls), [branching](/building/branching), [lists and loops](/building/lists-and-loops), and [sub-workflows](/building/sub-workflows) as the automation grows. Use [Testing workflows](/guides/testing-workflows) and [Run History](/essentials/workflow-runs) to inspect actual inputs, outputs, and errors. Understand [Live and Paused workflows](/essentials/enable-and-pause), account health, project variables, usage, and external-trigger lifecycle before relying on the automation in production. ## Find exact node behavior Guides explain how to design and operate automations. The reference documents the exact inputs, outputs, defaults, limits, and caveats of each node: * [Actions reference](/reference/actions) * [Triggers reference](/reference/triggers) The action picker also links directly to the matching reference page. # Quickstart Source: https://learn.workflow.dog/quickstart Build and run a live HTTP workflow in a few minutes. Build a workflow that receives a browser request and responds with a message containing the request method and path. The finished URL returns a message such as: ```text theme={null} Hello! You made a GET request to /. ``` ## Before you begin Sign in at [workflow.dog/login](https://workflow.dog/login). A new account starts with a project. If you already have several projects, select the one where this workflow should live. ## 1. Create a workflow Open **Workflows**, select **Create a Workflow**, and choose: **HTTP → When a request is received at a URL** WorkflowDog creates the workflow and opens its editor. The trigger panel shows the public URL assigned to this workflow. A workflow has one trigger. The trigger is chosen during creation, while actions are added on the canvas afterward. ## 2. Add a Text action Press / or select **Search actions** in the bottom toolbar. Search for **Text**, then choose: **Core → Text** Enter this template in the action: ```handlebars theme={null} Hello! You made a {{method}} request to {{path}}. ``` The Text action detects `method` and `path` and creates a dynamic input for each one. ## 3. Connect the trigger data The workflow includes **Trigger Data**, which exposes values from the incoming request. Create these two connections: | From | To | | ------------------------- | ----------------- | | **Trigger Data → Method** | **Text → method** | | **Trigger Data → Path** | **Text → path** | Drag from an output handle to its matching input handle. A connection carries the value and makes the Text action wait for that trigger output. If a handle is hard to find, select the node to read its field descriptions in the configuration panel. ## 4. Return the message Open the action search again and choose: **HTTP → Respond Text** Connect: | From | To | | --------------- | ----------------------- | | **Text → Text** | **Respond Text → Body** | The response action sends the generated text back to the browser request that started the workflow. ## 5. Wait for the workflow to save WorkflowDog saves graph changes automatically. Watch the status beside the workflow name and wait for **Saved!** before triggering a run. Triggering while the editor still says **Saving...** can run the previous saved graph. ## 6. Enable the workflow Open the **Paused** menu and choose **Enable Workflow**. The status changes to **Live**. New workflows begin paused. While paused, incoming events do not wait to be processed later; they produce failed runs. See [Live and Paused workflows](/essentials/enable-and-pause) for the full behavior. ## 7. Send a request Open the trigger panel at the top-left of the editor and select **Go to URL**. The page should display: ```text theme={null} Hello! You made a GET request to /. ``` Add a path or query string to the URL and reload to create another run. ## 8. Inspect the run Open **Run History** from the top-right of the editor. Select the latest run, then inspect the graph: * Trigger Data contains the HTTP method and path. * Text shows the rendered output. * Respond Text shows the response body it sent. Use **Snapshot (Read-Only)** when you need the graph exactly as it existed for that run. Learn more in [Workflow runs](/essentials/workflow-runs). ## What you learned You have used the complete automation lifecycle: 1. A trigger received an event. 2. Connections carried event values into an action. 3. An action produced a new value. 4. A response action completed the HTTP request. 5. Run History recorded the execution. Continue with [Connect data](/building/connect-data), or browse the exact [URL trigger](/reference/triggers/http/url), [Text action](/reference/actions/core/text), and [Respond Text action](/reference/actions/http/respond) behavior. # Route Incoming Email Source: https://learn.workflow.dog/recipes/email-routing Classify an incoming message and send it down the right workflow branch. Email routing combines a service trigger with deterministic filters, optional AI classification, and one branch per destination. A typical workflow normalizes each new message, classifies it or applies fixed rules, chooses a branch, then labels, drafts, forwards, replies, or notifies as appropriate. ## Start with the narrowest trigger Use a Gmail or Outlook new-email trigger and configure its built-in filters when possible. Trigger filters avoid creating runs for messages the automation will never process. Remember that subject matching can be case-sensitive. Test with the exact capitalization and message shapes that arrive in the real mailbox. ## Choose deterministic or AI routing Use deterministic text and logic actions when the rule can be stated exactly: * sender domain equals a known customer or vendor, * subject starts with a fixed prefix, * a label is present, * body contains a specific identifier. Use [OpenAI Chat](/reference/actions/openai/chat) with structured output when the distinction depends on meaning rather than a fixed phrase. Keep the schema small: ```json theme={null} { "type": "object", "properties": { "route": { "type": "string", "enum": ["sales", "support", "billing", "ignore"] }, "summary": { "type": "string" }, "urgent": { "type": "boolean" } }, "required": ["route", "summary", "urgent"], "additionalProperties": false } ``` Put hard safety rules before AI classification. For example, ignore your own automated senders and known newsletters before paying to classify the remaining messages. ## Build the branches Connect `route` to a case-selection action or compare it in separate branches: * `sales` can forward to the sales queue. * `support` can add a label and draft a reply. * `billing` can notify the billing team with the summary. * `ignore` can end without a side effect. Use [Conditional](/building/meta-controls) on side-effect actions so only the matching branch runs. Independent preparation branches can still run concurrently. ## Avoid mail loops A workflow that sends, forwards, or labels mail can trigger another email-based workflow—including itself. Filter automated senders, dedicated labels, or recognizable headers so generated messages do not loop. Before enabling: 1. Send representative messages for every route. 2. Confirm the trigger data contains the body and attachments you expect. 3. Inspect drafts before switching to automatic replies. 4. Test the fallback branch for ambiguous messages. 5. Review Run History for node errors even when a run status says completed. See [Service event triggers](/guides/service-triggers) for account and event lifecycle behavior. # Build an HTTP Endpoint Source: https://learn.workflow.dog/recipes/http-endpoint Receive an HTTP request, process its data, and return a controlled response. Use an HTTP-triggered workflow when another application needs to call your automation through a URL. Start with a URL, Webhook, or Form trigger; validate and transform the request data; perform the work; then return text, JSON, HTML, a file, a status, or a redirect. ## Choose the trigger | Trigger | Use it for | Request data | | ------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------- | | [URL](/reference/triggers/http/url) | General endpoints that accept common HTTP methods and text or binary bodies | Path, method, query, headers, body | | [Webhook](/reference/triggers/http/webhook) | Services that send a JSON `POST` webhook | Path, headers, parsed JSON body | | [Form](/reference/triggers/http/form) | Browser form submissions and optional hosted form HTML | Path, method, query, fields, files | The trigger is selected when you create the workflow. If the upstream service has a documented webhook format, use **Webhook**. Use **URL** for a custom API surface and **Form** for browser-submitted fields or uploads. ## Validate the incoming data Trigger Data exposes the request values. Treat all of them as untrusted. * Check required properties before using them. * Use type checks and conversion actions when a value may arrive as text. * Validate structured bodies with [Validate JSON Schema](/reference/actions/utilities/validate-json-schema). * Return a clear `4xx` response when the request cannot be processed. Do not place secrets in query parameters. URLs are commonly stored in browser, proxy, and service logs. Prefer a request header or body field when the sending service supports it. ## Return one response Add the response action that matches the endpoint contract: | Response action | Result | | -------------------------------------------------------- | ------------------------------------- | | [Respond Text](/reference/actions/http/respond) | Plain text with a configurable status | | [Respond JSON](/reference/actions/http/respond-json) | A JSON response body | | [Respond HTML](/reference/actions/http/respond-html) | Rendered HTML | | [Respond File](/reference/actions/http/respond-file) | A downloadable or inline file | | [Respond Status](/reference/actions/http/respond-status) | Status code without a body | | [Redirect](/reference/actions/http/redirect) | Redirect to another URL | Only response actions compatible with the selected trigger can be added. If several branches can respond, design them so one branch wins for each request. ## Example: create a JSON endpoint 1. Create a workflow with the **Webhook** trigger. 2. Read the parsed body from Trigger Data. 3. Validate the required fields. 4. Run the actions that process the request. 5. Build a result object. 6. Connect it to **Respond JSON**. 7. Wait for **Saved!**, enable the workflow, and send a representative `POST`. 8. Inspect the run and the caller's response. For an error branch, connect the validation result to a condition and return: ```json theme={null} { "ok": false, "error": "email is required" } ``` with status `400`. The success branch can return status `200` or `201`. ## Operate the endpoint * Keep the workflow **Live** while callers depend on it. * Watch [Run History](/essentials/workflow-runs) for failed requests and node errors. * Preserve a stable response shape when downstream applications parse it. * If you pause the workflow, new requests produce paused-workflow failures; they are not queued for later. See [HTTP and webhook triggers](/guides/http-webhooks) for payload limits, response timing, and the differences between the three trigger types. # Build a Scheduled Automation Source: https://learn.workflow.dog/recipes/scheduled-automation Run a workflow repeatedly or queue another workflow for a future time. WorkflowDog supports two scheduling patterns: | Pattern | Use | | --------------------------------------------------------------------- | ------------------------------------------------------------------------- | | [Schedule trigger](/reference/triggers/core/schedule) | Start this workflow on one or more recurring schedules. | | [Schedule Workflow action](/reference/actions/core/schedule-workflow) | Queue a separate callable workflow to run once at a future date and time. | Choose the trigger for recurring jobs such as a daily report. Choose the action for delayed work such as sending a follow-up two days after an event. ## Example: send a daily report Create a workflow with the **Schedule** trigger. Each run loads the reporting data, formats the summary, and sends the finished email or message. Add a daily schedule at the intended local time and confirm its timezone. A workflow can have multiple schedule entries. Add the actions that read the source system. Keep unrelated reads on independent branches when they can run concurrently. Combine the values into text, HTML, a spreadsheet, or a file. Use a sub-workflow when the same report logic is reused elsewhere. Add the send action, wait for the graph to save, enable the workflow, and inspect its next run in Run History. ## Example: schedule a one-time follow-up Create a second workflow with the [Callable trigger](/reference/triggers/core/callable). Give its trigger inputs the values the follow-up needs. In the first workflow: 1. Add **Schedule Workflow**. 2. Select the callable workflow. 3. Set the future date and time. 4. Connect the callable workflow's inputs. The scheduled execution appears in Run History. It already exists in the queue, so pausing the child workflow does not remove it. Cancel that scheduled run from history when it should no longer execute. A delayed run uses the child workflow's saved graph when it executes. Review scheduled work before making incompatible changes to the child's expected trigger data. ## Make schedules reliable * State the timezone explicitly; do not assume every teammate or service uses the same local time. * Design recurring work to tolerate being retried manually. * Avoid relying on one run's in-memory state. Store durable state in the destination service or a [project variable](/essentials/variables). * Add **Succeeded?** or **Error** meta outputs around critical delivery actions when a recovery branch is useful. See [Scheduling workflows](/guides/scheduling) for configuration details and [Workflow runs](/essentials/workflow-runs) for cancel and rerun behavior. # Use Structured AI Output Source: https://learn.workflow.dog/recipes/structured-ai Turn unstructured text or files into predictable fields for later actions. AI responses are easiest to automate when the model returns a small, schema-defined object instead of prose. A typical workflow sends a message, document, or image to **OpenAI Chat** with Structured Output enabled. The resulting typed properties can drive conditions, storage, and service actions. ## Design the schema around decisions Start from what later actions need. For an intake workflow, that might be: ```json theme={null} { "type": "object", "properties": { "summary": { "type": "string", "description": "One sentence describing the request" }, "category": { "type": "string", "enum": ["question", "bug", "billing"] }, "priority": { "type": "string", "enum": ["low", "normal", "high"] }, "customerEmail": { "type": ["string", "null"] } }, "required": ["summary", "category", "priority", "customerEmail"], "additionalProperties": false } ``` Use enums for values that control a branch. Use nullable fields when the source may legitimately omit a value. Avoid collecting fields no downstream action uses. ## Configure Chat 1. Add [OpenAI Chat](/reference/actions/openai/chat). 2. Connect the source text to **Prompt**. 3. Add images or PDFs under **Files** when the model must inspect them. 4. Turn on **Structured Output**. 5. Paste the JSON schema. 6. Expose the detected properties you need as outputs. Enabling Structured Output replaces the normal text **Response** with **Structured Response**. Review existing connections when changing this setting. ## Route and validate Connect enum outputs to conditions or case selection. Connect extracted text only to actions that accept missing or nullable values when the schema permits them. For high-impact work, add deterministic validation after the model: * check that an email address is valid, * confirm a number is in the allowed range, * require human review before sending or deleting, * reject categories outside the schema, * preserve the original source for audit and correction. ## Handle failure deliberately Enable the Chat action's **Succeeded?** and **Error** meta outputs. Use them to send failures to a recovery branch without treating invented fallback data as real extraction. A valid schema controls the response shape, not the truth of its contents. Treat model-produced values as untrusted whenever they can spend money, modify access, send external messages, or make irreversible changes. Use [Files and structured data](/building/files-and-structured-data) for downstream object and file handling, and [Troubleshoot workflow runs](/guides/troubleshooting-runs) when a model or provider request fails. # Create Record Source: https://learn.workflow.dog/reference/actions/airtable/create-record Create one Airtable record, including file attachments. The **Create Record** action adds one record to an Airtable table. Field names map directly to Airtable columns, and File values are uploaded to attachment fields after the record is created. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-write access to the base. | | **Base ID** | String | Yes | Airtable base identifier, typically beginning with `app`. | | **Table Name or ID** | String | Yes | Visible table name or ID, typically beginning with `tbl`. | | **Fields** | Object | No | Field-name/value pairs for the new record. | | **Type Cast?** | Boolean | No | Let Airtable convert values to field types. Defaults to on. | Add a File or list of Files as a field value to upload attachments to that field. The destination must be an Airtable attachment field. ## Outputs | Output | Type | Description | | ------------------ | ------ | ------------------------------------------------------ | | **Record ID** | String | ID of the new Airtable record. | | **Created Record** | Object | Fields returned by Airtable, including uploaded files. | Store **Record ID** whenever the workflow may update, retrieve, or delete the same record later. ## Troubleshooting Confirm the field name exists and its Airtable type accepts the supplied value. **Type Cast?** can convert common input forms but cannot repair every incompatible value. # Create Records Source: https://learn.workflow.dog/reference/actions/airtable/create-records Create multiple Airtable records, including file attachments. The **Create Records** action adds a list of records to one Airtable table. It automatically partitions the work into Airtable's 10-record API batches, so the input list can contain more than ten records. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-write access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or Airtable table ID. | | **Records** | List of objects | Yes | At least one record of field-name/value pairs. | | **Type Cast?** | Boolean | No | Let Airtable convert values to field types. Defaults to on. | File-valued fields are uploaded after each batch's records are created. ## Outputs **Created Records** contains one item per input record, in batch order: | Field | Type | Description | | ------------- | ------ | --------------------------------------------------- | | **Record ID** | String | ID assigned by Airtable. | | **Fields** | Object | Created fields, including uploaded attachment data. | A failure in a later batch does not undo records already created by earlier API requests. ## Example For a contact import, first normalize the source data into a list of Airtable field-name/value objects and connect that list to **Records**. After creation, repeat over **Created Records** and store each **Record ID** wherever the source contact is tracked. # Delete Records Source: https://learn.workflow.dog/reference/actions/airtable/delete-records Delete multiple records from an Airtable table. The **Delete Records** action permanently deletes records by ID. It groups larger lists into Airtable's 10-record delete batches. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | --------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-write access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or Airtable table ID. | | **Record IDs** | List of strings | Yes | Airtable record IDs to delete. | Record deletion is permanent and this action returns no output. A failure in a later batch does not restore records deleted by earlier requests. An empty Record IDs list performs no operation. # Find Records Source: https://learn.workflow.dog/reference/actions/airtable/find-records Find Airtable records using structured field comparisons. The **Find Records** action turns one or more field filters into an Airtable formula. Records must satisfy every filter. Use it when you want typed controls without writing Airtable formula syntax yourself. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | -------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-read access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or ID. | | **Filters** | List of filters | Yes | Field comparisons joined with Airtable `AND(...)`. | | **Sort Field** | String | No | Field used to order matches. | | **Sort Direction** | `asc` or `desc` | No | Sort direction. Defaults to `asc`; used with Sort Field. | Each filter includes **Field Name**, **Match Mode**, and, when needed, **Search Value**. ### Match modes | Mode | Airtable behavior | | ----------------------------------- | ---------------------------------------------------- | | **Equals** / **Does Not Equal** | Compare a field with text, number, or boolean input. | | **Is Empty** / **Is Not Empty** | Compare with `BLANK()`. | | **Contains** / **Does Not Contain** | Use Airtable's case-sensitive `FIND` function. | | **Matches Regex** | Use `REGEX_MATCH`. | | **Greater/Less Than** variants | Numeric comparisons. | | **Is True** / **Is False** | Compare with Airtable booleans. | | **Is Truthy** / **Is Falsy** | Combine blank and false checks. | ## Outputs | Output | Type | Description | | ----------- | --------------- | --------------------------------- | | **Records** | List of objects | Fields for every matching record. | | **Count** | Number | Number of records returned. | The action requests at most 1,000 records. Output objects contain fields but not Airtable record IDs. ## Example: active premium accounts Add two filters: * **Status** → **Equals** → `Active` * **Plan Value** → **Greater Than or Equal** → `1000` Then sort by **Plan Value** in descending order. ## Troubleshooting The generated formula uses Airtable's `FIND` function, whose text matching is case-sensitive. Field names are inserted exactly as supplied. Confirm the spelling and punctuation match Airtable. # Find Records by Formula Source: https://learn.workflow.dog/reference/actions/airtable/find-records-by-formula Find Airtable records with a native Airtable filter formula. The **Find Records by Formula** action passes a formula directly to Airtable and returns the field objects for records where the formula is truthy. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | -------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-read access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or ID. | | **Filter Formula** | String | Yes | Airtable formula used as `filterByFormula`. | | **Sort Field** | String | No | Field used to order matches. | | **Sort Direction** | `asc` or `desc` | No | Sort direction. Defaults to `asc`; used with Sort Field. | Example: ```text theme={null} AND({Status} = "Open", {Amount} > 1000) ``` ## Outputs | Output | Type | Description | | ----------- | --------------- | ---------------------------- | | **Records** | List of objects | Fields for matching records. | | **Count** | Number | Number of matches returned. | The action requests at most 1,000 matches and omits Airtable record IDs from each output object. ## Troubleshooting Test it in Airtable first. Field names with spaces need braces, text needs quotes, and function names must follow Airtable formula syntax. # Get Record Source: https://learn.workflow.dog/reference/actions/airtable/get-record Retrieve one Airtable record's fields by record ID. The **Get Record** action loads one record from an Airtable table. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-read access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or Airtable table ID. | | **Record ID** | String | Yes | Airtable record ID, usually starting `rec`. | ## Outputs | Output | Type | Description | | ---------- | ------ | -------------------------------------------------- | | **Record** | Object | Record fields keyed by their Airtable field names. | The output contains the fields object, not the Record ID or creation time. Keep the input ID if later steps need it. # Get Table Schema Source: https://learn.workflow.dog/reference/actions/airtable/get-table-schema Retrieve Airtable table metadata and field definitions. The **Get Table Schema** action reads a base's metadata, resolves one table by name or ID, and returns its field definitions. It requires Airtable schema-read permission rather than record-read permission. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ---------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with `schema.bases:read` access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Exact table name or Airtable table ID. | ## Outputs | Output | Type | Description | | -------------------- | -------------- | -------------------------------- | | **Name** | String | Table name. | | **Description** | String | Table description, when present. | | **Primary Field ID** | String | ID of the table's primary field. | | **Fields** | List of fields | Metadata for every table field. | Each **Fields** item contains: | Field | Type | Description | | --------------- | ------ | -------------------------------- | | **ID** | String | Airtable field ID. | | **Name** | String | Visible field name. | | **Type** | String | Airtable field type identifier. | | **Description** | String | Field description, when present. | ## Example: validate dynamic mappings Use **Fields** as the source for a repeat step, then compare each field's **Name** and **Type** with the mapping your workflow expects. Continue to the record creation or update step only after the required fields have been confirmed. ## Troubleshooting Matching uses the exact Airtable table ID or table name. Inspect the base and verify the connected account can read its schema. # Get All Records Source: https://learn.workflow.dog/reference/actions/airtable/list-records List Airtable records with optional view, formula, and sorting. The **Get All Records** action reads records from an Airtable table, follows offset pagination, and returns each record's fields. A view, formula, and single-field sort can narrow or order the result. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | -------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-read access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or ID. | | **View Name or ID** | String | No | Limit records to an Airtable view. | | **Filter Formula** | String | No | Airtable formula that records must satisfy. | | **Sort Field** | String | No | Field used to order results. | | **Sort Direction** | `asc` or `desc` | No | Sort direction. Defaults to `asc`; used with Sort Field. | View and formula filters are combined by Airtable when both are supplied. Test formulas in Airtable before placing them in a workflow. ## Outputs | Output | Type | Description | | ----------- | --------------- | --------------------------------------- | | **Records** | List of objects | Field objects for the returned records. | | **Count** | Number | Number of returned records. | The action requests at most 1,000 records and returns field objects without their Airtable record IDs. Use a dedicated ID field when downstream work must retain an identifier. ## Troubleshooting **Sort Direction** is sent only when **Sort Field** is also provided. Check that the field name exists in the table. # Update Record Source: https://learn.workflow.dog/reference/actions/airtable/update-record Merge into or replace one Airtable record. The **Update Record** action changes one Airtable record. Choose **Merge** to touch only supplied fields or **Replace** to replace the record's field set. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-write access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or ID. | | **Record ID** | String | Yes | Record to update. | | **Fields** | Object | Yes | Field-name/value pairs to write. | | **Update Method** | `merge` or `replace` | No | Update strategy. Defaults to `merge`. | | **Type Cast?** | Boolean | No | Let Airtable convert values to field types. Defaults to on. | Updates only the supplied regular fields. Existing omitted fields remain. Replaces the record with the supplied regular fields. Omitted fields can be cleared. File or File-list values are uploaded to their attachment fields after the regular-field update. **Replace** is destructive to omitted fields. Use **Merge** unless clearing the rest of the record is intentional. This action changes the record and returns no output. # Update Records Source: https://learn.workflow.dog/reference/actions/airtable/update-records Merge into or replace multiple Airtable records. The **Update Records** action applies updates to multiple record IDs. It sends updates in batches of ten and uploads file-valued fields after each batch. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------------- | -------- | --------------------------------------------------------- | | **Third-party account** | Airtable account | Yes | Account with record-write access. | | **Base ID** | String | Yes | Airtable base ID. | | **Table Name or ID** | String | Yes | Table name or ID. | | **Updates** | List of updates | Yes | Each item contains **Record ID** and a **Fields** object. | | **Update Method** | `merge` or `replace` | No | Strategy applied to every update. Defaults to `merge`. | | **Type Cast?** | Boolean | No | Let Airtable convert supplied values. Defaults to on. | **Merge** preserves omitted fields. **Replace** can clear every field omitted from each update object. The action returns no output and is not transactional across batches. If a later request fails, earlier record updates are not rolled back. # Append to List Source: https://learn.workflow.dog/reference/actions/arrays/append Add one or more items to the end of a list. **Append to List** preserves the existing order of a list, then adds each new item at the end. ## Inputs | Input | Type | Required | Description | | --------- | -------------- | -------- | ------------------------------------ | | **List** | List | No | The starting list. Defaults to `[]`. | | **Items** | Repeatable any | No | Items to append, in the order shown. | ## Output | Output | Type | Description | | ---------- | ---- | --------------------------------------------- | | **Result** | List | The original items followed by the new items. | For example, appending `3` and `4` to `[1, 2]` returns `[1, 2, 3, 4]`. # Create List Source: https://learn.workflow.dog/reference/actions/arrays/build Combine individual values into a new list. **Create List** collects its repeatable item inputs into one list. Use it when separate values need to travel through the workflow as a single collection. ## Inputs | Input | Type | Required | Description | | --------- | -------------- | -------- | -------------------------------------------------- | | **Items** | Repeatable any | No | Values to include. The node starts with two slots. | ## Output | Output | Type | Description | | -------- | ---- | ----------------------------------------- | | **List** | List | Every supplied item, in input-slot order. | Add or remove item slots as needed. With no items, the action returns an empty list. # Chunk List Source: https://learn.workflow.dog/reference/actions/arrays/chunk Split a list into smaller lists of a fixed maximum size. **Chunk List** divides a list from left to right. The final chunk can contain fewer items than the requested size. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------------------------------- | | **List** | List | No | The list to split. Defaults to `[]`. | | **Size** | Number | Yes | A positive whole number of items per chunk. | ## Output | Output | Type | Description | | ---------- | ------------- | ------------------------------------ | | **Chunks** | List of lists | The chunks, in their original order. | For example, chunking `[1, 2, 3, 4, 5]` with a size of `2` returns `[[1, 2], [3, 4], [5]]`. **Size** must be a whole number greater than zero. # Empty List Source: https://learn.workflow.dog/reference/actions/arrays/empty-array Produce a list containing no items. **Empty List** is a compact value node with no inputs. ## Output | Output | Type | Description | | -------- | ---- | -------------------- | | **List** | List | An empty list: `[]`. | Use it to initialize a list input or explicitly represent “no items.” # Filter With Workflow Source: https://learn.workflow.dog/reference/actions/arrays/filter-with-workflow Keep the list items for which another workflow returns a truthy value. **Filter With Workflow** runs a selected workflow once for each input item and keeps the items whose run returns a truthy **Data Out** value. ## Quick start Give the workflow a **Data In** input and return the decision through **Data Out**. The decision is converted to true or false by truthiness. Choose that workflow, then connect a list to **Payloads**. Connect **Results** to the next action. ## Inputs | Input | Type | Required | Description | | --------------------- | -------- | -------- | --------------------------------------------- | | **Selected Workflow** | Workflow | Yes | The workflow used to test each item. | | **Payloads** | List | No | Items to test, up to 1,000. Defaults to `[]`. | ## Output | Output | Type | Description | | ----------- | ---- | --------------------------------------------- | | **Results** | List | Passing items in the same order as the input. | The predicate runs sequentially. If any child workflow fails, this action fails instead of returning a partial list. The selected workflow receives the current item as **Data In**. Values such as non-empty strings and non-zero numbers pass because the returned value is evaluated by truthiness, not required to be a Boolean. # Find With Workflow Source: https://learn.workflow.dog/reference/actions/arrays/find-with-workflow Return the first list item accepted by another workflow. **Find With Workflow** tests items from the beginning of a list and stops as soon as the selected workflow returns a truthy **Data Out** value. ## Inputs | Input | Type | Required | Description | | --------------------- | -------- | -------- | ----------------------------------------------- | | **Selected Workflow** | Workflow | Yes | The workflow used to test each item. | | **Payloads** | List | No | Items to search, up to 1,000. Defaults to `[]`. | ## Output | Output | Type | Description | | ---------- | ---- | ------------------------------------------------- | | **Result** | Any | The first matching item, or `null` if none match. | The selected workflow receives each candidate as **Data In**. A failed child run fails the action; later candidates are not tested after a match. Use **Filter With Workflow** when you need every matching item. Use this action when only the first match matters. # Flatten List Source: https://learn.workflow.dog/reference/actions/arrays/flatten Combine nested lists into a single list. **Flatten List** removes one level of nesting by default, or all nested levels when deep flattening is enabled. ## Inputs | Input | Type | Required | Description | | -------- | ------- | -------- | -------------------------------------------- | | **List** | List | No | The list to flatten. Defaults to `[]`. | | **Deep** | Boolean | No | Flatten every nested level. Defaults to off. | ## Output | Output | Type | Description | | ------------- | ---- | ------------------- | | **Flattened** | List | The flattened list. | With **Deep** off, `[[1], [[2]]]` becomes `[1, [2]]`. With it on, the same input becomes `[1, 2]`. # Get First Item Source: https://learn.workflow.dog/reference/actions/arrays/get-first-item Return the item at the beginning of a list. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ---------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | ## Output | Output | Type | Description | | -------------- | ---- | -------------------------------------------- | | **First Item** | Any | The first item, or `null` for an empty list. | The input list is not changed. # Get Items by Index Source: https://learn.workflow.dog/reference/actions/arrays/get-items Expose selected list positions as individual outputs. **Get Items by Index** creates one output for each repeatable index input. List positions start at zero. ## Inputs | Input | Type | Required | Description | | ----------- | ----------------- | -------- | ----------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | | **Indices** | Repeatable number | No | Whole-number positions to retrieve. | ## Outputs Each **Index** slot creates a matching **Item at Index *n*** output. The output keeps the identity of its input slot, so reordering or removing index slots updates the corresponding outputs. Negative indices count backward from the end: `-1` retrieves the last item. An index outside the list produces no value for that output. # Get Last Item Source: https://learn.workflow.dog/reference/actions/arrays/get-last-item Return the item at the end of a list. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ---------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | ## Output | Output | Type | Description | | ------------- | ---- | ------------------------------------------- | | **Last Item** | Any | The last item, or `null` for an empty list. | The input list is not changed. # Insert at Index Source: https://learn.workflow.dog/reference/actions/arrays/insert-at-index Insert one or more items at a chosen list position. **Insert at Index** places new items at a zero-based position and returns the resulting list. ## Inputs | Input | Type | Required | Description | | --------- | -------------- | -------- | ------------------------------------------- | | **List** | List | No | The starting list. | | **Items** | Repeatable any | No | Items to insert, in the order shown. | | **Index** | Number | Yes | The zero-based position at which to insert. | ## Output | Output | Type | Description | | ---------- | ---- | --------------------------------- | | **Result** | List | The list with the items inserted. | For example, inserting `b` and `c` at index `1` in `[a, d]` produces `[a, b, c, d]`. This action is visible in the workflow editor, but the current server package does not include a matching implementation. # Is List? Source: https://learn.workflow.dog/reference/actions/arrays/is-array Check whether a value is a list. ## Input | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | ## Output | Output | Type | Description | | ---------- | ------- | ----------------------------------------------- | | **Result** | Boolean | `true` for a list; `false` for any other value. | Objects, strings, and `null` are not lists. # Join Lists Source: https://learn.workflow.dog/reference/actions/arrays/join Concatenate multiple lists into one. **Join Lists** adds the contents of each input list to the result in order. It removes only the outer list boundary; nested lists inside an input remain nested. ## Input | Input | Type | Required | Description | | --------- | --------------- | -------- | ---------------------------------------------- | | **Lists** | Repeatable list | No | Lists to join. The node starts with two slots. | ## Output | Output | Type | Description | | ---------- | ---- | ------------------------------------ | | **Joined** | List | All input items in input-list order. | Joining `[1, 2]`, `[]`, and `[3]` returns `[1, 2, 3]`. # Get Length Source: https://learn.workflow.dog/reference/actions/arrays/length Count the number of items in a list. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ------------------------------------ | | **List** | List | No | The list to count. Defaults to `[]`. | ## Output | Output | Type | Description | | ---------- | ------ | ------------------------------ | | **Length** | Number | The number of top-level items. | Nested lists count as one item each. # List Contains Source: https://learn.workflow.dog/reference/actions/arrays/list-contains Check whether a list contains a value. ## Inputs | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------------------------- | | **List** | List | No | The list to search. Defaults to `[]`. | | **Value** | Any | No | The value to find. | ## Output | Output | Type | Description | | ---------- | ------- | ----------------------------------------- | | **Result** | Boolean | `true` when the value occurs in the list. | The comparison is exact. Objects and lists match only when they are the same runtime value; two separate objects with identical properties do not match. # Prepend to List Source: https://learn.workflow.dog/reference/actions/arrays/prepend Add one or more items to the beginning of a list. **Prepend to List** puts the new items first, preserving the order of both the new items and the original list. ## Inputs | Input | Type | Required | Description | | --------- | -------------- | -------- | ------------------------------ | | **List** | List | No | The existing list. | | **Items** | Repeatable any | No | Items to add at the beginning. | ## Output | Output | Type | Description | | ---------- | ---- | ----------------------------------- | | **Result** | List | The new items followed by the list. | For example, prepending `1` and `2` to `[3, 4]` produces `[1, 2, 3, 4]`. This action is visible in the workflow editor, but the current server package does not include a matching implementation. # Create Range Source: https://learn.workflow.dog/reference/actions/arrays/range Create a regularly spaced list of numbers. **Create Range** starts at one number and adds a step until it reaches the end boundary. ## Inputs | Input | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------ | | **Start** | Number | No | First number. Defaults to `0`. | | **End** | Number | Yes | End boundary. | | **Step** | Number | No | Amount added per item. Defaults to `1`. | | **Inclusive** | Boolean | No | Include the end boundary. Defaults to off. | ## Output | Output | Type | Description | | -------- | --------------- | ------------------------------- | | **List** | List of numbers | Numbers in the generated range. | With **Start** `0`, **End** `5`, and **Step** `2`, the result is `[0, 2, 4]`. Turning on **Inclusive** adds one more stepped value. Use a positive step for an end greater than the start and a negative step for an end less than the start. A zero step or a step pointed away from the end cannot produce a valid range. When **Inclusive** is on and the step does not land exactly on **End**, the extra value can pass the end boundary. # Repeat Elements Source: https://learn.workflow.dog/reference/actions/arrays/repeat Repeat a sequence of list items a chosen number of times. ## Inputs | Input | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------- | | **Elements** | List | No | The sequence to repeat. Defaults to `[]`. | | **Count** | Number | Yes | A non-negative whole number of repetitions. | ## Output | Output | Type | Description | | -------- | ---- | ---------------------------- | | **List** | List | The repeated input sequence. | For example, repeating `[a, b]` three times returns `[a, b, a, b, a, b]`. A count of `0` returns an empty list. # Reverse List Source: https://learn.workflow.dog/reference/actions/arrays/reverse Return a list with its item order reversed. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ---------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | ## Output | Output | Type | Description | | ------------ | ---- | --------------------------------- | | **Reversed** | List | A new list in the opposite order. | `[a, b, c]` becomes `[c, b, a]`. The source list is not modified. # Shuffle List Source: https://learn.workflow.dog/reference/actions/arrays/shuffle Randomly reorder the items in a list. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ---------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | ## Output | Output | Type | Description | | ------------ | ---- | -------------------------------------- | | **Shuffled** | List | A randomly reordered copy of the list. | Every item appears exactly once, but the order may differ on each run. A shuffle can occasionally return the original order, especially for short lists. # Slice List Source: https://learn.workflow.dog/reference/actions/arrays/slice Extract a section of a list by position. **Slice List** returns items from the start index up to, but not including, the end index. ## Inputs | Input | Type | Required | Description | | --------- | ------ | -------- | --------------------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | | **Start** | Number | No | Inclusive, zero-based start. Defaults to `0`. | | **End** | Number | No | Exclusive end. Defaults to the list length. | ## Output | Output | Type | Description | | --------- | ---- | --------------------------------- | | **Slice** | List | The selected portion of the list. | For `[a, b, c, d]`, start `1` and end `3` return `[b, c]`. Although the editor description mentions negative indices, the server currently accepts only non-negative whole numbers for **Start** and **End**. # Sort List Source: https://learn.workflow.dog/reference/actions/arrays/sort Sort numbers, strings, or object properties. **Sort List** returns a sorted copy of the input. It can compare top-level values or a nested property selected by an object path. ## Inputs | Input | Type | Required | Description | | --------------- | ------ | -------- | --------------------------------------------- | | **List** | List | No | Values to sort. Defaults to `[]`. | | **Direction** | String | Yes | **Ascending** (default) or **Descending**. | | **Object Path** | String | No | Nested property such as `user.name` or `age`. | ## Output | Output | Type | Description | | ---------- | ---- | --------------------------- | | **Sorted** | List | A sorted copy of the input. | Numbers are compared numerically and strings use locale-aware text ordering. When **Object Path** is set, those same rules apply to the value at that path. Items whose compared values are not both numbers or both strings compare as equal, so their relative positions are preserved. # Get Unique Items Source: https://learn.workflow.dog/reference/actions/arrays/unique Remove duplicate values while keeping their first occurrence. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | ---------------------------------- | | **List** | List | No | The source list. Defaults to `[]`. | ## Output | Output | Type | Description | | ---------- | ---- | ----------------------------------- | | **Unique** | List | The first occurrence of each value. | Primitive values such as strings and numbers are deduplicated by value. Objects and nested lists are duplicates only when they refer to the same runtime value. # Zip Lists Source: https://learn.workflow.dog/reference/actions/arrays/zip Combine matching positions from multiple lists. **Zip Lists** groups the first item from every input list, then the second item from every list, and so on. The result is as long as the longest input; missing positions become `null`. ## Inputs | Input | Type | Required | Description | | ------------------------------- | --------------- | -------- | ------------------------------------------- | | **Name Lists with Object Keys** | Boolean | No | Return objects instead of positional lists. | | **Lists** | Repeatable list | No | Lists to combine. Starts with two slots. | When naming is enabled, every list entry has a **Key** and **List** input. Each output item is an object whose properties use those keys. ## Output | Output | Type | Description | | ---------- | ---- | --------------------------------------- | | **Zipped** | List | Positionally combined lists or objects. | Zipping `[1, 2]` and `["a"]` returns `[[1, "a"], [2, null]]`. Naming the same lists `id` and `label` returns `[{"id": 1, "label": "a"}, {"id": 2, "label": null}]`. Toggling **Name Lists with Object Keys** replaces the list-input shape and changes each output item from a list to an object. Check downstream connections after changing it. # Activate Email Template Source: https://learn.workflow.dog/reference/actions/brevo/activate-email-template Make an existing Brevo email template active. **Activate Email Template** sets an existing Brevo template's active state to true. | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | -------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used for the update. | | **Template ID** | Positive number | Yes | The Brevo template to activate. | The action has no output. Continue the workflow after Brevo confirms the template was updated. # Add Contacts to List Source: https://learn.workflow.dog/reference/actions/brevo/add-contacts-to-list Add existing Brevo contacts to a contact list by email. **Add Contacts to List** adds one or more existing contacts to a Brevo contact list. Brevo reports individual addresses that succeed or fail. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------- | | **Third-party account** | Brevo account | Yes | The Brevo account that owns the contact list. | | **Contact List ID** | Number | Yes | The destination contact list. | | **Emails** | List of emails | Yes | Existing Brevo contacts to add. | ## Outputs | Output | Type | Description | | --------------------- | -------------- | ----------------------------------------- | | **Successful Emails** | List of emails | Contacts Brevo added to the list. | | **Failed Emails** | List of emails | Contacts Brevo could not add to the list. | This action does not create missing contacts. Use **Upsert Contact** before this action when an address may not exist in Brevo. # Create Email Template Source: https://learn.workflow.dog/reference/actions/brevo/create-email-template Create an HTML transactional email template in Brevo. **Create Email Template** creates a reusable Brevo template with its sender, subject, and HTML content. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------- | -------- | ------------------------------------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used to create the template. | | **Template Name** | String | Yes | A non-empty name visible in Brevo. | | **Subject** | String | Yes | A non-empty email subject. | | **HTML Content** | String | Yes | A non-empty HTML body. | | **Sender Email** | String | Yes | The address shown as the sender. | | **Sender Name** | String | No | The display name shown with the sender address. | | **Is Active** | Boolean | No | Whether the template can be used immediately. Defaults to on. | ## Output | Output | Type | Description | | --------------- | ------ | ------------------------- | | **Template ID** | Number | The ID assigned by Brevo. | Store **Template ID** if a later workflow will activate, deactivate, or send from this template. # Deactivate Email Template Source: https://learn.workflow.dog/reference/actions/brevo/deactivate-email-template Make an existing Brevo email template inactive. **Deactivate Email Template** sets an existing Brevo template's active state to false. The template remains in the account and can be activated again later. | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | --------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used for the update. | | **Template ID** | Positive number | Yes | The Brevo template to deactivate. | The action has no output. # Get Contact Lists Source: https://learn.workflow.dog/reference/actions/brevo/get-contact-lists List contact lists in a Brevo account. **Get Contact Lists** retrieves one page of contact lists from Brevo. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------- | -------- | ------------------------------------------------ | | **Third-party account** | Brevo account | Yes | The Brevo account to inspect. | | **Limit** | Number | No | Lists to return, from 0 to 50. Defaults to 50. | | **Offset** | Number | No | Lists to skip. Defaults to 0. | | **Sort** | Choice | No | Sort by creation time. Defaults to newest first. | ## Outputs | Output | Type | Description | | --------- | --------------- | --------------------------------------------- | | **Lists** | List of objects | The requested page of Brevo contact lists. | | **Count** | Number | Total contact lists in the connected account. | Each list exposes **List ID**, **Name**, **Folder ID**, and **Unique Subscribers**. If **Count** exceeds **Limit**, increase **Offset** in another action to retrieve the next page. # Get Sent Email Content Source: https://learn.workflow.dog/reference/actions/brevo/get-email-content Retrieve a sent Brevo transactional email by message ID. **Get Sent Email Content** retrieves the recipient, subject, HTML body, and timestamp for a previously sent transactional email. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------- | -------- | ----------------------------------------------------------------------------------------- | | **Third-party account** | Brevo account | Yes | The account that sent the email. | | **Message ID** | String | Yes | A Brevo message ID from a send action or email logs. A Brevo email UUID is also accepted. | ## Outputs | Output | Type | Description | | ---------------- | ------ | ---------------------------- | | **Recipient** | String | The recipient email address. | | **Subject** | String | The sent subject line. | | **HTML Content** | String | The sent message body. | | **Date** | Date | When the email was sent. | When given a message ID rather than a UUID, WorkflowDog first looks up the matching email record and then retrieves its content. # Get Email Templates Source: https://learn.workflow.dog/reference/actions/brevo/get-email-templates List Brevo transactional email templates. **Get Email Templates** retrieves up to 250 templates from a Brevo account. ## Inputs | Input | Type | Required | Description | | --------------------------------- | ------------- | -------- | ------------------------------------------- | | **Third-party account** | Brevo account | Yes | The account to inspect. | | **Only Include Active Templates** | Boolean | No | Exclude inactive templates. Defaults to on. | ## Outputs | Output | Type | Description | | ------------- | --------------- | ------------------------------------- | | **Templates** | List of objects | The returned templates. | | **Count** | Number | Brevo's total count for the response. | Each template exposes **Template ID**, **Template Name**, **Subject**, **Sender Name**, **Sender Email**, **Reply To**, **Is Active**, **HTML Content**, **Created At**, and **Modified At**. The action requests a maximum of 250 templates. Accounts with more templates may need narrower organization outside this action. # Remove Contacts from List Source: https://learn.workflow.dog/reference/actions/brevo/remove-contacts-from-list Remove Brevo contacts from a contact list by email. **Remove Contacts from List** removes one or more contacts from a Brevo contact list. It does not delete the contacts from the Brevo account. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------- | | **Third-party account** | Brevo account | Yes | The Brevo account that owns the contact list. | | **Contact List ID** | Number | Yes | The contact list to update. | | **Emails** | List of emails | Yes | Contacts to remove from the list. | ## Outputs | Output | Type | Description | | --------------------- | -------------- | ---------------------------------------------- | | **Successful Emails** | List of emails | Contacts Brevo removed from the list. | | **Failed Emails** | List of emails | Contacts Brevo could not remove from the list. | # Send Email from Template Source: https://learn.workflow.dog/reference/actions/brevo/send-email-from-template Send a Brevo transactional email from an existing template. **Send Email from Template** uses a Brevo template and optional parameter values to send to one or more recipients. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------------------ | -------- | ----------------------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used to send. | | **Template ID** | Non-negative integer | Yes | The Brevo template to use. | | **Recipients** | List of emails | Yes | One or more destination addresses. | | **CC** | List of emails | No | Carbon-copy recipients. | | **Parameters** | List of name/value pairs | No | Values made available to template placeholders. | For a parameter named `FIRSTNAME`, use the following placeholder in Brevo: ```text theme={null} {{params.FIRSTNAME}} ``` ## Output | Output | Type | Description | | -------------- | ------ | -------------------------------- | | **Message ID** | String | Brevo's identifier for the send. | Keep parameter names stable and match their capitalization exactly between the template and the workflow. # Send Email Source: https://learn.workflow.dog/reference/actions/brevo/send-transactional-email Send a custom transactional email through Brevo. Brevo **Send Email** sends custom HTML with an optional plain-text alternative, CC recipients, reply-to address, and file or URL attachments. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used to send. | | **Recipients** | List of emails | Yes | One or more destination addresses. | | **CC** | List of emails | No | Carbon-copy recipients. | | **Subject** | String | Yes | A non-empty subject line. | | **HTML Content** | String | Yes | The HTML message body. | | **Text Content** | String | No | A plain-text alternative. | | **Sender Email** | String | Yes | The address shown as the sender. | | **Sender Name** | String | No | The sender display name. | | **Reply To** | String | No | The address that receives replies. | | **Attachment Files** | List of files | No | Workflow files encoded and uploaded with the email. | | **Attachment URLs** | List of URLs | No | Public files Brevo should fetch and attach. | URL attachments use the last part of the URL path as their filename. ## Output | Output | Type | Description | | -------------- | ------ | -------------------------------- | | **Message ID** | String | Brevo's identifier for the send. | Supply **Text Content** for clients that cannot render HTML and for better accessibility. Keep attachment URLs public for as long as Brevo needs to fetch them. # Send Transactional SMS Source: https://learn.workflow.dog/reference/actions/brevo/send-transactional-sms Send a non-promotional SMS message through Brevo. **Send Transactional SMS** sends an operational text message such as a confirmation, alert, or one-time code. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------- | -------- | --------------------------------------------------------------------------------- | | **Third-party account** | Brevo account | Yes | The API key used to send. | | **Recipient** | String | Yes | Phone number with country code and 6 to 15 digits. | | **Sender** | String | Yes | Up to 11 letters or digits, or up to 15 digits. | | **Content** | String | Yes | The text message to send. | | **Tags** | List of text | No | Up to 10 Brevo reporting tags. | | **Unicode Enabled** | Boolean | No | Enable accented characters, non-Latin scripts, and emoji. | | **Organization Prefix** | String | No | A brand prefix added before the message; it counts toward the SMS segment length. | | **Webhook URL** | URL | No | URL that receives Brevo delivery events for this message. | ## Output | Output | Type | Description | | -------------- | ------ | --------------------------------------- | | **Message ID** | String | Brevo's identifier for the SMS request. | Use this action only for transactional messages. Brevo automatically reclassifies content containing an opt-out stop code as marketing SMS, which can make the message subject to regional sending restrictions. Message content plus the optional **Organization Prefix** counts toward the 160-character segment limit. Longer messages may be split and consume multiple credits. Unicode messages can have a lower per-message character limit. # Upsert Contact Source: https://learn.workflow.dog/reference/actions/brevo/upsert-contact Create or update a Brevo contact by email. **Upsert Contact** creates a contact or updates the existing contact with the same email address. It can set account-defined attributes, add the contact to lists, and change email or SMS blocklist status. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------- | | **Third-party account** | Brevo account | Yes | The Brevo account that owns the contact. | | **Email** | Email | Yes | The address that identifies the contact. | | **Attributes** | Object | No | Account-defined contact attributes and their values. | | **Contact List IDs** | List of numbers | No | Lists to add the contact to. | | **Email Blocklisted** | Boolean | No | Block or allow marketing email for the contact when provided. | | **SMS Blocklisted** | Boolean | No | Block or allow SMS messages for the contact when provided. | ## Output | Output | Type | Description | | -------------- | ------ | ------------------------------------------------------ | | **Contact ID** | Number | Brevo's identifier for the created or updated contact. | Attribute names must already exist in the connected Brevo account. Workflow Dog converts them to uppercase before sending them, so `firstname` becomes `FIRSTNAME`. Brevo may ignore values that do not match the configured attribute type. # Get Page Content Source: https://learn.workflow.dog/reference/actions/cloudflare/content Render a URL with Cloudflare Browser Rendering and return HTML, Markdown, JSON, or a PDF. **Get Page Content** loads a public URL in a browser operated by Cloudflare and returns the page in the format you choose. It is useful when a normal HTTP request is not enough because the page depends on JavaScript. ## Inputs | Input | Type | Required | Description | | ----------------------------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------- | | **Third-party account** | Cloudflare account | Yes | The Cloudflare account and API credentials used for browser rendering. | | **URL** | String | Yes | The complete page URL to render. | | **Format** | `HTML`, `Markdown`, `JSON`, or `PDF` | Yes | Controls both the rendering endpoint and the node's output. Defaults to `HTML`. | | **Prompt Or Schema** | String | No | For `JSON` only. A JSON schema or natural-language prompt that describes the data to extract. | | **Wait For Selector** | String | No | A CSS selector that must appear before Cloudflare captures the result. | | **Wait Time** | Number | No | Extra time to wait after the page loads, from `0` to `30000` milliseconds. | | **Viewport Width** | Number | No | Browser viewport width, up to `1920`. Defaults to `1920`. | | **Viewport Height** | Number | No | Browser viewport height, up to `1080`. Defaults to `1080`. | | **JavaScript Code** | String | No | JavaScript inserted into the rendered page as a script. | | **Additional API Parameters** | Object | No | Extra fields passed to Cloudflare's Browser Rendering API. | When **Format** is `JSON`, the node first tries to parse **Prompt Or Schema** as JSON. Valid JSON is sent as a JSON schema; any other string is sent as an extraction prompt. JavaScript Code runs inside the remote page. Only use code and input values you trust, and do not place secrets in code that the page could read. ## Outputs The selected format changes which output is available: | Format | Output | Type | Description | | ---------- | ------------ | ------ | --------------------------------------- | | `HTML` | **Content** | String | Rendered page HTML. | | `Markdown` | **Content** | String | Page content converted to Markdown. | | `JSON` | **Data** | Object | Structured data returned by Cloudflare. | | `PDF` | **PDF File** | File | A PDF named after the page's hostname. | ## Example: extract product data Choose `JSON`, then set **Prompt Or Schema** to a schema such as: ```json theme={null} { "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "string" }, "inStock": { "type": "boolean" } }, "required": ["name", "price"] } ``` If the page renders its product card asynchronously, set **Wait For Selector** to the product card's CSS selector before extracting it. ## Troubleshooting Wait for a stable CSS selector, or add a short **Wait Time**. A selector is usually more reliable than a fixed delay on pages with variable load times. Confirm that **Prompt Or Schema** is valid JSON. If parsing fails, the node treats the entire value as a natural-language prompt. Match the page's expected viewport, then use **JavaScript Code** or **Additional API Parameters** for site-specific browser behavior. # HTML to PDF Source: https://learn.workflow.dog/reference/actions/cloudflare/html-to-pdf Render an HTML document as a PDF with Cloudflare Browser Rendering. **HTML to PDF** renders an HTML string in Cloudflare's remote browser and returns the result as a PDF file. Use it for invoices, reports, certificates, and other documents assembled earlier in a workflow. ## Inputs | Input | Type | Required | Description | | ----------------------------- | ------------------ | -------- | --------------------------------------------------------------------- | | **Third-party account** | Cloudflare account | Yes | The Cloudflare account used to render the document. | | **HTML** | String | Yes | The complete HTML document or fragment to render. | | **Wait For Selector** | String | No | A CSS selector that must appear before the PDF is captured. | | **Wait Time** | Number | No | Extra time to wait after rendering, from `0` to `30000` milliseconds. | | **Viewport Width** | Number | No | Browser viewport width, up to `1920`. Defaults to `1920`. | | **Viewport Height** | Number | No | Browser viewport height, up to `1080`. Defaults to `1080`. | | **JavaScript Code** | String | No | JavaScript inserted into the rendered document. | | **Additional API Parameters** | Object | No | Extra Browser Rendering API fields, such as PDF-specific options. | ## Output | Output | Type | Description | | ------------ | ---- | --------------------------------- | | **PDF File** | File | The rendered `page.pdf` document. | Put print-specific rules in the HTML with `@media print`. Page size, margins, headers, and footers can be supplied through **Additional API Parameters** when supported by Cloudflare's PDF endpoint. External stylesheets, fonts, and images must be reachable from Cloudflare's browser. For the most portable document, use absolute URLs or embed the assets directly in the HTML. ## Troubleshooting Replace local and relative asset paths with public absolute URLs, or embed the asset in the HTML. The remote browser cannot access files on your computer or private network. Set **Wait For Selector** to an element created after rendering finishes, or add a small **Wait Time**. # HTML to Screenshot Source: https://learn.workflow.dog/reference/actions/cloudflare/html-to-screenshot Render HTML and capture it as a PNG, JPEG, or WebP image. **HTML to Screenshot** turns an HTML string into an image using Cloudflare Browser Rendering. It can capture either the configured viewport or the full height of the rendered document. ## Inputs | Input | Type | Required | Description | | ----------------------------- | ------------------------ | -------- | ------------------------------------------------------------------------- | | **Third-party account** | Cloudflare account | Yes | The Cloudflare account used for rendering. | | **HTML** | String | Yes | The HTML to render. | | **Format** | `png`, `jpeg`, or `webp` | Yes | Image encoding. Defaults to `png`. | | **Full Page** | Boolean | No | Captures the full document instead of only the viewport. Defaults to off. | | **Wait For Selector** | String | No | A CSS selector that must appear before capture. | | **Wait Time** | Number | No | Extra delay after load, from `0` to `30000` milliseconds. | | **Viewport Width** | Number | No | Viewport width, up to `1920`. Defaults to `1920`. | | **Viewport Height** | Number | No | Viewport height, up to `1080`. Defaults to `1080`. | | **JavaScript Code** | String | No | JavaScript inserted into the rendered HTML before capture. | | **Additional API Parameters** | Object | No | Extra fields passed to Cloudflare's screenshot endpoint. | ## Output | Output | Type | Description | | -------------- | ---- | -------------------------------------------------------------------------- | | **Screenshot** | File | The captured image, named `rendered` with the selected format's extension. | With **Full Page** off, viewport width and height define the capture area. With it on, the width still affects responsive layout while the page height expands to include the full document. ## Example: generate a social card Build a fixed-size HTML card with inline CSS, select a `1200` by `630` viewport, and leave **Full Page** off. Connect **Screenshot** to an upload, email, or image-processing action. ## Troubleshooting Change **Viewport Width** before capture. The viewport controls which CSS media queries apply. Enable **Full Page**, or increase **Viewport Height** when you intentionally want a fixed-size capture. # Get Links on Page Source: https://learn.workflow.dog/reference/actions/cloudflare/links Render a web page and return the links Cloudflare finds on it. **Get Links on Page** opens a URL with Cloudflare Browser Rendering and returns the links found after the page renders. This is useful for link discovery on JavaScript-heavy pages. ## Inputs | Input | Type | Required | Description | | ----------------------------- | ------------------ | -------- | ----------------------------------------------------------- | | **Third-party account** | Cloudflare account | Yes | The Cloudflare account used for browser rendering. | | **URL** | String | Yes | The complete page URL to inspect. | | **Wait For Selector** | String | No | A CSS selector that must appear before links are collected. | | **Wait Time** | Number | No | Extra delay after load, from `0` to `30000` milliseconds. | | **Viewport Width** | Number | No | Viewport width, up to `1920`. Defaults to `1920`. | | **Viewport Height** | Number | No | Viewport height, up to `1080`. Defaults to `1080`. | | **JavaScript Code** | String | No | JavaScript inserted into the rendered page. | | **Additional API Parameters** | Object | No | Extra fields passed to Cloudflare's links endpoint. | ## Output | Output | Type | Description | | --------- | --------------- | --------------------------------------------------------------------------- | | **Links** | List of strings | Links returned by the rendered page. The list is empty when none are found. | This action discovers links on one page; it does not crawl those links. Use a loop or a crawl-oriented integration when you need to visit them. If links appear only after an interaction, use **JavaScript Code** to perform that interaction and **Wait For Selector** to identify when the new content is ready. # Take Screenshot Source: https://learn.workflow.dog/reference/actions/cloudflare/screenshot Capture a rendered web page as a PNG, JPEG, or WebP image. **Take Screenshot** opens a URL in Cloudflare's remote browser and captures the rendered page. Unlike a direct HTTP request, it can wait for client-side content and run JavaScript before capture. ## Inputs | Input | Type | Required | Description | | ----------------------------- | ------------------------ | -------- | -------------------------------------------------------------------------- | | **Third-party account** | Cloudflare account | Yes | The Cloudflare account used for browser rendering. | | **URL** | String | Yes | The complete page URL to capture. | | **Format** | `png`, `jpeg`, or `webp` | Yes | Image encoding. Defaults to `png`. | | **Full Page** | Boolean | No | Captures the full document rather than only the viewport. Defaults to off. | | **Wait For Selector** | String | No | A CSS selector that must appear before capture. | | **Wait Time** | Number | No | Extra delay after load, from `0` to `30000` milliseconds. | | **Viewport Width** | Number | No | Viewport width, up to `1920`. Defaults to `1920`. | | **Viewport Height** | Number | No | Viewport height, up to `1080`. Defaults to `1080`. | | **JavaScript Code** | String | No | JavaScript inserted into the page before capture. | | **Additional API Parameters** | Object | No | Extra fields passed to Cloudflare's screenshot endpoint. | ## Output | Output | Type | Description | | -------------- | ---- | -------------------------------------------------- | | **Screenshot** | File | The captured image, named from the URL's hostname. | ## Example: capture a loaded dashboard Set **URL** to the dashboard, **Wait For Selector** to a selector on its final chart, and choose the viewport used by the dashboard's desktop layout. Turn on **Full Page** when charts extend below the initial viewport. Cloudflare must be able to reach and authenticate to the URL. Do not expect a browser session from your own computer to be present in the remote browser. ## Troubleshooting The remote browser does not share your local cookies. Use supported request or browser parameters to authenticate only when it is safe to do so. Wait for a selector that appears after the content loads. Use **Wait Time** only when the page has no reliable ready-state element. # Fallback Source: https://learn.workflow.dog/reference/actions/control/coalesce Choose the first usable value from an ordered set of alternatives. **Fallback** checks its **Try** inputs from top to bottom and returns the first one that qualifies under the selected mode. ## Inputs | Input | Type | Required | Description | | -------- | -------------- | -------- | ------------------------------------- | | **Try** | Repeatable any | Yes | Candidate values, checked in order. | | **Mode** | String | Yes | **Non-Null** (default) or **Truthy**. | Skips only `null`. Values such as `false`, `0`, and empty text are valid results. Skips falsy values, including `null`, `false`, `0`, and empty text. ## Output | Output | Type | Description | | --------- | ---- | -------------------------------------- | | **Value** | Any | The first qualifying value, or `null`. | Use **Non-Null** for default values where `false` or `0` is meaningful. Use **Truthy** only when those values should also fall through. # Route Value Source: https://learn.workflow.dog/reference/actions/control/demux Send a value to one of two outputs based on a condition. ## Inputs | Input | Type | Required | Description | | ------------- | ------- | -------- | -------------------------- | | **Value** | Any | Yes | The value to route. | | **Condition** | Boolean | Yes | Selects the active output. | ## Outputs | Output | Type | Description | | ------------ | ---- | ----------------------------------------------- | | **If True** | Any | Receives the value when the condition is true. | | **If False** | Any | Receives the value when the condition is false. | Only the selected output is produced during a run. Use **Choose Value** for the inverse pattern: two possible inputs feeding one output. # Is Falsy? Source: https://learn.workflow.dog/reference/actions/control/is-falsy Convert JavaScript-style falsiness into a Boolean result. ## Input | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | ## Output | Output | Type | Description | | ---------- | ------- | ------------------------------- | | **Result** | Boolean | `true` when the value is falsy. | Falsy values include `null`, `false`, `0`, empty text, and missing values. Empty lists and empty objects are truthy. # Is Truthy? Source: https://learn.workflow.dog/reference/actions/control/is-truthy Convert JavaScript-style truthiness into a Boolean result. ## Input | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | ## Output | Output | Type | Description | | ---------- | ------- | -------------------------------- | | **Result** | Boolean | `true` when the value is truthy. | `null`, `false`, `0`, empty text, and missing values are falsy. Empty lists and empty objects are truthy. # Choose Value Source: https://learn.workflow.dog/reference/actions/control/mux Choose between two values using a Boolean condition. ## Inputs | Input | Type | Required | Description | | ------------- | ------- | -------- | --------------------------------------- | | **If True** | Any | No | Returned when the condition is `true`. | | **If False** | Any | No | Returned when the condition is `false`. | | **Condition** | Boolean | Yes | Selects which input to return. | ## Output | Output | Type | Description | | ---------- | ---- | ------------------- | | **Result** | Any | The selected input. | An unconnected selected input produces no value. Both alternatives may have different data types, so check what downstream actions accept. # Choose Value by Case Source: https://learn.workflow.dog/reference/actions/control/mux-case Map an exact text match to a corresponding output value. **Choose Value by Case** compares text against a set of named cases and returns the value belonging to the matching case. ## Inputs | Input | Type | Required | Description | | -------------- | ----------------- | -------- | -------------------------------------------------- | | **Test Value** | String | Yes | Text to look up. | | **Cases** | Repeatable object | Yes | One or more **Case** and **Value** pairs. | | **Default** | Any | No | Returned when no case matches. Defaults to `null`. | Each **Case** is a string key. Matching is exact and case-sensitive. ## Output | Output | Type | Description | | ---------- | ---- | ---------------------------------------- | | **Result** | Any | The matching case value, or **Default**. | For example, cases `urgent → page`, `normal → queue` and a test value of `urgent` return `page`. This action chooses a value. To send one value to separate workflow branches, use **Route Value** after producing a Boolean condition. # Passthrough Source: https://learn.workflow.dog/reference/actions/control/passthrough Expose an input unchanged as an output. **Passthrough** is primarily useful while arranging or testing a workflow. | Input | Type | Required | Description | | --------- | ---- | -------- | -------------------------- | | **Value** | Any | Yes | The value to pass through. | | Output | Type | Description | | --------- | ---- | ---------------------- | | **Value** | Any | The exact input value. | The action does not copy, convert, or validate the value. # Third-Party Account Source: https://learn.workflow.dog/reference/actions/core/account Select a connected account and pass it to another action. **Third-Party Account** creates a reusable account value. Use it when several actions should use the same connected account, or when an account input needs to be selected independently. ## Inputs | Input | Type | Required | Description | | ----------- | ------- | --------- | ------------------------------------ | | **Service** | Service | Yes | The integration provider. | | **Account** | Account | Sometimes | Appears after a service is selected. | ## Output | Output | Type | Description | | ----------- | ------- | -------------------------------------- | | **Account** | Account | The selected account for that service. | The available services come from the integrations installed in WorkflowDog. The server verifies that the selected account belongs to the chosen service. Changing **Service** changes the account type. Select a new account and check downstream connections after switching providers. # Append to List in Project Variables Source: https://learn.workflow.dog/reference/actions/core/append-to-project-var-list Add values to a project-wide persistent list. **Append to List in Project Variables** loads a stored list, adds the supplied values to its end, and saves the result under the same key. If the key does not exist, the action starts with an empty list. ## Inputs | Input | Type | Required | Description | | ---------- | -------------- | -------- | -------------------------------------- | | **Key** | String | Yes | Name of the project variable. | | **Values** | Repeatable any | Yes | One or more values to append in order. | The action has no output. Use **Get Project Variable** afterward when the updated list is needed in the workflow. The existing value must be a list. The action fails with `Value is not a list` for another type, or `Variable is corrupted` when the stored value cannot be read. The value is shared by every workflow in the project. Simultaneous read-and-append operations can overwrite one another, so this action is not a transactional queue. # True/False Source: https://learn.workflow.dog/reference/actions/core/boolean Provide a fixed Boolean value. Use the switch on the compact **True/False** node to choose a value. It defaults to off. | Input | Type | Required | Description | | ----------- | ------- | -------- | ----------------------------- | | **Boolean** | Boolean | No | On is `true`; off is `false`. | | Output | Type | Description | | ------ | ------- | ------------------------- | | | Boolean | The current switch value. | # Comment Source: https://learn.workflow.dog/reference/actions/core/comment Add explanatory Markdown to the workflow canvas. **Comment** is purely visual. It does not produce data or affect execution. ## Settings | Setting | Options | Default | | -------------- | -------------------- | ------- | | **Text** | Markdown text | Empty | | **Text Align** | Left, Center, Right | Center | | **Text Size** | Small, Medium, Large | Small | Use comments to explain assumptions, label sections, or leave maintenance notes beside related actions. Anyone who can view the workflow can read the comment. Do not put secrets or credentials in it. # Convert Encoding Source: https://learn.workflow.dog/reference/actions/core/convert-encoding Decode text from one byte encoding and encode it as another. **Convert Encoding** first interprets **Input Text** using its declared source encoding, then emits the same bytes in the target encoding. ## Inputs | Input | Type | Required | Description | | ------------------- | ------ | -------- | --------------------------------------------- | | **Input Text** | String | Yes | Text or encoded byte representation. | | **Input Encoding** | String | No | How to decode the input. Defaults to UTF-8. | | **Output Encoding** | String | No | How to encode the result. Defaults to Base64. | Supported options are UTF-8, Base64, Base64 URL, Hex, ASCII, UTF-16LE, UCS-2, Latin-1, and Binary. ## Output | Output | Type | Description | | ------------------ | ------ | ---------------------------- | | **Converted Text** | String | Text in the target encoding. | For example, UTF-8 text `hello` converted to Base64 returns `aGVsbG8=`. Set **Input Encoding** to the format the input already uses. Choosing Base64 for ordinary text attempts to decode that text as Base64 rather than encode it. # Format Number Source: https://learn.workflow.dog/reference/actions/core/format-number Render a number as localized decimal, currency, percentage, or compact text. **Format Number** uses the `en-US` locale and returns display text rather than a numeric value. ## Inputs | Input | Type | Required | Description | | ------------------ | ------ | --------- | ----------------------------------------------------------- | | **Number** | Number | Yes | Value to format. | | **Format Type** | String | Yes | Decimal, Currency, Percentage, or Compact. | | **Decimal Places** | Number | Sometimes | `0`–`20`; used by decimal, percentage, and compact formats. | | **Currency** | String | Sometimes | ISO currency code; appears for Currency. Defaults to USD. | ## Output | Output | Type | Description | | ------------- | ------ | ----------------------------- | | **Formatted** | String | The localized display string. | `1234.5` with two decimal places becomes `1,234.50`. `1234.5` in USD becomes `$1,234.50`. Currency controls its conventional number of decimal places. The input is a ratio: `0.125` with one decimal place becomes `12.5%`. `1200` with one decimal place becomes `1.2K`. # Get Project Variable Source: https://learn.workflow.dog/reference/actions/core/get-project-var Load a persistent value shared across the current project. ## Inputs | Input | Type | Required | Description | | ----------------- | ------ | -------- | ----------------------------------------- | | **Key** | String | Yes | Name of the project variable to retrieve. | | **Default Value** | Any | No | Returned when the key does not exist. | ## Output | Output | Type | Description | | --------- | ---- | ----------------------------------------- | | **Value** | Any | The stored value, the default, or `null`. | When the key is missing and **Default Value** is unconnected, the result is `null`. Reading a value does not change it. Project variable keys are shared by all workflows in the project. Use a naming convention such as `billing.last_sync` to avoid accidental overlap. # Is True/False? Source: https://learn.workflow.dog/reference/actions/core/is-boolean Check whether a value is a Boolean. | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | | Output | Type | Description | | ---------- | ------- | ------------------------------------------------ | | **Result** | Boolean | `true` only when the value is `true` or `false`. | Truthy numbers and strings are not Boolean values. # Is Null? Source: https://learn.workflow.dog/reference/actions/core/is-null Check whether a value is null or missing. | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | | Output | Type | Description | | ---------- | ------- | ------------------------------------- | | **Result** | Boolean | `true` for `null` or a missing value. | Empty text, `0`, `false`, empty lists, and empty objects return `false`. # Is Number? Source: https://learn.workflow.dog/reference/actions/core/is-number Check whether a value has the Number type. | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | | Output | Type | Description | | ---------- | ------- | ---------------------------------- | | **Result** | Boolean | `true` when the value is a number. | Numeric text such as `"42"` returns `false`. Use **Convert to Number** first when coercion is desired. # Parse JSON Source: https://learn.workflow.dog/reference/actions/core/json-parse Convert JSON text into a workflow value. ## Input | Input | Type | Required | Description | | -------- | ------ | -------- | ---------------- | | **JSON** | String | Yes | Valid JSON text. | ## Output | Output | Type | Description | | ---------- | ---- | --------------------------------------------------- | | **Parsed** | Any | The object, list, string, number, Boolean, or null. | ```json theme={null} { "customer": { "id": 42 }, "active": true } ``` The example produces an object whose `customer.id` is the number `42`. JSON does not allow comments, trailing commas, or single-quoted strings. A syntax error fails the action. # Convert to JSON Source: https://learn.workflow.dog/reference/actions/core/json-stringify Serialize a workflow value as JSON text. ## Inputs | Input | Type | Required | Description | | ---------- | ------- | -------- | ------------------------------------------------- | | **Value** | Any | Yes | The value to serialize. | | **Pretty** | Boolean | No | Indent nested JSON by two spaces. Defaults to on. | ## Output | Output | Type | Description | | -------- | ------ | ------------------------- | | **JSON** | String | The serialized JSON text. | Turn **Pretty** off for compact payloads sent to APIs. Keep it on when humans will read the result. JSON cannot represent every runtime value. Unsupported object properties may be omitted, and circular structures cause serialization to fail. # Loop Workflow Source: https://learn.workflow.dog/reference/actions/core/loop-workflow Run a callable workflow once for each item in a list. **Loop Workflow** sends every payload to the selected workflow and collects the returned values in the same order. ## Inputs | Input | Type | Required | Description | | --------------------- | -------- | -------- | ------------------------------------------------ | | **Selected Workflow** | Workflow | Yes | Callable workflow to run for each item. | | **Payloads** | List | No | Items to process, up to 1,000. Defaults to `[]`. | ## Output | Output | Type | Description | | ----------- | ---- | ------------------------------------------------ | | **Results** | List | One child result per payload, in matching order. | Each item becomes **Data In** in the child workflow. A child run without **Return Data** contributes `null` to the result list. Iterations run sequentially, not in parallel. This preserves order but means total runtime grows with the number and duration of child runs. If any child run fails, this action fails and does not return partial results. Recursive workflow calls are also rate-limited to prevent infinite loops. # Null Source: https://learn.workflow.dog/reference/actions/core/null Produce an explicit null value. **Null** has no inputs. | Output | Type | Description | | -------- | ---- | ----------------- | | **Null** | Null | The value `null`. | Use it when an action must receive an explicit “no value” rather than an unconnected input. # Number Source: https://learn.workflow.dog/reference/actions/core/number Provide a fixed numeric value. Enter a number directly on the compact node. | Input | Type | Required | Description | | ---------- | ------ | -------- | -------------------------- | | **Number** | Number | Yes | The numeric value to emit. | | Output | Type | Description | | ------ | ------ | ------------------- | | | Number | The entered number. | If the input cannot be parsed as a number, the server produces `null`. # Return Data Source: https://learn.workflow.dog/reference/actions/core/return-data Return a value to the workflow that called this sub-workflow. **Return Data** is available for workflows using the **Sub-Workflow** trigger. It sends a response back to **Run Workflow**, **Loop Workflow**, or another calling action. ## Input | Input | Type | Required | Description | | -------- | ---- | -------- | --------------------------------- | | **Data** | Any | Yes | The value returned to the caller. | The calling action receives this value as its result or corresponding loop item. If a callable workflow finishes without returning data, callers use `null` as its result. # Run Workflow Source: https://learn.workflow.dog/reference/actions/core/run-workflow Run a callable workflow and wait for its returned data. **Run Workflow** starts another workflow, waits for it to finish, and exposes the value it returns. ## Quick start Give it the **Sub-Workflow** trigger. Use **Data from Trigger** to read **Data In**, and **Return Data** to send a result back. Choose it in **Selected Workflow**, or connect a **Callable Workflow** value. Connect an optional **Payload** and use **Result** after the child run completes. ## Inputs | Input | Type | Required | Description | | --------------------- | -------- | -------- | ----------------------------------- | | **Selected Workflow** | Workflow | Yes | Callable workflow to run. | | **Payload** | Any | No | Passed to the child as **Data In**. | ## Output | Output | Type | Description | | ---------- | ---- | --------------------------------------------------- | | **Result** | Any | Returned child data, or `null` if none is returned. | If the child run fails, this action fails with the child run's failure message. Recursive workflow calls are rate-limited to prevent infinite loops. # Schedule Workflow Source: https://learn.workflow.dog/reference/actions/core/schedule-workflow Queue a callable workflow to run at a future date and time. **Schedule Workflow** creates a future child run and completes without waiting for that run to execute. ## Inputs | Input | Type | Required | Description | | --------------------- | ----------- | -------- | ----------------------------------- | | **Selected Workflow** | Workflow | Yes | Callable workflow to schedule. | | **Date & Time** | Date & Time | Yes | Exact instant for the child run. | | **Payload** | Any | No | Passed to the child as **Data In**. | The scheduled child workflow can read the payload through **Data from Trigger**. This action has no result output because it does not wait for the future run. **Date & Time** must be at least 10 seconds in the future when this action executes. A date too close to the present fails with `Date must be in the future`. Scheduling confirms that the run was queued, not that it eventually succeeded. Use a project variable, email, or another durable side effect in the child workflow when completion must be observable. # Send Email Source: https://learn.workflow.dog/reference/actions/core/send-email Send a Markdown email to members of the current project. **Send Email** delivers a notification from the current WorkflowDog project. For safety, it cannot send to addresses that are not project members. ## Inputs | Input | Type | Required | Description | | ------------------------ | ----------------- | --------- | ------------------------------------------ | | **Send to all members?** | Boolean | No | Send to every current project member. | | **Recipients** | Repeatable string | Sometimes | Required when sending to selected members. | | **Subject** | String | Yes | Email subject line. | | **Body** | String | Yes | Message body with Markdown support. | When **Send to all members?** is on, the **Recipients** input disappears and membership is resolved when the action runs. ## Example ```markdown theme={null} ## Import complete Processed **{{count}}** records for {{customer}}. ``` Build dynamic content with a **Text** action, then connect the rendered result to **Body**. Every explicitly supplied address must exactly match a current member of the project. If any recipient is not a member, the entire action fails and sends no email. Duplicate recipient addresses are removed. The sender name uses the project name and a project-specific WorkflowDog notification address. # Set Project Variable Source: https://learn.workflow.dog/reference/actions/core/set-project-var Store a persistent value shared across the current project. ## Inputs | Input | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------ | | **Key** | String | Yes | Name under which to store the value. | | **Value** | Any | Yes | Value to save. | The action has no output. If the key already exists, its previous value is replaced. Project variables preserve supported WorkflowDog data types rather than reducing everything to plain text. Use **Get Project Variable** with the same key to load the value later. Project variables are shared by all workflows in the project. Reusing a key intentionally overwrites its value for every workflow. # Text Source: https://learn.workflow.dog/reference/actions/core/text Provide fixed text or render a Handlebars template. **Text** emits exactly what you type unless the text contains template expressions such as `{{name}}`. Each top-level template variable becomes a connectable input on the node. ## Inputs | Input | Type | Required | Description | | ------------------ | ------- | --------- | --------------------------------------------- | | **Text** | String | Yes | Fixed text or a Handlebars template. | | **Sensitive** | Boolean | No | Mask the text on the canvas. Defaults to off. | | Template variables | Any | Sometimes | Created from expressions in the text. | ## Output | Output | Type | Description | | ------ | ------ | ------------------ | | | String | The rendered text. | ## Example ```handlebars theme={null} Hello {{customer.name}}! {{#if urgent}}This request is urgent.{{/if}} ``` The node exposes **customer** and **urgent** inputs. Connect an object to **customer** and a value to **urgent**. Template values are inserted without HTML escaping. **Sensitive** only masks the canvas display; the value remains visible in the configuration panel and is still passed through the workflow. Renaming or removing a template variable removes its corresponding input. Check downstream connections after editing template expressions. # Throw Error Source: https://learn.workflow.dog/reference/actions/core/throw-error Fail the current workflow run with a custom message. ## Input | Input | Type | Required | Description | | ----------- | ------ | -------- | ----------------------------------- | | **Message** | String | Yes | The error shown for the failed run. | When this action executes, it throws immediately. Actions that depend on its completion do not run. Use it after validation or on a failure branch. For example, when a required customer ID is missing, connect that branch to **Throw Error** and set **Message** to `Customer ID is required`. # Convert to True/False Source: https://learn.workflow.dog/reference/actions/core/to-boolean Convert an arbitrary value into a Boolean. | Input | Type | Required | Description | | --------- | ---- | -------- | --------------------- | | **Value** | Any | Yes | The value to convert. | | Output | Type | Description | | ----------- | ------- | ------------------------------- | | **Boolean** | Boolean | The converted true/false value. | The following become `false`: * `null`, `false`, `0`, empty text, and missing values * The text `"false"` in any capitalization All other values become `true`, including empty lists, empty objects, and text containing spaces. # Convert to Number Source: https://learn.workflow.dog/reference/actions/core/to-number Coerce a value into a number. | Input | Type | Required | Description | | --------- | ---- | -------- | --------------------- | | **Value** | Any | Yes | The value to convert. | | Output | Type | Description | | ---------- | ------ | ---------------------------- | | **Number** | Number | The converted numeric value. | Numeric text such as `"42.5"` becomes `42.5`. `true` becomes `1`, `false` becomes `0`, and empty text becomes `0`. The action fails when the input cannot be coerced to a valid number. Use **Is Number?** only to test existing types; it does not predict every value that this action can convert. # Data from Trigger Source: https://learn.workflow.dog/reference/actions/core/trigger-data Access the data that started the current workflow run. **Data from Trigger** changes its name and outputs to match the workflow's selected trigger. Examples include: * **Data In** for a Sub-Workflow trigger * Sender, subject, body, and attachments for a Mail Hook * **Timestamp** for a Schedule trigger Add the node after selecting a trigger, then connect only the event fields the workflow needs. Changing the workflow trigger changes this node's available outputs. Review connections after switching triggers. # Callable Workflow Source: https://learn.workflow.dog/reference/actions/core/workflow Select a callable workflow and expose it as a value. **Callable Workflow** lets the workflow choose which sub-workflow another action should run. Connect its output to **Run Workflow**, **Loop Workflow**, or another action that accepts a workflow value. ## Input | Input | Type | Required | Description | | ------------ | -------- | -------- | ------------------------------------ | | **Workflow** | Workflow | Yes | A callable workflow in this project. | ## Output | Output | Type | Description | | ------------ | -------- | ------------------------------------------ | | **Workflow** | Workflow | The selected workflow, including its name. | The server verifies that the workflow exists in the current project. # Convert to YAML Source: https://learn.workflow.dog/reference/actions/core/yaml-stringify Serialize a workflow value as YAML text. ## Inputs | Input | Type | Required | Description | | ------------------- | ------- | -------- | -------------------------------------------------------------------------- | | **Value** | Any | Yes | The value to serialize. | | **Use references?** | Boolean | No | Represent repeated objects with YAML anchors and aliases. Defaults to off. | ## Output | Output | Type | Description | | -------- | ------ | --------------------------------- | | **YAML** | String | YAML using two-space indentation. | Lines wrap at approximately 80 characters. Enable references when a repeated object should be emitted once and reused with aliases; leave it off for simpler standalone YAML. # Current Date & Time Source: https://learn.workflow.dog/reference/actions/datetime/current Capture the date and time when the action runs. **Current Date & Time** has no inputs. It reads the clock at execution time, not when the workflow is saved or opened. ## Output | Output | Type | Description | | -------- | ----------- | ------------------------------------ | | **Date** | Date & Time | The instant at which the action ran. | Use **Format Date/Time** afterward when another action needs text in a particular timezone or display style. # Date & Time Source: https://learn.workflow.dog/reference/actions/datetime/datetime Provide a fixed date and time to a workflow. **Date & Time** is a compact value node. Choose a date and local time in the editor; the value is stored as an exact ISO timestamp. ## Input | Input | Type | Required | Description | | --------------- | ----------- | -------- | ------------------------------ | | **Date & Time** | Date & Time | Yes | The fixed date and time value. | ## Output | Output | Type | Description | | ------ | ----------- | --------------------------- | | | Date & Time | The selected date and time. | The editor interprets the entered clock time in the browser's local timezone, then stores the corresponding instant. If the workflow must construct a time relative to execution, use **Relative Date** instead. # Format Date/Time Source: https://learn.workflow.dog/reference/actions/datetime/format-date Convert a date and time into display-ready text. **Format Date/Time** renders one instant in a chosen timezone. Use preset date and time styles for localized English output, or enable a custom formatting expression for exact control. ## Inputs | Input | Type | Required | Description | | ------------------------------- | ----------- | -------- | ------------------------------------------- | | **Date & Time** | Date & Time | Yes | The instant to format. | | **Use a formatting expression** | Boolean | No | Switch from presets to a custom expression. | | **Timezone** | String | Yes | IANA timezone used to display the instant. | The timezone defaults to the browser's current timezone when the node is created. **Date Style** and **Time Style** each support `short`, `medium`, `long`, `full`, or `none`. Defaults are `medium` for the date and `short` for the time. Choose `none` to omit either part. **Expression** uses Day.js formatting tokens and defaults to `DD/MM/YYYY h:mm`. For example, `YYYY-MM-DD HH:mm` can produce `2026-07-24 15:30`. ## Output | Output | Type | Description | | ------------- | ------ | ------------------------------------ | | **Formatted** | String | The formatted date and time as text. | Toggling expression mode replaces the preset inputs. Check the format after switching an existing node. # Date from Text Source: https://learn.workflow.dog/reference/actions/datetime/natural-language-date Parse a date from a natural-language expression. **Date from Text** understands phrases such as `in 2 days`, `next Friday`, or `tomorrow at 9am`. ## Inputs | Input | Type | Required | Description | | ----------------- | ----------- | -------- | ------------------------------------------------ | | **Expression** | String | Yes | Natural-language date or time to parse. | | **Starting Date** | Date & Time | No | Reference instant. Defaults to the current time. | | **Timezone** | String | Yes | Timezone used to interpret the expression. | ## Output | Output | Type | Description | | -------- | ----------- | ------------------- | | **Date** | Date & Time | The parsed instant. | For predictable results, make the phrase explicit: ```text theme={null} next Friday at 9:00 AM ``` Set **Starting Date** in tests so relative phrases do not change from one run to the next. Natural-language parsing is experimental and can interpret ambiguous phrases differently than intended. The action fails with `Couldn't parse date` when it cannot recognize the expression. # Relative Date Source: https://learn.workflow.dog/reference/actions/datetime/relative-date Add a duration to a starting date and time. ## Inputs | Input | Type | Required | Description | | ----------------- | ----------- | -------- | ----------------------------------------------------------- | | **Amount** | Number | Yes | Amount to add. Use a negative value to subtract. | | **Unit** | String | Yes | Minutes, hours, days, weeks, or months. Defaults to hours. | | **Starting Date** | Date & Time | No | Reference instant. Intended to default to the current time. | ## Output | Output | Type | Description | | -------- | ----------- | ----------------------------- | | **Date** | Date & Time | The calculated date and time. | For example, an amount of `-2` and a unit of `days` returns two calendar days before the starting date. Days, weeks, and months use calendar arithmetic. Month lengths vary, and daylight-saving changes can make a calendar day differ from exactly 24 elapsed hours. The current server initializes the blank **Starting Date** default when the Date & Time package loads, rather than for each action run. Connect **Current Date & Time** explicitly when the calculation must start at execution time. # Create Text File Source: https://learn.workflow.dog/reference/actions/files/create-text-file Turn string content into a named file. **Create Text File** packages a string as a file that can be uploaded, emailed, stored, or returned from a workflow. ## Inputs | Input | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------------------------------------- | | **Content** | String | Yes | The complete text written to the file. | | **File Name** | String | Yes | The output name, including an extension such as `report.csv`. | ## Output | Output | Type | Description | | -------- | ---- | ------------------------------------ | | **File** | File | A file containing the supplied text. | The MIME type is inferred from the filename when its extension is recognized. Include the correct extension in **File Name**. For example, use `.json` for JSON content and `.html` for an HTML document. # Convert Data URL to File Source: https://learn.workflow.dog/reference/actions/files/data-url-to-file Decode a base64 data URL into a file. **Convert Data URL to File** decodes an embedded base64 value and returns a file with the matching MIME type. ## Input and output | Direction | Field | Type | Description | | --------- | ------------ | ------ | ------------------------------------------------- | | Input | **Data URL** | String | A base64 URL such as `data:image/png;base64,...`. | | Output | **File** | File | The decoded file. | The output is named `converted.EXTENSION`, where the extension is inferred from the MIME type. The input must use the exact `data:MIME_TYPE;base64,DATA` form. Non-base64 data URLs and MIME types without a known file extension are rejected. # Download File from URL Source: https://learn.workflow.dog/reference/actions/files/download-from-url Fetch a public URL and return its response as a file. **Download File from URL** retrieves a public resource and turns the response bytes into a WorkflowDog file. ## Inputs | Input | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------ | | **URL** | String | Yes | The complete public URL to download. | | **Filename** | String | No | A custom output filename. | ## Output | Output | Type | Description | | -------- | ---- | ----------------------- | | **File** | File | The downloaded content. | When **Filename** is empty, the action uses the last part of the URL path. If that name has no extension, `.bin` is added. The response's `Content-Type` header supplies the MIME type when available; otherwise it is inferred from the filename. Internal, local, and private network addresses are blocked. The action also fails when the remote server returns a non-success HTTP status. # Convert File to Data URL Source: https://learn.workflow.dog/reference/actions/files/file-to-data-url Encode a file as a base64 data URL. **Convert File to Data URL** embeds a file's MIME type and base64-encoded bytes in a single string. ## Input and output | Direction | Field | Type | Description | | --------- | ------------ | ------ | -------------------------------------------------- | | Input | **File** | File | The file to encode. | | Output | **Data URL** | String | A string in the form `data:MIME_TYPE;base64,DATA`. | Data URLs are useful when an API or HTML document expects embedded content instead of a separate file. Base64 increases the size of the data. Prefer a normal file upload when the receiving service supports one. # Rename File Source: https://learn.workflow.dog/reference/actions/files/rename Create a copy of a file with a different name. **Rename File** preserves a file's contents and MIME type while changing its name. | Direction | Field | Type | Description | | --------- | ---------------- | ------ | -------------------------------------- | | Input | **File** | File | The original file. | | Input | **Name** | String | The new name, including any extension. | | Output | **Renamed File** | File | A copy with the new name. | Renaming does not convert the file. Changing `.png` to `.jpg`, for example, does not change the underlying image format or MIME type. # Crawl Website Source: https://learn.workflow.dog/reference/actions/firecrawl/crawl Crawl multiple pages from a site and return content, links, and screenshots. **Crawl Website** starts an asynchronous Firecrawl crawl at one URL, waits for it to finish, and returns every completed page as a list. Use it when you need site-wide content rather than a single page. The workflow remains on this action while Firecrawl is scraping. The node checks the crawl every two seconds and fails if Firecrawl reports a failed crawl. ## Crawl inputs | Input | Type | Required | Description | | --------------------------- | ----------------- | -------- | ------------------------------------------------------------------------------ | | **Third-party account** | Firecrawl account | Yes | The Firecrawl API key used for the crawl. | | **URL** | String | Yes | The starting URL. | | **Limit** | Integer | Yes | Maximum pages to crawl, from `1` to `1000`. Defaults to `100`. | | **Max Depth** | Integer | Yes | Maximum link depth from the starting URL, from `1` to `100`. Defaults to `10`. | | **Ignore Query Parameters** | Boolean | No | Treats URL variants that differ only by query parameters as the same page. | | **Allow Backward Links** | Boolean | No | Allows the crawl to move to parent paths outside the starting URL's path. | ## Per-page scrape inputs These settings are applied to every page visited: | Input | Type | Default | Description | | ------------------------ | -------------------------------- | ------- | --------------------------------------------------------------- | | **Format** | `markdown`, `html`, or `rawHtml` | `html` | Content representation for each page. | | **Include Links** | Boolean | Off | Includes links found on each page. | | **Include Screenshot** | Boolean | Off | Includes a screenshot for each page. | | **Full Page Screenshot** | Boolean | Off | Captures full-page screenshots when screenshots are enabled. | | **Only Main Content** | Boolean | On | Excludes headers, navigation, footers, and similar page chrome. | | **Mobile** | Boolean | Off | Emulates a mobile device. | | **Headers** | List of name/value pairs | Empty | Headers sent while scraping. | | **Wait For** | Number | `0` | Milliseconds to wait before extracting each page. | | **Remove Base64 Images** | Boolean | On | Removes embedded base64 image data while retaining alt text. | ## Outputs | Output | Type | Description | | --------- | --------------- | -------------------------------------------------------------------------------------------------------- | | **Total** | Number | Number of pages returned by the completed crawl. | | **Pages** | List of objects | Crawled pages, each containing **URL**, **Content**, and any enabled **Links** or **Screenshot** values. | Expanding **Pages** gives each page: | Property | Type | Description | | -------------- | --------------- | ----------------------------------------------- | | **URL** | String | Firecrawl's source URL for the page. | | **Content** | String | Content in the selected format. | | **Links** | List of strings | Present when **Include Links** is enabled. | | **Screenshot** | File | Present when **Include Screenshot** is enabled. | ## Scope the crawl deliberately Start with a modest **Limit** and **Max Depth**, inspect the returned URLs, and increase them only when needed. Query-heavy sites can expose many near-duplicate URLs; **Ignore Query Parameters** helps keep those from consuming the page limit. Screenshots multiply the work and data produced by a crawl. Enable them only when downstream steps actually need an image for every page. ## Troubleshooting Enable **Ignore Query Parameters** and lower **Max Depth**. Tracking, filtering, and pagination parameters often create many URL variants. Enable **Allow Backward Links**. Leave it off when the crawl should stay within a subsection of a site. Reduce **Limit**, **Max Depth**, and **Wait For**. Full-page screenshots on every page also add substantial work. # Scrape URL Source: https://learn.workflow.dog/reference/actions/firecrawl/scrape Extract page content, links, and an optional screenshot with Firecrawl. **Scrape URL** loads one web page through Firecrawl and returns its content as HTML, raw HTML, or Markdown. It can also collect page links and capture a screenshot in the same request. ## Inputs | Input | Type | Required | Description | | ------------------------ | -------------------------------- | -------- | ----------------------------------------------------------------------------------------------- | | **Third-party account** | Firecrawl account | Yes | The Firecrawl API key used for the request. | | **URL** | String | Yes | The complete page URL to scrape. | | **Format** | `markdown`, `html`, or `rawHtml` | Yes | The content representation. Defaults to `html`. | | **Include Links** | Boolean | No | Adds the page's discovered links to the output. Defaults to off. | | **Include Screenshot** | Boolean | No | Adds a screenshot file to the output. Defaults to off. | | **Full Page Screenshot** | Boolean | No | When screenshots are enabled, captures the full page instead of the viewport. | | **Only Main Content** | Boolean | No | Excludes navigation, headers, footers, and similar surrounding content. Defaults to on. | | **Mobile** | Boolean | No | Emulates a mobile device while scraping. Defaults to off. | | **Headers** | List of name/value pairs | No | Request headers, such as a cookie or user-agent. | | **Wait For** | Number | No | Time to wait before scraping, in milliseconds. Defaults to `0`. | | **Remove Base64 Images** | Boolean | No | Replaces embedded base64 image data with placeholders while retaining alt text. Defaults to on. | Headers can contain credentials. Only send them to URLs you trust, and avoid exposing private session cookies in workflow outputs or logs. ## Outputs | Output | Type | Available when | Description | | -------------- | --------------- | ---------------------------- | ------------------------------------ | | **Content** | String | Always | Page content in the selected format. | | **Links** | List of strings | **Include Links** is on | Links Firecrawl found on the page. | | **Screenshot** | File | **Include Screenshot** is on | The downloaded page screenshot. | Changing either include toggle changes the node's output handles. Check downstream connections after turning one off. ## Choosing a format * `markdown` produces compact content suited to summaries, search indexing, and language-model prompts. * `html` returns Firecrawl's cleaned HTML representation. * `rawHtml` preserves the page's original HTML more closely. Use **Only Main Content** with Markdown or HTML when page chrome is noise. Turn it off when headers, navigation, or footer content is part of what you need. ## Troubleshooting Turn off **Only Main Content** if the text is outside the page's detected main region. Increase **Wait For** when the content appears after load. Keep **Remove Base64 Images** on, use `markdown`, and enable **Only Main Content**. Embedded images and raw HTML can make results much larger. Confirm **Include Screenshot** is enabled. Firecrawl must return a screenshot URL for the node to download a file. # Search Web Source: https://learn.workflow.dog/reference/actions/firecrawl/search Search the web with Firecrawl and return titles, descriptions, and URLs. **Search Web** sends a search query through Firecrawl and returns structured search results. It is useful for discovering pages before scraping or crawling them. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------- | -------- | ------------------------------------------------------------------------------------ | | **Third-party account** | Firecrawl account | Yes | The Firecrawl API key used for search. | | **Query** | String | Yes | The search terms. An empty query is rejected. | | **Limit** | Integer | Yes | Maximum results, from `1` to `100`. Defaults to `5`. | | **Location** | String | No | A geographic location used to localize results. | | **Time Filter** | Enum | No | Restricts results to the past hour, day, week, month, or year. Defaults to any time. | Available time filters are: * **Any time** * **Past hour** * **Past 24 hours** * **Past week** * **Past month** * **Past year** If you expand **Results** into a fixed number of output entries, that entry count becomes the requested result limit. Otherwise the action uses **Limit**. ## Outputs | Output | Type | Description | | ----------- | --------------- | ------------------------------------------------------------ | | **Total** | Number | Number of results Firecrawl returned. | | **Results** | List of objects | Search results with **Title**, **Description**, and **URL**. | Search results identify candidate pages; they do not contain the full page body. Connect a selected **URL** to **Scrape URL** when you need its content. ## Example: research recently updated pages Search for a focused query, set **Time Filter** to **Past month**, and expand the first few **Results**. Use their descriptions for an initial relevance check, then scrape only the URLs you decide to process. ## Troubleshooting The limit is a maximum, not a guarantee. The time filter, location, and available matches can reduce the result count. Check whether **Results** has been expanded into individual entries. Its configured entry count takes precedence over **Limit**. # Autocomplete Places Source: https://learn.workflow.dog/reference/actions/geo/autocomplete-places Find likely places and search suggestions from partial text. **Autocomplete Places** uses fuzzy matching to turn partial names, addresses, misspellings, or plus codes into Google place predictions. ## Inputs | Input | Type | Required | Description | | ------------------------------ | --------------- | -------- | ------------------------------------------------------------------------------------ | | **Input** | String | Yes | The search text. | | **Latitude** | Number | No | Center latitude for location-biased results. | | **Longitude** | Number | No | Center longitude for location-biased results. | | **Radius Meters** | Number | No | Bias radius from `0` to `50,000`. Defaults to `5,000` when coordinates are supplied. | | **Include Query Predictions?** | Boolean | No | Also return alternative search phrases. | | **Region Codes** | List of strings | No | Up to 15 two-character country codes, such as `US` and `CA`. | Location bias is applied only when both **Latitude** and **Longitude** are present. A radius without both coordinates has no effect. ## Outputs | Output | Type | Description | | --------------------- | --------------- | ------------------------------------------------------------------------------------------------ | | **Top Place ID** | String | The Google Place ID from the first place prediction. | | **Top Place Text** | String | The formatted text of the first place prediction. | | **Place Predictions** | List of objects | All matches, including place ID, text, primary and secondary text, types, and optional distance. | | **Query Predictions** | List of objects | Suggested search text when query predictions are enabled. | When there are no place matches, the top outputs are empty and **Place Predictions** is an empty list. # Validate Address Source: https://learn.workflow.dog/reference/actions/geo/refine-address Standardize an address and return location and deliverability details. **Validate Address** sends a street address to Google's Address Validation API. It returns standardized address parts, coordinates, a Place ID, and deliverability signals. ## Inputs | Input | Type | Required | Description | | ---------------------- | ------- | -------- | --------------------------------------------------------------------------- | | **Address** | String | Yes | The complete address to validate. | | **Get Full Zip Code?** | Boolean | No | Return a ZIP+4 value when Google or USPS provides one. | | **Enable USPS CASS?** | Boolean | No | Request USPS CASS standardization and delivery-point data for US addresses. | ## Outputs | Output | Type | Description | | --------------------------------------- | ------- | -------------------------------------------------------------------- | | **Formatted Address** | String | Google's standardized complete address. | | **Address Line 1** / **Address Line 2** | String | Standardized street lines. | | **City** / **State** / **Zip Code** | String | Parsed locality and postal fields. | | **Latitude** / **Longitude** | Number | Geocoded coordinates. | | **Place ID** | String | Google's stable identifier for the location. | | **Is Residential** / **Is Business** | Boolean | Address metadata when available. | | **Is Deliverable** | Boolean | True when the address is complete and has no unconfirmed components. | Some outputs can be empty when the service cannot confirm that detail. Treat **Is Deliverable** as the clearest validation signal rather than assuming a formatted address is deliverable. ## Example: clean a shipping address Connect the customer's raw address to **Address**, enable USPS CASS for US shipments, and store **Formatted Address** for display. Continue fulfillment only when **Is Deliverable** is true; otherwise route the order for review. # Add Label Source: https://learn.workflow.dog/reference/actions/gmail/add-label Apply a Gmail label to one message. The **Add Label** action applies an existing Gmail label to a message. Use it to categorize processed mail, route inbox work, or mark a workflow stage. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | | **Label** | String | Yes | Existing Gmail label name or label ID. | Label names are matched after trimming whitespace and ignoring capitalization. Supplying an exact Gmail label ID also works. This action has no output. A successful run means Gmail accepted the label update. ## Example Use **Search Messages** to find the relevant mail, repeat over its **Message IDs**, and apply the `Processed` label to each message with **Add Label**. ## Troubleshooting The action does not create labels. Create the label in Gmail first, then use its visible name or exact ID. # Delete Draft Source: https://learn.workflow.dog/reference/actions/gmail/delete-draft Permanently delete a Gmail draft. The **Delete Draft** action deletes an unsent draft from the connected Gmail account. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ---------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that owns the draft. | | **Message ID** | String | Yes | Identifier of the draft to delete. | The identifier returned by **Draft Email** or **Draft Reply** can be connected directly. Deleting a draft is permanent and this action has no output. Do not pass the ID of a draft that still needs human review. ## Troubleshooting Confirm the identifier belongs to an existing draft in the connected account. A draft that was already sent or deleted no longer resolves. # Draft Email Source: https://learn.workflow.dog/reference/actions/gmail/draft-email Create an unsent Gmail draft with optional recipients and attachments. The **Draft Email** action saves a new message in Gmail without sending it. Use it for human review, approval workflows, or messages that should be completed manually in Gmail. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | -------------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that owns the draft. | | **Recipients** | List of email strings | No | `To` addresses. | | **CC** | List of email strings | No | Carbon-copy addresses. | | **Subject** | String | No | Draft subject. Defaults to an empty subject. | | **Body** | String | No | Draft content. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files to include in the draft. | Because this action creates a draft, recipients and message content can remain empty and be completed later in Gmail. ## Outputs | Output | Type | Description | | -------------- | ------ | ------------------------------------------ | | **Message ID** | String | Identifier returned for the created draft. | Despite its label, this output is the identifier accepted by **Delete Draft**. ## Example: prepare a message for approval Generate the customer update with an earlier action and connect the result to the draft's **Body**. Once Gmail creates the draft, notify the reviewer that it is ready. ## Troubleshooting Use **Draft Email**, not **Send Email**. This action only saves the message in the connected account's Drafts folder. Choose **HTML** as the **Body Type** before providing markup. # Draft Reply Source: https://learn.workflow.dog/reference/actions/gmail/draft-reply Create an unsent reply draft for a Gmail message. The **Draft Reply** action prepares a reply in Gmail without sending it. It keeps the original subject and conversation headers, so a reviewer can finish or send the response from Gmail. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that owns the draft. | | **Message ID** | String | Yes | Gmail ID of the message being answered. | | **Reply All** | Boolean | No | Include original `To` and `CC` recipients except this account. | | **Body** | String | No | Draft reply content. Defaults to empty. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files to attach to the draft. | ## Outputs | Output | Type | Description | | -------------------- | ------ | --------------------------------------- | | **Reply Message ID** | String | Identifier for the created reply draft. | When **Reply All** is enabled, the finished draft includes original `To` and `CC` recipients other than the connected account. Review the recipients before sending. ## Example: human-review support reply For a human-review workflow: 1. Use the incoming email to generate a suggested response. 2. Connect the original **Message ID** and suggested response to **Draft Reply**. 3. Notify the support agent after Gmail creates the draft. ## Troubleshooting Supply the Gmail Message ID for the message being answered. The action needs that message's thread and RFC reply headers to construct the draft. # Forward Source: https://learn.workflow.dog/reference/actions/gmail/forward Forward a Gmail message, including its original attachments. The **Forward** action sends an existing Gmail message to one or more new recipients. It preserves the original content and attachments, adds a forwarded message block to the plain-text body, and keeps the message associated with the original Gmail thread. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------------- | -------- | -------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that sends the forward. | | **Message ID** | String | Yes | Gmail ID of the message to forward. | | **Recipients** | List of email strings | Yes | One or more addresses that receive it. | ## Outputs | Output | Type | Description | | ---------------------- | ------ | --------------------------------------------- | | **Forward Message ID** | String | Gmail ID of the newly sent forwarded message. | The subject receives `Fwd: ` unless it already starts with `Fwd:`. Original attachments are downloaded and attached to the outgoing message. Forwarding a message with large attachments requires downloading and re-uploading those files during the workflow run. ## Troubleshooting Forwarding requires the message's thread, raw content, From, Date, Subject, and To data. Confirm the Message ID belongs to a complete message in the connected mailbox. Add each valid email address as a separate **Recipients** item. # Get Message by ID Source: https://learn.workflow.dog/reference/actions/gmail/get-message Retrieve Gmail message content and optionally download its attachments. The **Get Message by ID** action retrieves one Gmail message. It accepts either Gmail's internal message ID or an RFC 822 `Message-ID`, making it useful with Gmail triggers as well as IDs received from other mail systems. ## Quick start Choose an account that can read the message. Connect a Gmail **Message ID**, or supply an RFC 822 message ID such as a value from an email's `Message-ID` header. Enable **Download Attachments** only when later actions need the files. Prefer **Plain Text** for text processing and **HTML** when preserving the message's formatting. ## Inputs | Input | Type | Required | Description | | ------------------------ | -------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read the message. | | **Message ID** | String | Yes | Gmail ID or RFC 822 message ID. | | **Download Attachments** | Boolean | No | Whether to download attached files and expose **Attachments**. | RFC 822 IDs are looked up across the mailbox, including Spam and Trash. Gmail IDs are loaded directly. ## Outputs | Output | Type | Description | | ------------------ | ------------- | --------------------------------------------------- | | **Message ID** | String | Canonical Gmail message ID. | | **Thread ID** | String | Gmail conversation ID. | | **Sender Name** | String | Parsed sender display name, when present. | | **Sender Address** | String | Parsed sender email address, when present. | | **Subject** | String | Message subject. | | **Plain Text** | String | Plain-text MIME content, when present. | | **HTML** | String | HTML MIME content, when present. | | **Attachments** | List of files | Downloaded files when attachment downloading is on. | **Attachments** is conditional. Turning off **Download Attachments** removes that output from the node and avoids downloading file bodies. ## Troubleshooting Use the Gmail ID returned by a Gmail action or trigger, or a complete RFC 822 `Message-ID`. The connected account must contain the message. A message can contain only one of those MIME formats. Use the format the sender supplied, or add fallback logic when processing varied mail. # Has Label? Source: https://learn.workflow.dog/reference/actions/gmail/has-label Check whether a Gmail message has a specific label. The **Has Label?** action resolves a Gmail label and checks whether it is currently applied to one message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to inspect. | | **Label** | String | Yes | Existing label name or exact label ID. | Label names are resolved case-insensitively after trimming whitespace. ## Outputs | Output | Type | Description | | ------------- | ------- | --------------------------------------------- | | **Has Label** | Boolean | Whether the resolved label is on the message. | Use the boolean in an If action to avoid repeating work or to route labeled messages differently. ## Troubleshooting This action fails when the label does not exist. It returns `false` only when the label exists but is not applied to the message. # Is Important? Source: https://learn.workflow.dog/reference/actions/gmail/is-important Check whether Gmail marks a message as important. The **Is Important?** action checks for Gmail's built-in `IMPORTANT` label on a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to inspect. | ## Outputs | Output | Type | Description | | ------------- | ------- | ---------------------------------------------- | | **Important** | Boolean | Whether the message has the `IMPORTANT` label. | Use this action before **Mark as Important** when the workflow should only change messages that are not already important. # Is Starred? Source: https://learn.workflow.dog/reference/actions/gmail/is-starred Check whether a Gmail message is starred. The **Is Starred?** action checks for Gmail's built-in `STARRED` label on one message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to inspect. | ## Outputs | Output | Type | Description | | ----------- | ------- | -------------------------------------------- | | **Starred** | Boolean | Whether the message has the `STARRED` label. | Route **Starred** into conditional logic when starred mail needs special handling. # Is Unread? Source: https://learn.workflow.dog/reference/actions/gmail/is-unread Check whether a Gmail message is unread. The **Is Unread?** action checks whether one Gmail message carries the built-in `UNREAD` label. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to inspect. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------- | | **Unread** | Boolean | Whether the message has the `UNREAD` label. | The result reflects the message's state when the action runs. # Mark as Important Source: https://learn.workflow.dog/reference/actions/gmail/mark-as-important Mark one Gmail message as important. The **Mark as Important** action adds Gmail's built-in `IMPORTANT` label to a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | This action has no output. Use **Is Important?** afterward only when a later step needs an explicit boolean. # Mark as Read Source: https://learn.workflow.dog/reference/actions/gmail/mark-as-read Mark one Gmail message as read. The **Mark as Read** action removes Gmail's built-in `UNREAD` label from a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | The action returns no output. A successful run means Gmail accepted the state change. # Mark as Unread Source: https://learn.workflow.dog/reference/actions/gmail/mark-as-unread Mark one Gmail message as unread. The **Mark as Unread** action adds Gmail's built-in `UNREAD` label to a message. Use it to return processed mail to an inbox review queue or preserve a reminder for a person. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | This action changes the message and returns no output. # Remove Label Source: https://learn.workflow.dog/reference/actions/gmail/remove-label Remove an existing Gmail label from one message. The **Remove Label** action removes one label from a Gmail message without deleting the label itself. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | | **Label** | String | Yes | Existing Gmail label name or label ID. | Label names are matched case-insensitively after surrounding whitespace is removed. Exact label IDs are accepted as well. This action has no output. It changes the message only; the label remains available elsewhere in Gmail. ## Troubleshooting Verify the label exists in the connected account. Labels belong to a mailbox, so a name from another Google account may not resolve. # Remove Reply Text Source: https://learn.workflow.dog/reference/actions/gmail/remove-reply-text Attempt to remove quoted reply history from plain-text email content. The **Remove Reply Text** action cleans a common plain-text email reply format. It removes carriage returns, looks for a line shaped like `On … wrote:`, and strips the following quoted lines beginning with `>`. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ---------------------------------- | | **Text** | String | Yes | Plain-text email content to clean. | ## Outputs | Output | Type | Description | | -------------- | ------ | ----------------------------------------------------- | | **Clean Text** | String | Trimmed text after matching reply history is removed. | This is a best-effort text cleanup, not a complete email parser. Reply markers vary across mail clients and languages, so unmatched history can remain. ## Example Read a message with **Get Message by ID**, connect its **Plain Text** output to **Remove Reply Text**, then pass **Clean Text** to the action that classifies the message. ## Troubleshooting The cleaner recognizes the common `On … wrote:` pattern followed by newline-prefixed `>` quotes. Other formats, HTML replies, and custom signatures are left unchanged. # Send Reply Source: https://learn.workflow.dog/reference/actions/gmail/reply Reply to a specific Gmail message with optional attachments. The **Send Reply** action sends a response to a specific Gmail message while preserving the original conversation. It addresses the original `Reply-To` header when present, otherwise the original sender. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that sends the reply. | | **Message ID** | String | Yes | Gmail ID of the message being answered. | | **Reply All** | Boolean | No | Include original `To` and `CC` recipients except this account. | | **Body** | String | Yes | Reply content. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files to attach to the reply. | ## Outputs | Output | Type | Description | | -------------------- | ------ | --------------------------- | | **Reply Message ID** | String | Gmail ID of the sent reply. | The action preserves the original subject and builds reply headers from the selected message so Gmail keeps the response in its thread. **Reply All** can notify every original `To` and `CC` recipient. Leave it off when a private response is intended. ## Troubleshooting The source message must have a subject, RFC message ID, reply or sender address, and Gmail thread ID. Confirm the Message ID points to a complete message in the connected mailbox. Turn off **Reply All** to reply only to the original Reply-To or From address. # Send Reply to Thread Source: https://learn.workflow.dog/reference/actions/gmail/reply-thread Reply to the most recent inbox message in a Gmail thread. The **Send Reply to Thread** action takes a Gmail thread ID, finds the most recent message in that thread carrying the `INBOX` label, and replies to it. Use it when your workflow tracks conversations rather than individual messages. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that sends the reply. | | **Thread ID** | String | Yes | Gmail conversation ID. | | **Reply All** | Boolean | No | Include original `To` and `CC` recipients except this account. | | **Body** | String | Yes | Reply content. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files to attach. | ## Outputs | Output | Type | Description | | -------------------- | ------ | --------------------------- | | **Reply Message ID** | String | Gmail ID of the sent reply. | The target is the newest inbox message in the thread, not necessarily the newest message of any kind. A thread containing only sent messages cannot be used by this action. ## Example: continue a stored conversation Load the customer's stored thread ID and connect it to **Send Reply to Thread**. After the reply is sent, store **Reply Message ID** if later actions need to refer to that specific message. ## Troubleshooting The thread must contain at least one message with Gmail's `INBOX` label. Use **Send Reply** with a specific Message ID when you already know the message to answer. # Search Messages Source: https://learn.workflow.dog/reference/actions/gmail/search-messages Find Gmail message IDs using Gmail search syntax and date filters. The **Search Messages** action searches a Gmail mailbox and returns matching message IDs. Its query uses the same operators as Gmail's search bar. ## Inputs | Input | Type | Required | Description | | ------------------------ | -------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account whose mailbox is searched. | | **Query** | String | Yes | Gmail search query. Whitespace-only text is ignored. | | **Max Results** | Number | No | Maximum IDs to return, from `1` to `100`. Defaults to `10`. | | **Include Spam & Trash** | Boolean | No | Whether Spam and Trash are included. Defaults to `false`. | | **After Date** | Date | No | Only messages after this calendar date. | | **Before Date** | Date | No | Only messages before this calendar date. | The date inputs are appended to the Gmail query using `after:YYYY/M/D` and `before:YYYY/M/D`. You can combine them with operators in **Query**: ```text theme={null} from:billing@example.com has:attachment ``` ## Outputs | Output | Type | Description | | --------------- | --------------- | ------------------------------------ | | **Message IDs** | List of strings | Gmail IDs for the matching messages. | This action returns identifiers only. Repeat over **Message IDs** and use **Get Message by ID** when you need subjects, bodies, or attachments. ## Example: process recent invoices Configure **Search Messages** with: * **Query** — `subject:invoice has:attachment` * **After Date** — The start of the current month. Repeat over the returned **Message IDs** and pass each one to **Get Message by ID** to load the invoice email's content and attachments. ## Troubleshooting Test the same query in Gmail, check the date boundaries, and enable **Include Spam & Trash** if those folders should be searched. Increase **Max Results** up to `100`. The action returns a single result page and does not expose pagination. # Send Email Source: https://learn.workflow.dog/reference/actions/gmail/send-email Send a plain-text or HTML email from a connected Gmail account. The **Send Email** action sends a new message from a connected Google account. It supports multiple recipients, CC addresses, HTML bodies, and file attachments. ## Quick start Choose the Google account that should appear as the sender. Add at least one **Recipients** item. Add **CC** items only when needed. Set **Subject** and **Body**, then choose **Plain Text** or **HTML** for **Body Type**. Store **Message ID** for message actions or **Thread ID** for thread-level replies. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ---------------------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account that sends the message. | | **Recipients** | List of email strings | Yes | One or more `To` addresses. | | **CC** | List of email strings | No | Carbon-copy recipients. | | **Subject** | String | Yes | Message subject. | | **Body** | String | Yes | Plain-text or HTML message content. | | **Body Type** | `Plain Text` or `HTML` | No | How the body is encoded. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files attached with their filename and content type. | When **Body Type** is **HTML**, the body is sent as HTML. Escape or sanitize untrusted values before inserting them into markup. ## Outputs | Output | Type | Description | | -------------- | ------ | ---------------------------------------------------- | | **Message ID** | String | Gmail ID of the sent message. | | **Thread ID** | String | Gmail ID of the conversation containing the message. | ## Example: send a generated report Create the report file first, then configure **Send Email** with: * **Recipients** — The project subscribers. * **Body Type** — **HTML**. * **Attachments** — The generated report file. Store the returned **Message ID** if another action needs to refer to the sent message. ## Troubleshooting Each recipient and CC value must be a valid email address. Put each address in its own list item. Set **Body Type** to **HTML**. The default is plain text. # Star Message Source: https://learn.workflow.dog/reference/actions/gmail/star Add Gmail's star to one message. The **Star Message** action adds Gmail's built-in `STARRED` label to a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to star. | This action has no output. Use **Is Starred?** when a downstream branch needs the current state as a boolean. # Trash Message Source: https://learn.workflow.dog/reference/actions/gmail/trash-message Move one Gmail message to Trash. The **Trash Message** action moves a Gmail message into Trash. It does not permanently delete the message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to trash. | This action returns no output. A trashed message can be restored with **Untrash Message** while Gmail still retains it. # Unmark as Important Source: https://learn.workflow.dog/reference/actions/gmail/unmark-as-important Remove Gmail's important marker from one message. The **Unmark as Important** action removes Gmail's built-in `IMPORTANT` label from a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to update. | This action changes the selected message and returns no output. # Unstar Message Source: https://learn.workflow.dog/reference/actions/gmail/unstar Remove Gmail's star from one message. The **Unstar Message** action removes Gmail's built-in `STARRED` label from a message. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to unstar. | This action changes the message and returns no output. # Untrash Message Source: https://learn.workflow.dog/reference/actions/gmail/untrash-message Restore one Gmail message from Trash. The **Untrash Message** action removes a Gmail message from Trash. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------- | | **Third-party account** | Google account | Yes | Gmail account containing the message. | | **Message ID** | String | Yes | Gmail ID of the message to restore. | This action can restore a message that is still in Trash. It cannot recover a message that Gmail has permanently deleted. # Check Availability Source: https://learn.workflow.dog/reference/actions/google-calendar/check-availability Check whether a Google Calendar has any conflicts during a specific time. The **Check Availability** action checks one calendar for busy periods between two times. Use it before scheduling an event, offering an appointment, or continuing a workflow only when a calendar is free. ## Quick start Choose the Google account whose calendar you want to check. Provide **Starting At** and **Ending At**, then choose the **Timezone** used for the availability request. Leave **Calendar ID** empty to check the account's primary calendar, or enter another calendar's ID. Route **Is Available?** into conditional logic. Inspect **Busy Periods** when you need the exact conflicts. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------ | | **Third-party account** | Google account | Yes | The Google account used to read free/busy information. | | **Starting At** | Date | Yes | Beginning of the time window to check. | | **Ending At** | Date | Yes | End of the time window to check. | | **Calendar ID** | String | No | Calendar to check. Defaults to `primary`. | | **Timezone** | Timezone string | Yes | Timezone supplied to Google for the free/busy query. | ## Outputs | Output | Type | Description | | ----------------- | -------------------- | -------------------------------------------------------------- | | **Is Available?** | Boolean | `true` when Google returns no busy periods in the time window. | | **Busy Periods** | List of busy periods | Conflicts, each with a **Start** and **End** date. | Availability is based on busy periods from the selected calendar. The action does not inspect other calendars attached to the account. ## Example: guard event creation Connect the requested start and end times to **Check Availability**, then branch on **Is Available?**: * When `true`, create the calendar event. * When `false`, use **Busy Periods** to prepare a message offering another time. ## Troubleshooting **Calendar ID** defaults to the account's primary calendar. Supply the intended calendar ID when checking a shared, team, or secondary calendar. Confirm that the connected account can access the Calendar ID and that the account still has a Calendar free/busy or read scope. # Create Event Source: https://learn.workflow.dog/reference/actions/google-calendar/create-event Create an event in Google Calendar and optionally invite attendees. The **Create Event** action adds a timed event to Google Calendar. It can set the event's details, invite multiple attendees, and optionally send Google Calendar notifications. ## Quick start Choose a Google account with permission to create calendar events. Set **Summary**, **Starting At**, **Ending At**, and **Timezone**. Add a description or location when they help attendees. Add one **Attendees** item for each email address that should be invited. Pass **Event ID** to later Calendar actions or send **Event Link** to a person who needs to open the event. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------------- | -------- | -------------------------------------------------------------------- | | **Third-party account** | Google account | Yes | The Google account that creates the event. | | **Summary** | String | Yes | Event title. | | **Starting At** | Date | Yes | Event start date and time. | | **Ending At** | Date | Yes | Event end date and time. | | **Description** | String | No | Additional event details. | | **Location** | String | No | Physical or virtual location text. | | **Attendees** | List of email strings | No | People to invite. Defaults to an empty list. | | **Send Notifications** | Boolean | No | Whether Google emails attendees about the event. Defaults to `true`. | | **Calendar ID** | String | No | Calendar that receives the event. Defaults to `primary`. | | **Timezone** | Timezone string | Yes | Timezone attached to the event's start and end. | ## Outputs | Output | Type | Description | | -------------- | ------ | --------------------------------------------- | | **Event ID** | String | Google's identifier for the created event. | | **Event Link** | String | Link that opens the event in Google Calendar. | **Send Notifications** defaults to on. Turn it off before testing with real attendee addresses if you do not want Google to email them. ## Example: schedule an approved request After a meeting request is approved, check the requested time with **Check Availability**. If the calendar is free, create the event and include the returned **Event Link** in a confirmation email to the requester. Use the same start, end, Calendar ID, and timezone for the availability check and event creation so the event is written to the calendar you checked. ## Troubleshooting Empty **Calendar ID** means the connected account's primary calendar. Supply the target calendar ID for shared or secondary calendars. Every attendee must be a valid email address. Remove names or surrounding text and pass only the email address. # Find Free Time Source: https://learn.workflow.dog/reference/actions/google-calendar/find-free-time Find open periods of a minimum length in a Google Calendar. The **Find Free Time** action returns gaps between busy periods on one Google Calendar. Use it to propose appointment windows, locate focus time, or search a calendar before creating an event. ## Quick start Set **Starting At** and **Ending At** to bound the search. Enter the shortest useful slot in minutes. The default is `30`. Leave **Calendar ID** empty for the primary calendar and select the **Timezone** used for the free/busy request. Use **Free Slots** as a list, or repeat the next workflow steps for each slot's **Start** and **End**. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read free/busy data. | | **Starting At** | Date | Yes | Beginning of the search range. | | **Ending At** | Date | Yes | End of the search range. | | **Minimum Duration** | Number | No | Minimum slot length in minutes. Must be at least `1`; default `30`. | | **Calendar ID** | String | No | Calendar to search. Defaults to `primary`. | | **Timezone** | Timezone string | Yes | Timezone supplied to Google for the free/busy query. | ## Outputs | Output | Type | Description | | -------------- | ------------------ | ------------------------------------------------ | | **Free Slots** | List of time slots | Open periods, each with a **Start** and **End**. | The action sorts busy periods by start time, then returns qualifying open time before the first conflict, between conflicts, and after the last conflict. Slots shorter than **Minimum Duration** are omitted rather than shortened or combined. The output can be an empty list. That means the selected calendar has no qualifying gap inside the requested range. ## Example: propose appointment options Search the acceptable scheduling window, take the first three items from **Free Slots**, and format their **Start** and **End** values into an availability message. The recipient can then choose among those options. ## Troubleshooting Check that **Ending At** is after **Starting At**, reduce **Minimum Duration**, widen the search range, and verify the Calendar ID. **Minimum Duration** is a filter, not a requested slot size. A two-hour opening remains one two-hour slot even when the minimum is 30 minutes. # Get Event Source: https://learn.workflow.dog/reference/actions/google-calendar/get-event Retrieve the details of one Google Calendar event. The **Get Event** action loads one event by its Google Calendar event ID. Use it when a workflow already has an event identifier and needs current event details, attendees, links, or ownership information. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read the event. | | **Event ID** | String | Yes | Google's identifier for the event. | | **Calendar ID** | String | No | Calendar containing the event. Defaults to `primary`. | **Event ID** is available from **Create Event** and from each item returned by **List Events**. ## Outputs | Output | Type | Description | | ---------------- | --------------- | --------------------------------------------------------------- | | **Summary** | String | Event title. | | **Description** | String | Event description, when present. | | **Location** | String | Event location, when present. | | **Start** | Date | Event start. | | **End** | Date | Event end. | | **Is All Day?** | Boolean | Whether Google represents the event without a start date-time. | | **Status** | String | Google status such as `confirmed`, `tentative`, or `cancelled`. | | **Event Link** | String | Link that opens the event in Google Calendar. | | **Meeting Link** | String | Google Meet or Hangout link, when present. | | **Attendees** | List of strings | Attendee email addresses. | | **Creator** | String | Event creator's email address, when available. | | **Organizer** | String | Event organizer's email address, when available. | Some event fields may be empty because Google did not provide them. All-day events still return **Start** and **End** as dates and set **Is All Day?** to `true`. ## Example: send an event reminder Pass a previously stored event ID to **Get Event**, then build the reminder from the returned **Summary**, **Start**, **Meeting Link**, and **Event Link**. Empty meeting links can be omitted when the event has no online meeting. ## Troubleshooting Event IDs are resolved inside a calendar. Supply the same Calendar ID that contains the event; leaving it blank searches the primary calendar. Google only returns this value when the event has an associated Google Meet or Hangout link. # List Events Source: https://learn.workflow.dog/reference/actions/google-calendar/list-events List Google Calendar events in chronological order. The **List Events** action retrieves events from one Google Calendar. Narrow the results by time range and free-text query, then process the returned events as a list or repeat over them one at a time. ## Quick start Choose an account that can read the calendar. Optionally provide **Starting At**, **Ending At**, or **Query**. Leave both dates empty when you do not want a time bound. Leave **Calendar ID** empty for the primary calendar. Set **Max Results** between `1` and `250`; it defaults to `50`. Connect the entire **Events** list or repeat downstream actions for each event. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read events. | | **Starting At** | Date | No | Earliest event time to include. | | **Ending At** | Date | No | Latest event time to include. | | **Calendar ID** | String | No | Calendar to list. Defaults to `primary`. | | **Max Results** | Number | No | Maximum returned events, from `1` to `250`. Defaults to `50`. | | **Query** | String | No | Free-text terms passed to Google Calendar search. | | **Timezone** | Timezone string | Yes | Timezone supplied with the Calendar request. | ## Outputs **Events** is a list ordered by start time. Recurring events are expanded into individual occurrences. | Event field | Type | Description | | ---------------- | ------- | ----------------------------------------------------------- | | **ID** | String | Unique event identifier. | | **Summary** | String | Event title. | | **Description** | String | Event description, when present. | | **Location** | String | Event location, when present. | | **Start** | Date | Event start. | | **End** | Date | Event end. | | **Is All Day?** | Boolean | Whether the event has a date rather than a date-time start. | | **Status** | String | Status such as `confirmed`, `tentative`, or `cancelled`. | | **Event Link** | String | Link to the event in Google Calendar. | | **Meeting Link** | String | Google Meet or Hangout link, when present. | | **Creator** | String | Creator email address, when available. | | **Organizer** | String | Organizer email address, when available. | This action returns one page of results only. If more events match than **Max Results**, later matches are not included. ## Example: prepare a daily agenda Set **Starting At** and **Ending At** to the beginning and end of the day, then repeat over **Events**. Format each event's **Summary**, **Start**, and **Meeting Link** into an agenda before sending the completed message. ## Troubleshooting Verify the date boundaries, Calendar ID, Query, and **Max Results**. The query uses Google Calendar's free-text search and can narrow the result set. Recurring series are expanded into their individual occurrences so each scheduled instance can be processed separately. # Create Form Source: https://learn.workflow.dog/reference/actions/google-forms/create-form Create a blank Google Form with a title. The **Create Form** action creates a new blank Google Form. Use it when a workflow needs a fresh form whose questions or sharing settings will be managed separately. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ---------------------------------------------- | | **Third-party account** | Google account | Yes | The Google account that owns the new form. | | **Title** | String | Yes | Title used for both the form and its document. | ## Outputs | Output | Type | Description | | ----------- | ------ | ----------------------------------------- | | **Form ID** | String | Google's identifier for the created form. | The action creates the form itself but does not add questions. Store **Form ID** if later workflow steps or external tools need to configure it. ## Example: create a form for a new project When a project is created, build a descriptive title such as *Project name feedback* and pass it to **Create Form**. Store the returned **Form ID** with the project so later steps can find and configure the correct form. # Get Form Details Source: https://learn.workflow.dog/reference/actions/google-forms/get-form Retrieve metadata and settings for a Google Form. The **Get Form Details** action retrieves one Google Form by ID or URL. Use it to confirm a form's identity, read its titles and settings, or get the public response URL. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read the form. | | **Form ID or URL** | String | Yes | A Google Form ID or a URL containing the form ID. | The action accepts a direct ID. For a URL, it extracts the value after `/forms/d/`. Use the form's edit URL when you have one. The public responder URL is also returned by the action for sharing with respondents. ## Outputs | Output | Type | Description | | ------------------ | ------ | -------------------------------------- | | **Form ID** | String | Unique form identifier. | | **Title** | String | Title displayed inside the form. | | **Document Title** | String | Title of the Google Forms document. | | **Settings** | Object | Form configuration returned by Google. | | **Revision ID** | String | Current form revision identifier. | | **Responder URI** | String | URL where people can submit responses. | ## Example: publish a response link Retrieve the form using its stored ID, then add **Responder URI** to a confirmation email. Recipients can use that URL to open the public form and submit a response. ## Troubleshooting Paste the direct ID or a standard Google Forms URL containing `/forms/d/`. Confirm the connected Google account has access to the form. Google stores the form's displayed title separately from the document title. Choose the output that matches where you intend to show it. # Chat Source: https://learn.workflow.dog/reference/actions/google-genai/chat Generate a text response with a Google Gemini model. The Google Gemini **Chat** action sends one prompt and an optional system instruction to a Gemini model. It returns the model's response as text. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------------- | -------- | ---------------------------------------------------------------------------------------------------------- | | **Third-party account** | Google Generative AI account | Yes | The API key used for the request. | | **Prompt** | String | Yes | The user request sent to Gemini. | | **Model** | Enum | Yes | Gemini 2.5 Pro, 2.5 Flash, 2.0 Flash, 2.0 Flash Lite, 1.5 Pro, or 1.5 Flash. Defaults to Gemini 2.5 Flash. | | **Temperature** | Number | No | Response randomness from `0` to `2`. Defaults to `1`. | | **System Prompt** | String | No | Instructions that define role, style, or constraints. | ## Output | Output | Type | Description | | ------------ | ------ | -------------------------------- | | **Response** | String | Gemini's complete text response. | This action is stateless and text-only. Include all required context in the current prompt, and use a separate action when you need image generation. # Generate Image Source: https://learn.workflow.dog/reference/actions/google-genai/generate-image Create an image with a Google Gemini image model. The Google Gemini **Generate Image** action returns one generated image file. It supports a broad set of aspect ratios and model-dependent output resolution. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------------- | --------- | --------------------------------------------------------------------------------- | | **Third-party account** | Google Generative AI account | Yes | The API key used for generation. | | **Prompt** | String | Yes | A description of the image to create. | | **Model** | Enum | Yes | Gemini 2.5 Flash Image or Gemini 3 Pro Image. Defaults to Gemini 2.5 Flash Image. | | **Aspect Ratio** | Enum | Yes | `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, or `21:9`. | | **Image Size** | Enum | Sometimes | `1K`, `2K`, or `4K`; shown only for Gemini 3 Pro Image. Defaults to `2K`. | ## Output | Output | Type | Description | | --------- | ---- | ---------------------------------------------------------- | | **Image** | File | The generated image with the MIME type returned by Gemini. | WorkflowDog makes up to three generation attempts when Gemini returns no image data. The action fails if all attempts produce no image. Pick the aspect ratio for the destination first—such as `9:16` for a story or `16:9` for a banner—then describe composition with that frame in mind. # Append Values to Range Source: https://learn.workflow.dog/reference/actions/google-sheets/append-values Append one or more rows at the end of a Google Sheets data range. The **Append Values to Range** action adds rows after the existing data found within an A1 range. Google inserts rows and treats values as user-entered input. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | ------------------------------------------------ | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet to update. | | **Range** | String | Yes | A1 table range, such as `Sheet1!A:B`. | | **Rows** | List of lists | Yes | Rows of string or numeric cell values to append. | ## Outputs | Output | Type | Description | | ----------------- | ------ | --------------------------------------------- | | **Updated Range** | String | A1 range occupied by the newly appended rows. | Appended rows take on the table's existing formatting behavior. The range tells Google where to detect the table; it is not necessarily the exact output range. ## Example For each new order, build a row containing the order ID, customer, and total, then append it to `Orders!A:C`. Store **Updated Range** if later actions need to locate the cells that were added. # Create Range from Parts Source: https://learn.workflow.dog/reference/actions/google-sheets/build-range Build Google Sheets A1 notation from row and column components. The **Create Range from Parts** action constructs an A1 range string without calling Google. It accepts column letters or one-based column numbers and automatically quotes sheet names containing punctuation or spaces. ## Inputs | Input | Type | Required | Description | | ---------------- | ---------------- | -------- | ------------------------------------------------------ | | **Sheet Name** | String | No | Sheet qualifier to place before `!`. | | **Start Column** | String or number | Yes | Starting column, such as `A` or `1`. | | **Start Row** | Number | No | Starting row. Omit for a full-column range. | | **End Column** | String or number | No | Ending column. Omit with End Row for a single address. | | **End Row** | Number | No | Ending row. | ## Outputs | Output | Type | Description | | --------- | ------ | ------------------------------- | | **Range** | String | Constructed A1 notation string. | ## Examples | Parts | Result | | ----------------------------------------- | --------------------- | | Start Column `1`, Start Row `2` | `A2` | | Start Column `A`, End Column `C` | `A:C` | | Sheet `Sales 2026`, Start `A1`, End `D20` | `'Sales 2026'!A1:D20` | Use this action when row or column bounds come from earlier steps, then pass **Range** to Read, Write, Clear, or Highlight Range. # Clear Range Source: https://learn.workflow.dog/reference/actions/google-sheets/clear-range Remove values from a Google Sheets range without deleting its cells. The **Clear Range** action removes cell values from an A1 range. It does not delete rows, columns, or the sheet itself. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | ------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet to update. | | **Range** | String | Yes | A1 range to clear, such as `Sheet1!A2:D20`. | Clearing values preserves the range's structure and formatting. Use **Delete Row(s)** when subsequent rows should shift upward. This action returns no output. Double-check dynamically built ranges before clearing them. # Create Sheet Source: https://learn.workflow.dog/reference/actions/google-sheets/create-sheet Add a blank sheet to an existing Google Spreadsheet. The **Create Sheet** action adds a blank tab to an existing spreadsheet. Use **Create Table** instead when the new sheet should also receive column headers. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | --------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access to the spreadsheet. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet that receives the sheet. | | **Sheet Name** | String | Yes | Title for the new sheet tab. | This action returns no output. Use **Get Spreadsheet Details** after creation if you need the new sheet's numeric ID. ## Troubleshooting Sheet titles must be unique within a spreadsheet. Choose a different name or write to the existing sheet. # Create Spreadsheet Source: https://learn.workflow.dog/reference/actions/google-sheets/create-spreadsheet Create a new Google Spreadsheet. The **Create Spreadsheet** action creates a new Google Sheets file owned by the connected account. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------- | | **Third-party account** | Google account | Yes | Google account that owns the spreadsheet. | | **Title** | String | Yes | Title of the new spreadsheet. | ## Outputs | Output | Type | Description | | ------------------- | ------ | ---------------------------------------- | | **Spreadsheet ID** | String | Google's identifier for the spreadsheet. | | **Spreadsheet URL** | String | URL that opens the spreadsheet. | Use either output as **Spreadsheet ID or URL** in later Google Sheets actions. ## Example When a new client is added: 1. Create a spreadsheet for the client. 2. Connect **Spreadsheet ID** to **Create Table** to initialize its columns. 3. Store **Spreadsheet URL** wherever your team tracks client resources. # Create Table Source: https://learn.workflow.dog/reference/actions/google-sheets/create-table Create a new sheet with headers and optional header formatting. The **Create Table** action creates a new sheet and writes a header row. It can format the headers and freeze all rows through the selected header row. ## Inputs | Input | Type | Required | Description | | --------------------------- | --------------- | -------- | ----------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet that receives the new sheet. | | **Sheet Name** | String | Yes | New sheet tab name. | | **Headers** | List of strings | Yes | One or more column headers, written from column A. | | **Header Row Number** | Number | No | One-based row containing headers. Defaults to `1`. | | **Apply Header Formatting** | Boolean | No | Add bold text, light-gray fill, and cell borders. Default `true`. | | **Freeze Header Row** | Boolean | No | Freeze rows through the header row. Defaults to `true`. | If **Header Row Number** is `3` and freezing is enabled, rows 1 through 3 are frozen—not only row 3. This action creates a new sheet every time it runs and has no output. It cannot add table headers to an existing sheet. ## Troubleshooting Use the same **Header Row Number** in later table actions. Those actions default to row `1`. # Delete Row(s) Source: https://learn.workflow.dog/reference/actions/google-sheets/delete-row Delete one or more numbered rows from a Google Sheet. The **Delete Row(s)** action removes complete rows from a sheet. Cells below the deleted rows shift upward. ## Inputs | Input | Type | Required | Description | | ------------------------- | --------------- | -------- | -------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the rows. | | **Sheet Name** | String | Yes | Exact sheet tab title. | | **Row Numbers** | List of numbers | Yes | One-based row numbers to delete. | Row numbers are deduplicated and grouped into consecutive ranges before the request is sent. This action deletes entire rows, including cells outside a logical table, and returns no output. Row numbers refer to the sheet before the deletion request. ## Troubleshooting Row numbers are absolute sheet positions, starting at `1`; they are not relative to the configured header row. # Delete Sheet Source: https://learn.workflow.dog/reference/actions/google-sheets/delete-sheet Delete a sheet tab from a Google Spreadsheet. The **Delete Sheet** action permanently removes one sheet tab and its cell data from a spreadsheet. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | ----------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the sheet. | | **Sheet Name** | String | Yes | Exact title of the sheet to delete. | This action deletes the entire sheet and returns no output. Use **Clear Range** when you only want to remove cell values. ## Troubleshooting Sheet-name matching is exact. Use **Get Spreadsheet Details** to inspect the available titles. # Find Table Row(s) by Column Source: https://learn.workflow.dog/reference/actions/google-sheets/find-rows-by-column Find Google Sheets table rows using one or more typed column filters. The **Find Table Row(s) by Column** action filters a header-based table and returns either the first match or every matching row. Multiple filters use AND logic: a row must satisfy all of them. ## Inputs | Input | Type | Required | Description | | --------------------------- | --------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with read access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to search. | | **Filters** | List of filters | Yes | One or more column comparisons. | | **Find Multiple Rows?** | Boolean | No | Return every match instead of only the first. Default `false`. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Return Formatted Values** | Boolean | No | Format returned row values. Comparisons always use raw values. | Each filter has a **Column Name**, **Match Mode**, and—when required—a **Search Value**. Column names resolve to the closest header ignoring capitalization, within a small spelling distance. ### Match modes | Mode | Behavior | | ------------------------------ | -------------------------------------------------------- | | **Exact Value** | Loosely compares strings, numbers, or booleans. | | **Empty** / **Not Empty** | Checks for `null`, missing, or empty-string values. | | **Contains Text** | Case-insensitive substring match. | | **Matches Regex** | Tests the string representation with the supplied regex. | | **Greater/Less Than** variants | Compare raw numeric cells only. | | **Is True** / **Is False** | Match actual boolean values. | | **Is Truthy** / **Is Falsy** | Test the raw value's truthiness. | ## Outputs **Found** is always available. Other outputs depend on **Find Multiple Rows?**: \| Output | Type | Description | | -------------- | ------ | \-------------------------------------------- | | **Found** | Boolean| Whether a match exists. | | **Row Data** | Object | First matching row, or empty when not found. | | **Row Number** | Number | One-based sheet row, or empty when not found. | \| Output | Type | Description | | --------------- | --------------- | \------------------------------------- | | **Found** | Boolean | Whether any match exists. | | **Rows** | List of objects | All matching rows. | | **Row Numbers** | List of numbers | Corresponding one-based row numbers. | Switching **Find Multiple Rows?** changes the node's output shape. Recheck downstream connections after toggling it. ## Example: find unpaid large invoices Add two filters: * **Status** → **Exact Value** → `Unpaid` * **Amount** → **Greater Than** → `1000` Then pass **Row Numbers** to **Update Table Row(s)** or **Delete Row(s)**. ## Troubleshooting Verify **Header Row Number** and inspect the header cells. The action allows small spelling differences but cannot infer unrelated names. Numeric modes only match raw numeric cells. A number stored as text does not qualify, even if its displayed characters look numeric. # Get First N Table Rows Source: https://learn.workflow.dog/reference/actions/google-sheets/get-first-n-table-rows Read the first N data rows below a Google Sheets header. The **Get First N Table Rows** action reads rows immediately below a table's header and returns them as objects keyed by the header values. ## Inputs | Input | Type | Required | Description | | --------------------------- | -------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with read access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to read. | | **Number of Rows** | Number | Yes | Maximum rows to read; must be at least `1`. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Return Formatted Values** | Boolean | No | Return display text instead of raw values. Default `false`. | ## Outputs | Output | Type | Description | | -------- | ------------------- | ------------------------------------------- | | **Rows** | List of row objects | First available data rows keyed by headers. | The header row is not included. If fewer populated rows exist in the requested range, the output list is shorter. # Get Last N Table Rows Source: https://learn.workflow.dog/reference/actions/google-sheets/get-last-n-table-rows Read the last N populated rows from a Google Sheets table. The **Get Last N Table Rows** action finds the end of a table and returns up to the requested number of final data rows as header-keyed objects. ## Inputs | Input | Type | Required | Description | | --------------------------- | -------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with Sheets write access, required to locate the table end. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to read. | | **Number of Rows** | Number | Yes | Maximum rows to return; must be at least `1`. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Return Formatted Values** | Boolean | No | Return display text instead of raw values. Default `false`. | ## Outputs | Output | Type | Description | | -------- | ------------------- | -------------------------------------- | | **Rows** | List of row objects | Final table rows keyed by header text. | The header row is excluded. If the table has fewer than N data rows, all available rows are returned. The action determines the append position using column A. Tables should have consistent data in their first column for reliable end-of-table detection. # Get Spreadsheet Details Source: https://learn.workflow.dog/reference/actions/google-sheets/get-spreadsheet Retrieve a Google Spreadsheet's title, URL, ID, and sheets. The **Get Spreadsheet Details** action reads workbook-level metadata without loading cell data. Use it to validate a spreadsheet or discover the sheets it contains. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | ---------------------------------------------------- | | **Third-party account** | Google account | Yes | Account used to read the spreadsheet. | | **Spreadsheet ID or URL** | String | Yes | Direct spreadsheet ID or standard Google Sheets URL. | ## Outputs | Output | Type | Description | | ------------------ | -------------- | --------------------------------- | | **Spreadsheet ID** | String | Unique spreadsheet identifier. | | **Title** | String | Spreadsheet title. | | **URL** | String | URL that opens the spreadsheet. | | **Sheets** | List of sheets | Sheet metadata in workbook order. | Each **Sheets** item contains: | Field | Type | Description | | ------------ | ------ | ------------------------------------------------ | | **Sheet ID** | String | Numeric Google sheet ID represented as a string. | | **Title** | String | Sheet tab name. | | **Index** | Number | Zero-based position of the sheet tab. | A spreadsheet is the whole file; a sheet is one tab inside it. Most table and row actions expect a sheet title, not the numeric Sheet ID. # Get Table Row(s) Source: https://learn.workflow.dog/reference/actions/google-sheets/get-table-row Read numbered Google Sheets rows as objects keyed by column headers. The **Get Table Row(s)** action reads specific absolute row numbers and turns each row into an object whose keys come from the table's header row. ## Inputs | Input | Type | Required | Description | | --------------------------- | --------------- | -------- | ------------------------------------------------------------ | | **Third-party account** | Google account | Yes | Account with read access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to read. | | **Row Numbers** | List of numbers | Yes | One-based absolute sheet rows. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Return Formatted Values** | Boolean | No | Return display text rather than raw values. Default `false`. | ## Outputs | Output | Type | Description | | -------- | ------------------- | --------------------------------------------- | | **Rows** | List of row objects | Requested rows keyed by their column headers. | Missing cell values become `null`. Duplicate row numbers are read once, and the result is returned in ascending row order. The output does not include row numbers. Keep the input list when later actions need to update or delete the same positions. # Get Table Row Range(s) Source: https://learn.workflow.dog/reference/actions/google-sheets/get-table-row-range Read one or more inclusive row ranges as table objects. The **Get Table Row Range(s)** action reads inclusive row-number ranges and maps their cells to table headers. ## Inputs | Input | Type | Required | Description | | --------------------------- | -------------- | -------- | ----------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with read access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to read. | | **Row Ranges** | List of ranges | Yes | **Start Row** and inclusive **End Row** for each range. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Return Formatted Values** | Boolean | No | Return display text instead of raw values. Default `false`. | Every row number is one-based and absolute within the sheet. An end row smaller than its start row is rejected. ## Outputs | Output | Type | Description | | ------------- | ------------------- | --------------------------------------------------- | | **Row Count** | Number | Number of rows actually returned. | | **Rows** | List of row objects | Rows keyed by header text, flattened across ranges. | The result can contain fewer rows than requested when the sheet has no values for some positions. ## Troubleshooting Reverse the bounds for the affected range. Both endpoints are inclusive. # Highlight Range Source: https://learn.workflow.dog/reference/actions/google-sheets/highlight-range Set the background color of a Google Sheets range. The **Highlight Range** action changes the background color of every cell in an A1 range. ## Inputs | Input | Type | Required | Description | | ------------------------- | -------------- | -------- | ------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet to format. | | **Range** | String | Yes | A1 range, such as `Sheet1!A1:B2`. | | **Color** | Hex color | No | Six-digit `#RRGGBB` color. Defaults to `#FFD230`. | When the range does not include a sheet name, the action formats the first sheet in the spreadsheet. This action changes only the cells' background color and returns no output. It does not alter values, fonts, borders, or number formats. ## Troubleshooting Use a hash followed by exactly six hexadecimal digits, such as `#98FB98`. Three-digit shorthand and alpha-channel colors are not accepted. # Insert Table Rows Source: https://learn.workflow.dog/reference/actions/google-sheets/insert-table-rows Append, insert, or overwrite rows using Google Sheets column headers. The **Insert Table Rows** action maps named values to a sheet's headers, then appends them or writes them at a specific row. It is easier to maintain than a raw range write when a table's columns have meaningful names. ## Inputs | Input | Type | Required | Description | | ------------------------- | ------------------- | -------- | ------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab containing the table. | | **Rows** | List of row objects | Yes | Column/value pairs for each row. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | | **Row Number** | Number | No | One-based destination. Omit to append after existing data. | | **Overwrite** | Boolean | No | With Row Number, replace cells instead of inserting new rows. | For each row object, column names are matched to the closest header ignoring capitalization, within a small spelling distance. Missing columns become empty cells. ## Behavior by mode Leave **Row Number** empty. Sheets appends the rows after its detected table and returns the appended **Updated Range**. Provide **Row Number** and leave **Overwrite** off. New sheet rows are inserted at that position, shifting existing rows down. Provide **Row Number** and enable **Overwrite**. Values replace cells in the destination rows without shifting existing data. ## Outputs | Output | Type | Description | | ----------------- | ------ | ------------------------------- | | **Updated Range** | String | A1 range written by the action. | In insert and overwrite modes, values are written as strings. Missing column values are written as empty strings across the table width. ## Troubleshooting Confirm **Header Row Number** and the sheet name, then use column names close to the visible header text. # Parse Range Source: https://learn.workflow.dog/reference/actions/google-sheets/parse-range Split Google Sheets A1 notation into sheet, row, and column fields. The **Parse Range** action converts A1 notation into structured fields without calling Google Sheets. ## Inputs | Input | Type | Required | Description | | --------- | ------ | -------- | -------------------------------------------- | | **Range** | String | Yes | A1 notation such as `Sheet1!A1:B2` or `A:C`. | Input column letters must be uppercase and contain no more than three letters. Quoted sheet names are accepted. ## Outputs | Output | Type | Description | | ----------------------- | ------- | ---------------------------------------------- | | **Sheet Name** | String | Sheet qualifier, or empty when omitted. | | **Start Column Letter** | String | Starting column letter. | | **Start Column Number** | Number | One-based starting column number. | | **Start Row** | Number | Starting row, or empty for full-column ranges. | | **End Column Letter** | String | Ending column letter, when present. | | **End Column Number** | Number | One-based ending column, when present. | | **End Row** | Number | Ending row, when present. | | **Is Single Cell?** | Boolean | Whether the notation identifies one cell. | ## Troubleshooting Use uppercase A1 notation. Examples include `A1`, `A1:B20`, `A:C`, and `'Sales Data'!B2:D10`. # Read Range Source: https://learn.workflow.dog/reference/actions/google-sheets/read-range Read a Google Sheets range as rows or columns. The **Read Range** action reads cell values from an A1 range. Choose whether the outer output list represents rows or columns and whether values use their display formatting. ## Inputs | Input | Type | Required | Description | | --------------------------- | ------------------- | -------- | -------------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with read access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet to read. | | **Range** | String | Yes | A1 range, such as `Sheet1!A1:B20`. | | **Major Dimension** | `Rows` or `Columns` | No | Structure of the outer list. Defaults to **Rows**. | | **Return Formatted Values** | Boolean | No | Return display strings instead of raw values. Default `false`. | ## Outputs | Output | Type | Description | | ----------------------- | ------------- | ---------------------------------------------------- | | **Rows** or **Columns** | List of lists | Cell values grouped by the selected major dimension. | Formatted values preserve display text such as `$1,234.00` or a rendered date. Raw values are better for numeric comparisons and calculations. Sheets can omit trailing empty cells and rows from returned arrays. Do not assume every inner list has the full requested width. ## Example Set **Range** to `Sheet1!A2:D` and keep **Major Dimension** set to **Rows**. Repeat over the returned **Rows** to process each row's cells individually. # Update Table Row(s) Source: https://learn.workflow.dog/reference/actions/google-sheets/update-table-row Update selected columns in one or more numbered Google Sheets rows. The **Update Table Row(s)** action writes the same set of named column values to one or more rows. It resolves column names from a header row and leaves unspecified columns unchanged. ## Inputs | Input | Type | Required | Description | | ------------------------- | --------------- | -------- | ------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet containing the table. | | **Sheet Name** | String | Yes | Sheet tab to update. | | **Row Numbers** | List of numbers | Yes | One-based absolute row numbers. | | **Values** | Object | Yes | Column/value pairs applied to every selected row. | | **Header Row Number** | Number | No | One-based header position. Defaults to `1`. | Column names are matched case-insensitively to the closest header within a small spelling distance. Row numbers are sorted and deduplicated. This action applies one **Values** object to every selected row and returns no output. Use separate action runs when different rows need different values. ## Example After finding the overdue rows, pass their row numbers to **Row Numbers** and set **Values** to `{ "Status": "Overdue" }`. The action writes that status to every selected row. ## Troubleshooting Verify the header row and available header text. A blank or substantially different column name cannot be resolved. # Write Range Source: https://learn.workflow.dog/reference/actions/google-sheets/write-range Write user-entered values into a Google Sheets range. The **Write Range** action replaces values in a specified A1 range. Values are interpreted as if a person entered them in Google Sheets, so formulas and recognized dates can be parsed by Sheets. ## Inputs | Input | Type | Required | Description | | ------------------------- | ------------------- | -------- | ------------------------------------------------------- | | **Third-party account** | Google account | Yes | Account with write access. | | **Spreadsheet ID or URL** | String | Yes | Spreadsheet to update. | | **Range** | String | Yes | A1 destination range. | | **Major Dimension** | `Rows` or `Columns` | No | How the outer Values list is interpreted. Default Rows. | | **Rows** or **Columns** | List of lists | Yes | Cell values arranged by the selected dimension. | ## Outputs | Output | Type | Description | | ----------------- | ------ | ------------------------------------ | | **Updated Range** | String | A1 range actually updated by Google. | This action writes over cells in the destination. Use **Append Values to Range** or **Insert Table Rows** when existing data should move rather than be replaced. ## Example With **Major Dimension** set to **Rows**, this value: ```json theme={null} [ ["Name", "Status"], ["Avery", "Active"] ] ``` writes two rows and two columns starting at the first cell of **Range**. # Close Window Source: https://learn.workflow.dog/reference/actions/http/close-window Return a small HTML response that asks the browser window to close. **Close Window** responds with an HTML script that calls `window.close()` after the page loads. It is available with **URL** and **Form Submission** triggers. ## Input | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------------------------------- | | **Status** | Number | No | An HTTP status code from `100` to `599`. Defaults to `200`. | This is useful at the end of popup-based authorization or handoff flows. Browsers commonly allow scripts to close only windows that were opened by script. A normal tab opened directly by the user may remain open. # Make HTTP Request Source: https://learn.workflow.dog/reference/actions/http/fetch Call an external HTTP endpoint and use its body, status, and headers. **Make HTTP Request** sends an outbound request to an external URL. Use it to call REST APIs, submit data to web services, or retrieve text-based resources. This action cannot call internal or private WorkflowDog URLs. Requests to non-external addresses are rejected. ## Inputs | Input | Type | Required | Description | | -------------------- | ------------------------------------------ | ------------------------------ | ------------------------------------------------------------------------------------- | | **URL** | String | Yes | The complete destination URL. | | **Method** | `GET`, `POST`, `PUT`, `PATCH`, or `DELETE` | Yes | The HTTP method. Defaults to `GET`. | | **Body** | String or file | For `POST`, `PUT`, and `PATCH` | The request payload. Its type follows **Content Type** when a known type is selected. | | **Content Type** | String | No | The MIME type sent in the `Content-Type` header. | | **Query Parameters** | List of name/value pairs | No | Parameters added to the URL. Existing parameters with the same name are replaced. | | **Headers** | List of name/value pairs | No | Request headers. | **Body** and **Content Type** are hidden for `GET` and `DELETE` requests. ### Body types Known text types—including `application/json`, `text/plain`, `text/csv`, and XML—use a string body. Known binary types—including `multipart/form-data`, `application/pdf`, and common image types—use a file body. You can also enter a custom MIME type; in that case the body accepts any compatible value. A header added under **Headers** takes precedence over the value generated by **Content Type** when both use the same header name. ## Outputs | Output | Type | Description | | ------------ | ----------------- | ------------------------------------------------------------------ | | **Response** | String | The complete response body read as text. | | **Status** | Number | The HTTP status code, such as `200` or `404`. | | **Headers** | Object of strings | Response headers. Select individual header properties when needed. | The action returns normally for non-success status codes. Branch on **Status** when a workflow must treat `4xx` or `5xx` responses differently. ## Example: send JSON to an API Set **Method** to `POST`, **Content Type** to `application/json`, and connect a JSON string to **Body**: ```json theme={null} { "email": "ada@example.com", "plan": "pro" } ``` Add authentication under **Headers**, then use **Status** to confirm whether the service accepted the request. ## Troubleshooting Use a complete public URL, including `https://`. Internal, loopback, and private destinations are blocked. **Response** is always read as text. Use an integration that returns a file when the response must preserve raw bytes. Confirm that **Content Type** matches the actual payload. Selecting `application/json` does not serialize an object automatically; **Body** must already be a JSON string. # Redirect Source: https://learn.workflow.dog/reference/actions/http/redirect Redirect an HTTP caller to another URL. **Redirect** finishes an HTTP-triggered workflow with a `Location` header. It is available with **URL**, **Form Submission**, and **Webhook** triggers. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------------------------------- | | **URL** | String | Yes | The absolute destination URL. | | **Status** | Number | No | A redirect status from `300` to `399`. Defaults to `302`. | Use `302` for a temporary redirect or `301` for a permanent redirect. Choose `307` or `308` when the caller must preserve its original request method. Permanent redirects can be cached by browsers and intermediaries. Use `302` while testing a workflow. # Respond Text Source: https://learn.workflow.dog/reference/actions/http/respond Finish an HTTP-triggered workflow with a text response. **Respond Text** sends a string back to the client that started the workflow. It is available in workflows using the **URL**, **Form Submission**, or **Webhook** trigger. ## Inputs | Input | Type | Required | Description | | ---------------- | ------ | -------- | ------------------------------------------------------------------------- | | **Body** | String | Yes | The response body. | | **Status** | Number | No | An HTTP status code from `100` to `599`. Defaults to `200`. | | **Content Type** | Enum | Yes | `text/plain`, `text/html`, or `application/json`. Defaults to plain text. | **Content Type** describes the string; it does not transform it. If you select JSON, **Body** must already contain valid JSON. This action ends the waiting HTTP response. Place it on every branch that should return a deliberate result to the caller. # Respond File Source: https://learn.workflow.dog/reference/actions/http/respond-file Return a file for display or download from an HTTP workflow. **Respond File** sends a file back to a **URL** or **Form Submission** caller. The response uses the file's MIME type. ## Inputs | Input | Type | Required | Description | | ------------------- | ------------------------ | -------- | --------------------------------------------------------------------------------- | | **File** | File | Yes | The file to return. | | **Status** | Number | No | An HTTP status code from `100` to `599`. Defaults to `200`. | | **Send Content As** | `Inline` or `Attachment` | Yes | Whether the browser should display the file or download it. Defaults to `Inline`. | Use **Inline** for browser-viewable content such as images or PDFs. Use **Attachment** to send a download; the response includes the file's name. Browser behavior still depends on the file type and the caller's browser settings. # Respond HTML Source: https://learn.workflow.dog/reference/actions/http/respond-html Return an HTML document from a URL or form workflow. **Respond HTML** returns a string with the `text/html` content type. It is available with the **URL** and **Form Submission** triggers. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------------------------------- | | **Body** | String | Yes | The HTML document or fragment to return. | | **Status** | Number | No | An HTTP status code from `100` to `599`. Defaults to `200`. | ```html theme={null}

Thanks — your submission was received.

``` The HTML is sent as provided. Only include markup and scripts you trust. # Respond JSON Source: https://learn.workflow.dog/reference/actions/http/respond-json Serialize a value as JSON and return it to an HTTP caller. **Respond JSON** serializes any connected value and returns it with an `application/json` content type. It works with the **URL**, **Form Submission**, and **Webhook** triggers. ## Inputs | Input | Type | Required | Description | | ---------- | ------- | -------- | ----------------------------------------------------------- | | **Body** | Any | Yes | The value to serialize. | | **Status** | Number | No | An HTTP status code from `100` to `599`. Defaults to `200`. | | **Pretty** | Boolean | No | Adds two-space indentation to the JSON. Defaults to on. | ## Example Connect an object containing `ok` and `orderId` to **Body**. The caller receives: ```json theme={null} { "ok": true, "orderId": "ord_123" } ``` Turn **Pretty** off for smaller production responses. Formatting changes whitespace only, not the returned data. # Respond Status Source: https://learn.workflow.dog/reference/actions/http/respond-status Finish an HTTP request with a status code and no custom body. **Respond Status** returns only an HTTP status. It works with **URL**, **Form Submission**, and **Webhook** triggers. ## Input | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------------------------- | | **Status** | Number | No | A status code from `100` to `599`. Defaults to `200`. | Use this action for acknowledgements such as `204`, authorization failures such as `401`, or not-found responses such as `404`. Because no custom body is supplied, the HTTP server may include the standard status text associated with the selected code. # Adjust Colors Source: https://learn.workflow.dog/reference/actions/images/adjust-colors Change an image's brightness, saturation, contrast, and hue. **Adjust Colors** applies four color adjustments to an image in one pass. Unchanged settings default to zero, so you can adjust only the properties you need. ## Inputs | Input | Type | Required | Description | | -------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------- | | **Image** | File | Yes | The image to adjust. | | **Brightness** | Number | No | From `-100` to `100`. Negative values darken; positive values brighten. Defaults to `0`. | | **Saturation** | Number | No | From `-100` to `100`. Negative values reduce color intensity; positive values increase it. Defaults to `0`. | | **Contrast** | Number | No | From `-100` to `100`. Negative values flatten tonal differences; positive values increase them. Defaults to `0`. | | **Hue** | Number | No | Hue rotation from `0` to `360` degrees. Defaults to `0`. | ## Output | Output | Type | Description | | ------------------ | ---- | -------------------------------------------------------------------- | | **Adjusted Image** | File | The processed image, preserving the input file's name and MIME type. | Adjustments are combined before the result is encoded. Reusing one node for several changes avoids repeatedly decoding and encoding the same image. Make small adjustments first. Extreme brightness, saturation, or contrast values can permanently clip details in the output. # Blur Image Source: https://learn.workflow.dog/reference/actions/images/blur Apply a configurable Gaussian blur to an image. **Blur Image** softens an image with a Gaussian blur. | Direction | Field | Type | Description | | --------- | ----------------- | ------ | ----------------------------------------------------------- | | Input | **Image** | File | The image to blur. | | Input | **Blur Amount** | Number | Blur strength from `0` to `1000`. Defaults to `5`. | | Output | **Blurred Image** | File | The blurred image, preserving the input name and MIME type. | Values below `0.3`, including `0`, return the original file unchanged. Larger values create progressively stronger blur, with processing capped at `1000`. A modest blur is usually enough for soft backgrounds. Use much larger values when the goal is to obscure rather than style image content. # Convert Image Format Source: https://learn.workflow.dog/reference/actions/images/convert-format Convert an image to JPEG, PNG, WebP, AVIF, or TIFF. **Convert Image Format** decodes an image and re-encodes it in a selected image format. The output filename receives the new extension. ## Inputs | Input | Type | Required | Description | | ----------- | ---------------------------------------- | -------- | ------------------------------------------ | | **Image** | File | Yes | The source image. | | **Format** | `jpeg`, `png`, `webp`, `avif`, or `tiff` | Yes | Target encoding. Defaults to `jpeg`. | | **Quality** | Number | No | Value from `1` to `100`. Defaults to `90`. | **Quality** controls lossy quality for JPEG, WebP, AVIF, and TIFF. For PNG, it is translated into a compression level: lower quality values request more compression, but do not intentionally discard pixels in the way JPEG does. ## Output | Output | Type | Description | | ------------------- | ---- | ------------------------------------------------- | | **Converted Image** | File | The re-encoded image with the selected extension. | The current output file may retain the input image's MIME type even though its filename and bytes use the new format. When a downstream service relies strictly on MIME metadata, verify what it receives. Choose PNG when transparency or lossless pixels matter, JPEG for broadly compatible photographs, and WebP or AVIF when smaller modern web assets are more important. # Crop Image Source: https://learn.workflow.dog/reference/actions/images/crop Extract a rectangular region from an image by pixel coordinates. **Crop Image** extracts a rectangle from an image. Coordinates start at the source image's top-left corner. | Direction | Field | Type | Description | | --------- | ----------------- | -------------------- | -------------------------------------------------------------- | | Input | **Image** | File | The source image. | | Input | **Left** | Non-negative integer | Pixels from the source's left edge to the crop's left edge. | | Input | **Top** | Non-negative integer | Pixels from the source's top edge to the crop's top edge. | | Input | **Width** | Positive integer | Width of the crop rectangle in pixels. | | Input | **Height** | Positive integer | Height of the crop rectangle in pixels. | | Output | **Cropped Image** | File | The extracted region, preserving the input name and MIME type. | The full rectangle must fit inside the source image: ```text theme={null} left + width ≤ source width top + height ≤ source height ``` Use **Get Image Dimensions** before this action when crop coordinates are calculated dynamically. The action fails when the requested rectangle extends beyond the image boundary. It does not pad or clamp the crop automatically. # Flip Image Source: https://learn.workflow.dog/reference/actions/images/flip Mirror an image horizontally, vertically, or in both directions. **Flip Image** mirrors an image across either axis. | Direction | Field | Type | Description | | --------- | ----------------- | ------- | ------------------------------------------------------------- | | Input | **Image** | File | The image to flip. | | Input | **Horizontal** | Boolean | Mirrors left to right. Defaults to on. | | Input | **Vertical** | Boolean | Mirrors top to bottom. Defaults to off. | | Output | **Flipped Image** | File | The processed image, preserving the input name and MIME type. | Enable both toggles to mirror across both axes, which is equivalent to a 180-degree rotation. If both are off, the image is reprocessed without a flip. # Generate Gradient Source: https://learn.workflow.dog/reference/actions/images/generate-gradient Create a linear or radial gradient image from a list of colors. **Generate Gradient** creates a new image without requiring an input file. Supply one or more colors, choose a gradient type, and set the output dimensions and format. ## Inputs | Input | Type | Required | Description | | --------------- | ------------------------ | -------------------- | ----------------------------------------------------- | | **Width** | Positive number | Yes | Output width in pixels. Defaults to `800`. | | **Height** | Positive number | Yes | Output height in pixels. Defaults to `600`. | | **Type** | `linear` or `radial` | Yes | Gradient geometry. Defaults to `linear`. | | **Angle** | Number | For linear gradients | Direction from `0` to `360` degrees. Defaults to `0`. | | **Color Stops** | List of strings | Yes | One or more colors. Two entries are shown by default. | | **Format** | `png`, `jpeg`, or `webp` | Yes | Output encoding. Defaults to `png`. | Color stops are placed at even intervals. With three colors, for example, they appear at `0%`, `50%`, and `100%`. A single color produces a solid fill rather than a gradient. Use CSS-compatible color strings such as `#ff006e`. Linear angles are normalized to one full rotation before rendering. **Angle** is hidden for a radial gradient, which is centered in the image. ## Output | Output | Type | Description | | ------------------ | ---- | ----------------------------------------------------------------------- | | **Gradient Image** | File | The generated image, named `gradient-{type}-{width}x{height}.{format}`. | JPEG and WebP are encoded at quality `90`. PNG uses its normal lossless encoding. ## Example: make a three-color background Set the size to `1600` by `900`, choose `linear`, set **Angle** to `135`, and add these color stops in order: ```text theme={null} #111827 #4f46e5 #ec4899 ``` The colors are spaced evenly from the first edge of the gradient to the last. # Get Image Dimensions Source: https://learn.workflow.dog/reference/actions/images/get-dimensions Read an image's pixel width, height, and aspect ratio. **Get Image Dimensions** inspects an image without changing it. | Direction | Field | Type | Description | | --------- | ---------------- | ------ | -------------------------------------------------------- | | Input | **Image** | File | The image to inspect. | | Output | **Width** | Number | Width in pixels. | | Output | **Height** | Number | Height in pixels. | | Output | **Aspect Ratio** | Number | Width divided by height, rounded to four decimal places. | Use the outputs to calculate safe crop coordinates, choose portrait or landscape branches, or resize an image relative to its original dimensions. The action fails when the file cannot be decoded as an image or its dimensions cannot be determined. # Invert Colors Source: https://learn.workflow.dog/reference/actions/images/invert Create a color-negative version of an image. **Invert Colors** replaces each color channel with its inverse while leaving the alpha channel unchanged. | Direction | Field | Type | Description | | --------- | ------------------ | ---- | ------------------------------------------------------------------ | | Input | **Image** | File | The image to invert. | | Output | **Inverted Image** | File | The color-inverted image, preserving the input name and MIME type. | Transparent pixels keep their transparency. Running the result through **Invert Colors** a second time approximately restores the original colors, subject to any encoding loss in the image format. # Modify EXIF Source: https://learn.workflow.dog/reference/actions/images/modify-exif Strip or preserve image metadata and orientation information. **Modify EXIF** controls which metadata is written into an image. Use it to remove identifying metadata before sharing an image or to preserve metadata when another image action would otherwise discard it. ## Inputs | Input | Type | Required | Description | | -------------------- | ------- | -------- | ------------------------------------------------------- | | **Image** | File | Yes | The image to process. | | **Action** | Enum | Yes | Metadata behavior. Defaults to `strip_all`. | | **Keep Orientation** | Boolean | No | Available for `strip_keep_orientation`. Defaults to on. | ### Actions | Action | Behavior | | ------------------------ | ----------------------------------------------------------------------------------------------------------- | | `strip_all` | Writes the image without preserving its existing metadata. | | `strip_keep_orientation` | Uses the orientation-specific path. **Keep Orientation** controls whether orientation metadata is retained. | | `keep_all` | Preserves available metadata in the output. | ## Output | Output | Type | Description | | ------------------- | ---- | ------------------------------------------------------------- | | **Processed Image** | File | The rewritten image, preserving the input name and MIME type. | Metadata handling depends on what the image decoder can read and the output format can store. Inspect the result when privacy or orientation is critical; do not assume every metadata namespace is supported identically. If the goal is privacy, use `strip_all` and verify the final file after all other image actions have run. A later encoder may add fresh technical metadata. # Overlay Images Source: https://learn.workflow.dog/reference/actions/images/overlay Scale and place a foreground image over a background image. **Overlay Images** composites one image over another. The foreground is scaled relative to the background, aligned to one of nine positions, and optionally made translucent. ## Inputs | Input | Type | Required | Description | | -------------- | ------ | -------- | -------------------------------------------------------------------- | | **Background** | File | Yes | The base image and the output canvas. | | **Foreground** | File | Yes | The image placed over the background. | | **Scale** | Number | No | Foreground scale from `0.01` to `1`. Defaults to `0.5`. | | **Position** | Enum | No | One of nine top, center, or bottom alignments. Defaults to `center`. | | **Opacity** | Number | No | Foreground opacity from `0` to `1`. Defaults to `1`. | The node preserves the foreground's aspect ratio. At scale `1`, the foreground is sized to fit the background along the limiting dimension; at `0.5`, that fitted size is halved. Available positions are: ```text theme={null} top-left top-center top-right center-left center center-right bottom-left bottom-center bottom-right ``` ## Output | Output | Type | Description | | ------------------- | ---- | ------------------------------------------------------------------- | | **Composite Image** | File | The combined image, using the background file's name and MIME type. | ## Example: place a watermark Use the source image as **Background**, a transparent logo as **Foreground**, set **Scale** to a small value such as `0.15`, choose `bottom-right`, and lower **Opacity** to `0.6`. Positions align directly to an edge or corner; the action has no margin input. Add transparent padding to the foreground first when the overlay needs inset spacing. ## Troubleshooting Scale is relative to the background's limiting dimension, not the foreground's original size. Reduce **Scale**. The output follows the background file's name and MIME type. Convert the background before overlaying, or convert the composite afterward. # Resize Image Source: https://learn.workflow.dog/reference/actions/images/resize Resize an image in pixels or as a percentage with configurable fit behavior. **Resize Image** changes an image's dimensions. Provide either width, height, or both; when only one dimension is present, the original aspect ratio is preserved. ## Inputs | Input | Type | Required | Description | | -------------- | ------------------------ | ------------- | --------------------------------------------------------------------------- | | **Image** | File | Yes | The image to resize. | | **Unit** | `pixels` or `percentage` | Yes | How width and height are interpreted. Defaults to `pixels`. | | **Width** | Positive number | No | Target width in pixels or as a percentage of original width. | | **Height** | Positive number | No | Target height in pixels or as a percentage of original height. | | **Fit** | Enum | Yes | How the source fits when both dimensions are supplied. Defaults to `cover`. | | **Position** | Enum | Sometimes | Alignment for `cover` or `contain`. Defaults to `center`. | | **Background** | String | For `contain` | Color used to fill empty space. Defaults to `#000000`. | Percentage dimensions are converted from the source metadata and rounded down to whole pixels. For example, width `50` means half of the original width. ### Fit modes | Fit | Behavior | | --------- | ------------------------------------------------------------------------------------------ | | `cover` | Fills both target dimensions, cropping overflow as needed. | | `contain` | Fits the whole image inside the target and fills remaining space with **Background**. | | `fill` | Stretches the image to exactly the requested dimensions, even if the aspect ratio changes. | | `inside` | Preserves aspect ratio and stays within both target dimensions. | | `outside` | Preserves aspect ratio while meeting or exceeding both target dimensions. | **Position** offers top, bottom, left, right, corner, and center alignment for the crop or padding created by `cover` and `contain`. ## Output | Output | Type | Description | | ----------------- | ---- | ----------------------------------------------------------- | | **Resized Image** | File | The resized image, preserving the input name and MIME type. | ## Examples * Set width to `1200`, leave height empty, and use pixels to make a 1200-pixel-wide image without changing its proportions. * Set width and height to `50` with percentage units to halve both dimensions. * Set `1080` by `1080` with `cover` to create a square crop, or `contain` to retain the whole source inside a square canvas. If both width and height are empty, the action has no target size. Provide at least one dimension for predictable output. # Rotate Image Source: https://learn.workflow.dog/reference/actions/images/rotate Rotate an image clockwise and choose the color behind exposed corners. **Rotate Image** rotates an image by any number of degrees. Positive angles rotate clockwise. | Direction | Field | Type | Description | | --------- | ----------------- | ------ | ------------------------------------------------------------------- | | Input | **Image** | File | The image to rotate. | | Input | **Angle** | Number | Rotation in degrees. Defaults to `0`. | | Input | **Background** | String | Color for newly exposed areas. Defaults to transparent `#00000000`. | | Output | **Rotated Image** | File | The rotated image, preserving the input name and MIME type. | Right-angle rotations rearrange the original pixels without exposed triangular corners. Other angles expand the canvas and fill those corners with **Background**. Formats without alpha transparency cannot preserve a transparent background. Choose an opaque color or convert to a transparency-capable format such as PNG. # Sharpen Image Source: https://learn.workflow.dog/reference/actions/images/sharpen Increase edge contrast with a configurable sharpening effect. **Sharpen Image** emphasizes edges and fine detail. | Direction | Field | Type | Description | | --------- | ------------------- | ------ | ------------------------------------------------------------- | | Input | **Image** | File | The image to sharpen. | | Input | **Sharpness** | Number | Strength from `0` to `1000`. Defaults to `50`. | | Output | **Sharpened Image** | File | The sharpened image, preserving the input name and MIME type. | The displayed value is divided by `100` before processing. Values at or very near zero return the original file unchanged; effective processing strength is capped once the displayed value reaches `1000`. Start below the default when sharpening compressed photographs. High values can exaggerate noise, halos, and existing compression artifacts. # Actions Source: https://learn.workflow.dog/reference/actions/index Reference documentation for every action available in WorkflowDog. Actions are the steps that do work after a workflow starts. They can transform values, call another service, make a decision, create a file, send a response, or control which path runs next. This reference documents every action currently available in the editor. Use the navigation to browse by package, or search for the action by the name shown in the node picker. ## Read an action page Every page starts with the action's purpose, then documents the fields and behavior that exist in the current implementation: * **Inputs** are values the action reads. A field can be configured directly, connected from an earlier output, or both, depending on the node. * **Outputs** are values later actions can use. Some outputs appear only when a related option is enabled. * **Third-party account** identifies the connected service account used for an external request. * **Examples** show a representative configuration when the action benefits from one. * **Troubleshooting** calls out common failures and implementation-specific constraints. Many nodes change their visible inputs or outputs when a configuration value changes. Review downstream connections after changing an option that controls the node's shape. ## Static and connected values Configuration fields are normally fixed for the workflow, while connectable inputs can receive a different value on every run. Some fields support either mode. Use a fixed value for behavior that should remain constant, and connect an earlier output when the value belongs to the data being processed. ## Accounts and external services Integration actions require a matching third-party account. The page for each action describes the account type and the request it makes, but access still depends on the permissions, API limits, and data available to that account. When a service action fails, first verify the selected account, then inspect required inputs and service-specific limits documented on that action's page. ## Actions and triggers An action runs because the workflow reached it. A trigger starts a workflow in response to an event or schedule. See the [Triggers reference](/reference/triggers) for every available starting event. # And Source: https://learn.workflow.dog/reference/actions/logic/and Return true only when every input is true. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | ---------------------------------- | | **Result** | Boolean | `true` when every value is `true`. | The node starts with two value slots. If there are no values, the result is `true`. # Buffer Source: https://learn.workflow.dog/reference/actions/logic/buffer Pass a Boolean value through unchanged. | Input | Type | Required | Description | | --------- | ------- | -------- | -------------------------- | | **Value** | Boolean | Yes | The value to pass through. | | Output | Type | Description | | ---------- | ------- | ------------------ | | **Result** | Boolean | The input Boolean. | Use Buffer as a simple connection point while organizing Boolean logic. # Equals Source: https://learn.workflow.dog/reference/actions/logic/equal Check whether two values are strictly equal. | Input | Type | Required | Description | | ----- | ---- | -------- | ------------------------ | | **A** | Any | Yes | First value to compare. | | **B** | Any | Yes | Second value to compare. | | Output | Type | Description | | ---------- | ------- | ------------------------------------------- | | **Result** | Boolean | `true` when both values are strictly equal. | Types must match: the number `1` does not equal the text `"1"`. Objects and lists compare by identity, not by recursively comparing their contents. # NAND Source: https://learn.workflow.dog/reference/actions/logic/nand Return false only when every input is true. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | ---------------------------------------------- | | **Result** | Boolean | The inverse of applying **And** to the values. | For `[true, true]`, the result is `false`. If at least one value is `false`, the result is `true`. With no values, the result is `false`. # NOR Source: https://learn.workflow.dog/reference/actions/logic/nor Return true only when every input is false. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | --------------------------------------------- | | **Result** | Boolean | The inverse of applying **Or** to the values. | The result is `false` as soon as any input is `true`. With no values, the result is `true`. # Not Source: https://learn.workflow.dog/reference/actions/logic/not Invert a Boolean value. | Input | Type | Required | Description | | --------- | ------- | -------- | -------------------- | | **Value** | Boolean | Yes | The value to invert. | | Output | Type | Description | | ---------- | ------- | ------------------------------------------- | | **Result** | Boolean | `false` for `true`, and `true` for `false`. | # Not Equals Source: https://learn.workflow.dog/reference/actions/logic/not-equal Check whether two values are not strictly equal. | Input | Type | Required | Description | | ----- | ---- | -------- | ------------------------ | | **A** | Any | Yes | First value to compare. | | **B** | Any | Yes | Second value to compare. | | Output | Type | Description | | ---------- | ------- | ---------------------------------------------- | | **Result** | Boolean | `true` when the values are not strictly equal. | Types matter: the number `1` and the text `"1"` are not equal. Objects and lists compare by identity. # Or Source: https://learn.workflow.dog/reference/actions/logic/or Return true when at least one input is true. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | ----------------------------------------- | | **Result** | Boolean | `true` when any supplied value is `true`. | If there are no values, the result is `false`. # XNOR Source: https://learn.workflow.dog/reference/actions/logic/xnor Return true when an even number of inputs are true. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | --------------------------------------------- | | **Result** | Boolean | `true` when the count of true values is even. | `[true, true, false]` returns `true`; `[true, false, false]` returns `false`. With no values, the true count is zero, so the result is `true`. # XOR Source: https://learn.workflow.dog/reference/actions/logic/xor Return true when an odd number of inputs are true. | Input | Type | Required | Description | | ---------- | ------------------ | -------- | ------------------- | | **Values** | Repeatable Boolean | No | Values to evaluate. | | Output | Type | Description | | ---------- | ------- | -------------------------------------------- | | **Result** | Boolean | `true` when the count of true values is odd. | `[true, false, false]` returns `true`; `[true, true, false]` returns `false`. With no values, the result is `false`. # Absolute Value Source: https://learn.workflow.dog/reference/actions/math/absolute Return a number's distance from zero. The **Absolute Value** action removes a number's sign. Positive values and zero stay unchanged; negative values become positive. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------- | | **Number** | Number | Yes | The value to transform. | ## Outputs | Output | Type | Description | | ------------ | ------ | --------------------------------- | | **Absolute** | Number | The absolute value of **Number**. | For example, both `-12.5` and `12.5` produce `12.5`. # Add Source: https://learn.workflow.dog/reference/actions/math/add Add two or more numbers. The **Add** action sums a repeatable list of numbers in order. The node requires at least two number inputs and can be expanded for additional values. ## Inputs | Input | Type | Required | Description | | ----------- | --------------- | -------- | -------------------------- | | **Numbers** | List of numbers | Yes | Two or more values to add. | ## Outputs | Output | Type | Description | | ------- | ------ | ---------------------------------- | | **Sum** | Number | The total of all supplied numbers. | Empty repeat slots are treated as `0`. For example, `12`, `8`, and `-5` produce `15`. # Ceil Source: https://learn.workflow.dog/reference/actions/math/ceil Round a number upward to the nearest integer. The **Ceil** action returns the smallest integer greater than or equal to the input. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ------------------- | | **Number** | Number | Yes | The value to round. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------------------- | | **Ceiled** | Number | The input rounded toward positive infinity. | For example, `4.01` becomes `5`, while `-4.99` becomes `-4`. # Clamp Source: https://learn.workflow.dog/reference/actions/math/clamp Keep a number between minimum and maximum limits. The **Clamp** action constrains a number to a range. Values below **Min** become the minimum, values above **Max** become the maximum, and values already inside the range stay unchanged. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | -------------------------- | | **Number** | Number | Yes | The value to constrain. | | **Min** | Number | Yes | The minimum allowed value. | | **Max** | Number | Yes | The maximum allowed value. | ## Outputs | Output | Type | Description | | ----------- | ------ | ----------------------------------- | | **Clamped** | Number | The value constrained to the range. | For a minimum of `0` and maximum of `100`, `-5` becomes `0`, `40` stays `40`, and `125` becomes `100`. Keep **Min** less than or equal to **Max**. Reversed bounds are applied in sequence and produce the maximum bound rather than a conventional range. # Cosine Source: https://learn.workflow.dog/reference/actions/math/cos Calculate the cosine of an angle in radians or degrees. The **Cosine** action calculates the cosine of an angle. ## Inputs | Input | Type | Required | Description | | -------------- | ------------------ | -------- | ------------------------------------------------ | | **Angle** | Number | Yes | The angle to evaluate. | | **Angle Unit** | Radians or Degrees | Yes | How to interpret **Angle**. Defaults to radians. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------ | | **Result** | Number | The cosine of the input angle. | For example, `180` degrees returns approximately `-1`, as does `π` radians. Small floating-point differences are normal. # Divide Source: https://learn.workflow.dog/reference/actions/math/divide Divide two numbers with decimal or integer division. The **Divide** action divides a dividend by a nonzero divisor. It can return a decimal quotient or a whole-number quotient with a remainder. ## Inputs | Input | Type | Required | Description | | ------------------------- | ------- | -------- | -------------------------------------------------------------- | | **Dividend** | Number | Yes | The value being divided. | | **Divisor** | Number | Yes | The nonzero value to divide by. | | **Use Integer Division?** | Boolean | No | Returns a floored quotient and remainder. Defaults to `false`. | ## Outputs | Output | Type | When shown | Description | | ------------- | ------ | ---------------------- | -------------------------------- | | **Quotient** | Number | Always | The result of the division. | | **Remainder** | Number | Integer division is on | The remainder from the division. | With **Dividend** set to `17` and **Divisor** set to `5`, **Quotient** is `3.4`. With the same inputs, **Quotient** is `3` and **Remainder** is `2`. The quotient is rounded down with `floor`, so negative inputs can differ from truncation toward zero. For example, `-17 ÷ 5` produces a quotient of `-4` and a remainder of `-2`. Division by zero is rejected before the calculation runs. # E Source: https://learn.workflow.dog/reference/actions/math/e Return Euler's number, the base of natural logarithms. The **E** action provides Euler's number for exponential growth, decay, and natural-logarithm calculations. ## Outputs | Output | Type | Description | | ------ | ------ | --------------------------------------------------------------------------------- | | **E** | Number | Euler's number at JavaScript number precision, approximately `2.718281828459045`. | Connect **E** to **Power** as the base to calculate `e^x`. # Floor Source: https://learn.workflow.dog/reference/actions/math/floor Round a number downward to the nearest integer. The **Floor** action returns the largest integer less than or equal to the input. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ------------------- | | **Number** | Number | Yes | The value to round. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------- | | **Floored** | Number | The input rounded toward negative infinity. | For example, `4.99` becomes `4`, while `-4.01` becomes `-5`. # Greater Than Source: https://learn.workflow.dog/reference/actions/math/greater-than Check whether one number is larger than another. The **Greater Than** action compares two numbers using `A > B`. ## Inputs | Input | Type | Required | Description | | ----- | ------ | -------- | ---------------------------- | | **A** | Number | Yes | The value on the left side. | | **B** | Number | Yes | The value on the right side. | ## Outputs | Output | Type | Description | | ---------- | ------- | ---------------------------------------- | | **Result** | Boolean | `true` when **A** is greater than **B**. | Equal values return `false`. # Greater Than or Equal Source: https://learn.workflow.dog/reference/actions/math/greater-than-or-equal Check whether one number is at least another. The **Greater Than or Equal** action compares two numbers using `A ≥ B`. ## Inputs | Input | Type | Required | Description | | ----- | ------ | -------- | ---------------------------- | | **A** | Number | Yes | The value on the left side. | | **B** | Number | Yes | The value on the right side. | ## Outputs | Output | Type | Description | | ---------- | ------- | ---------------------------------------------------- | | **Result** | Boolean | `true` when **A** is greater than or equal to **B**. | For example, `10 ≥ 10` and `12 ≥ 10` both return `true`. # Number in Range Source: https://learn.workflow.dog/reference/actions/math/in-range Check whether a number falls inside inclusive bounds. The **Number in Range** action returns whether a value is between a minimum and maximum, including both boundaries. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------- | | **Number** | Number | Yes | The value to test. | | **Min** | Number | Yes | The inclusive lower boundary. | | **Max** | Number | Yes | The inclusive upper boundary. | ## Outputs | Output | Type | Description | | ---------- | ------- | ---------------------------------------------------- | | **Result** | Boolean | `true` when `Min ≤ Number ≤ Max`; otherwise `false`. | For a range of `0` through `100`, the values `0`, `50`, and `100` all return `true`. Supply the lower boundary as **Min** and the upper boundary as **Max**. Reversed bounds do not get reordered and cannot match a normal finite number. # Inverse Source: https://learn.workflow.dog/reference/actions/math/inverse Calculate the reciprocal of a nonzero number. The **Inverse** action divides `1` by the input value. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ---------------------------- | | **Number** | Number | Yes | The nonzero value to invert. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------ | | **Inverse** | Number | The reciprocal, calculated as `1/x`. | For example, `4` produces `0.25`, and `-2` produces `-0.5`. An input of `0` is rejected because its reciprocal is undefined. # Less Than Source: https://learn.workflow.dog/reference/actions/math/less-than Check whether one number is smaller than another. The **Less Than** action compares two numbers using `A < B`. ## Inputs | Input | Type | Required | Description | | ----- | ------ | -------- | ---------------------------- | | **A** | Number | Yes | The value on the left side. | | **B** | Number | Yes | The value on the right side. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------- | | **Result** | Boolean | `true` when **A** is less than **B**. | Equal values return `false`. # Less Than or Equal Source: https://learn.workflow.dog/reference/actions/math/less-than-or-equal Check whether one number is no larger than another. The **Less Than or Equal** action compares two numbers using `A ≤ B`. ## Inputs | Input | Type | Required | Description | | ----- | ------ | -------- | ---------------------------- | | **A** | Number | Yes | The value on the left side. | | **B** | Number | Yes | The value on the right side. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------- | | **Result** | Boolean | `true` when **A** is less than or equal to **B**. | For example, `10 ≤ 10` and `8 ≤ 10` both return `true`. # Logarithm Source: https://learn.workflow.dog/reference/actions/math/log Calculate a natural logarithm or a logarithm in a chosen base. The **Logarithm** action calculates the exponent to which a base must be raised to produce the input number. Leave **Base** empty for the natural logarithm. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------------------------- | | **Number** | Number | Yes | A non-negative value whose logarithm is calculated. | | **Base** | Number | No | The logarithm base. Defaults to `e`. | ## Outputs | Output | Type | Description | | ------- | ------ | ----------------------------------- | | **Log** | Number | The logarithm in the selected base. | For example, **Number** `1000` with **Base** `10` returns approximately `3`. Although zero is accepted, its logarithm is negative infinity. Bases `1`, `0`, and negative values can produce infinity or `NaN`; use a positive base other than `1` for ordinary real-number logarithms. # Map Range Source: https://learn.workflow.dog/reference/actions/math/map-range Convert a number's position in one range to another range. The **Map Range** action linearly maps a value from an input range to the corresponding position in an output range. Use it for percentages, scores, coordinates, and unit-like scaling. ## Inputs | Input | Type | Required | Description | | ----------------- | ------- | -------- | --------------------------------------------------------------- | | **Number** | Number | Yes | The value to map. | | **In Min** | Number | Yes | The start of the input range. | | **In Max** | Number | Yes | The end of the input range. | | **Out Min** | Number | Yes | The corresponding start of the output range. | | **Out Max** | Number | Yes | The corresponding end of the output range. | | **Clamp Result?** | Boolean | No | Keeps the result within the output bounds. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------ | --------------------------------------- | | **Result** | Number | The value mapped into the output range. | ## Example Map a five-star rating into a percentage: | Setting | Value | | ----------- | ----- | | **Number** | `4` | | **In Min** | `1` | | **In Max** | `5` | | **Out Min** | `0` | | **Out Max** | `100` | The result is `75`. When clamping is off, values outside the input range are extrapolated. In the example above, a rating of `6` maps to `125`. Turn on **Clamp Result?** to return `100` instead. Reversed output ranges are supported. Clamping uses the lower and upper numeric output bounds regardless of their direction. **In Min** and **In Max** must be different. Equal input bounds cause a division by zero and produce a non-finite result. # Max Source: https://learn.workflow.dog/reference/actions/math/max Return the largest value from two or more numbers. The **Max** action examines a repeatable list and returns its largest number. ## Inputs | Input | Type | Required | Description | | ----------- | --------------- | -------- | ------------------------------- | | **Numbers** | List of numbers | Yes | At least two values to compare. | ## Outputs | Output | Type | Description | | ------- | ------ | ---------------------------- | | **Max** | Number | The largest supplied number. | For example, `8`, `-3`, and `4.5` produce `8`. Zero and empty repeat slots are currently ignored by this action. If zero needs to participate in the comparison, compare it explicitly with the returned value in a later step. # Min Source: https://learn.workflow.dog/reference/actions/math/min Return the smallest value from two or more numbers. The **Min** action examines a repeatable list and returns its smallest number. ## Inputs | Input | Type | Required | Description | | ----------- | --------------- | -------- | ------------------------------- | | **Numbers** | List of numbers | Yes | At least two values to compare. | ## Outputs | Output | Type | Description | | ------- | ------ | ----------------------------- | | **Min** | Number | The smallest supplied number. | For example, `8`, `-3`, and `4.5` produce `-3`. Zero and empty repeat slots are currently ignored by this action. If zero needs to participate in the comparison, compare it explicitly with the returned value in a later step. # Multiply Source: https://learn.workflow.dog/reference/actions/math/multiply Multiply two or more numbers together. The **Multiply** action multiplies a repeatable list of numbers. ## Inputs | Input | Type | Required | Description | | ----------- | --------------- | -------- | --------------------------------- | | **Numbers** | List of numbers | Yes | At least two factors to multiply. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------ | | **Product** | Number | The product of all supplied numbers. | Empty repeat slots are treated as `1`. For example, `4`, `2.5`, and `-3` produce `-30`. # Negate Source: https://learn.workflow.dog/reference/actions/math/negate Reverse the sign of a number. The **Negate** action multiplies a number by `-1`. Positive values become negative, and negative values become positive. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | -------------------- | | **Number** | Number | Yes | The value to negate. | ## Outputs | Output | Type | Description | | ------------ | ------ | --------------------------------- | | **Negation** | Number | The input with its sign reversed. | For example, `8` produces `-8`, while `-2.5` produces `2.5`. # Pi Source: https://learn.workflow.dog/reference/actions/math/pi Return the mathematical constant π. The **Pi** action provides the numeric constant π for calculations involving circles, angles, and periodic formulas. ## Outputs | Output | Type | Description | | ------ | ------ | -------------------------------------------------------------------- | | **Pi** | Number | π at JavaScript number precision, approximately `3.141592653589793`. | For example, multiply **Pi** by a circle's diameter to calculate its circumference. # Power Source: https://learn.workflow.dog/reference/actions/math/power Raise a base number to an exponent. The **Power** action calculates `base` raised to `exponent`. ## Inputs | Input | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------ | | **Base** | Number | Yes | The number being raised. | | **Exponent** | Number | Yes | The power applied to the base. | ## Outputs | Output | Type | Description | | ---------- | ------ | ----------------------------- | | **Result** | Number | The value of `base^exponent`. | Examples include `2^8 = 256`, `9^0.5 = 3`, and `10^-2 = 0.01`. Some combinations do not have a real-number result. For example, a negative base with a fractional exponent can produce `NaN`. # Random Number Source: https://learn.workflow.dog/reference/actions/math/random Generate a random decimal or whole number within a range. The **Random Number** action first generates a pseudorandom decimal from **Min** inclusive up to **Max** exclusive. Whole-number mode floors that value. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------- | -------- | ------------------------------------------------ | | **Min** | Number | Yes | The inclusive lower end of the range. | | **Max** | Number | Yes | The exclusive upper end of the range. | | **Only Whole Numbers?** | Boolean | No | Floors the generated value. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------------- | | **Random** | Number | A newly generated value in the range. | With integer boundaries **Min** `1`, **Max** `7`, and whole numbers enabled, the possible outputs are `1` through `6`. This action uses general-purpose pseudorandom selection. It is not suitable for security-sensitive tokens, secrets, or cryptographic use. Whole-number mode uses floor rather than choosing integers from adjusted bounds. A fractional minimum can therefore produce a whole number below that minimum; for example, values starting at `1.5` can floor to `1`. Use **Min** less than **Max**. Reversing the range changes the arithmetic and, with whole numbers enabled, can produce values outside the intuitive bounds. # Round Source: https://learn.workflow.dog/reference/actions/math/round Round a number to a chosen number of decimal places. The **Round** action rounds a number to the nearest value at the configured decimal precision. ## Inputs | Input | Type | Required | Description | | ------------------ | ------ | -------- | ----------------------------------------------------- | | **Number** | Number | Yes | The value to round. | | **Decimal Places** | Number | No | Non-negative whole-number precision. Defaults to `0`. | ## Outputs | Output | Type | Description | | ----------- | ------ | -------------------------- | | **Rounded** | Number | The rounded numeric value. | ## Examples | Number | Decimal Places | Rounded | | --------- | -------------- | ----------------------------------------------- | | `12.3456` | `0` | `12` | | `12.3456` | `2` | `12.35` | | `1.005` | `2` | May be `1` due to floating-point representation | The result is a number, so trailing zeroes are not preserved. Rounding `4.5` to two decimal places returns the numeric value `4.5`, not formatted text `4.50`. # Sine Source: https://learn.workflow.dog/reference/actions/math/sin Calculate the sine of an angle in radians or degrees. The **Sine** action calculates the sine of an angle. ## Inputs | Input | Type | Required | Description | | -------------- | ------------------ | -------- | ------------------------------------------------ | | **Angle** | Number | Yes | The angle to evaluate. | | **Angle Unit** | Radians or Degrees | Yes | How to interpret **Angle**. Defaults to radians. | ## Outputs | Output | Type | Description | | ---------- | ------ | ---------------------------- | | **Result** | Number | The sine of the input angle. | For example, `90` degrees returns approximately `1`, as does `π / 2` radians. Small floating-point differences are normal. # Square Root Source: https://learn.workflow.dog/reference/actions/math/sqrt Calculate the principal square root of a number. The **Square Root** action returns the non-negative value that, when multiplied by itself, equals the input. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | -------------------------------------- | | **Number** | Number | Yes | A number greater than or equal to `0`. | ## Outputs | Output | Type | Description | | -------- | ------ | --------------------------------------- | | **Sqrt** | Number | The principal square root of the input. | For example, `81` produces `9`. Negative inputs are rejected. # Subtract Source: https://learn.workflow.dog/reference/actions/math/subtract Subtract each later number from the first. The **Subtract** action starts with the first number, then subtracts every remaining number from it in order. ## Inputs | Input | Type | Required | Description | | ----------- | --------------- | -------- | ------------------------------------------ | | **Numbers** | List of numbers | Yes | At least two values, in calculation order. | ## Outputs | Output | Type | Description | | -------------- | ------ | ---------------------------------- | | **Difference** | Number | The result after all subtractions. | For example, `20`, `3`, and `2` are evaluated as `20 - 3 - 2`, producing `15`. Empty repeat slots are treated as `0`. # Tangent Source: https://learn.workflow.dog/reference/actions/math/tan Calculate the tangent of an angle in radians or degrees. The **Tangent** action calculates the tangent of an angle. ## Inputs | Input | Type | Required | Description | | -------------- | ------------------ | -------- | ------------------------------------------------ | | **Angle** | Number | Yes | The angle to evaluate. | | **Angle Unit** | Radians or Degrees | Yes | How to interpret **Angle**. Defaults to radians. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------- | | **Result** | Number | The tangent of the input angle. | For example, `45` degrees returns approximately `1`. Tangent is undefined at angles such as `90°` and `π / 2`. Floating-point arithmetic may return a very large finite value near those angles instead of an explicit error. # Verify Email Source: https://learn.workflow.dog/reference/actions/millionverifier/verify-email Check an email address with MillionVerifier. **Verify Email** sends one syntactically valid email address to MillionVerifier and returns its deliverability quality. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------------- | -------- | ---------------------------------- | | **Third-party account** | MillionVerifier account | Yes | The API key used for verification. | | **Email** | String | Yes | The address to verify. | ## Output | Output | Type | Description | | ----------- | ------ | ------------------------------------------------------------- | | **Quality** | String | `good`, `bad`, or `risky` when the service provides a result. | The output is empty when MillionVerifier returns an empty or missing quality. Treat `risky` as a separate branch instead of silently accepting or rejecting it. The right policy depends on whether you are validating signups, cleaning a list, or protecting a transactional send. # Create Object Source: https://learn.workflow.dog/reference/actions/objects/build Build an object from a repeatable list of keys and values. The **Create Object** action assembles key/value entries into a new object. Add one property input for every field the workflow should expose together. ## Inputs | Input | Type | Required | Description | | -------------- | ----------------- | --------- | ------------------------------------------ | | **Properties** | Key/value entries | No | The fields included in the new object. | | **Key** | String | Per entry | The property name. | | **Value** | Any | Per entry | The value stored under that property name. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------------------- | | **Object** | Object | The object built from all property entries. | ## Example Add these entries: | Key | Value | | -------- | ------ | | `name` | `Ada` | | `active` | `true` | | `score` | `98` | The output is: ```json theme={null} { "name": "Ada", "active": true, "score": 98 } ``` Property values keep their original types. A connected number remains a number; it is not converted to text. # Are Objects Equal? Source: https://learn.workflow.dog/reference/actions/objects/compare-objects Deeply compare two objects for equivalent contents. The **Are Objects Equal?** action performs a deep equality comparison. It checks nested objects and arrays, not just whether the two inputs are the same reference. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------- | | **First** | Object | Yes | The first object to compare. | | **Second** | Object | Yes | The second object to compare. | ## Outputs | Output | Type | Description | | ---------- | ------- | ----------------------------------------- | | **Result** | Boolean | `true` when the objects are deeply equal. | Object property order does not affect equality, but array order does. These objects are equal: ```json theme={null} { "name": "Ada", "tags": ["admin", "beta"] } { "tags": ["admin", "beta"], "name": "Ada" } ``` Changing the second array to `["beta", "admin"]` makes the result `false`. # Count Properties Source: https://learn.workflow.dog/reference/actions/objects/count-properties Count an object's top-level properties. The **Count Properties** action returns the number of enumerable top-level keys in an object. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ---------------------------------- | | **Object** | Object | Yes | The object whose keys are counted. | ## Outputs | Output | Type | Description | | --------- | ------ | ----------------------------------- | | **Count** | Number | The number of top-level properties. | Nested fields are not counted separately. For `{"name":"Ada","address":{"city":"London"}}`, the count is `2`. # Delete Properties Source: https://learn.workflow.dog/reference/actions/objects/delete-properties Return a copy of an object without selected properties. The **Delete Properties** action removes a repeatable list of property paths from an object. The original input is not returned as the output. ## Inputs | Input | Type | Required | Description | | -------------- | --------------- | -------- | ------------------------------------------ | | **Object** | Object | Yes | The object to copy and remove fields from. | | **Properties** | List of strings | No | Top-level keys or nested paths to remove. | ## Outputs | Output | Type | Description | | -------------- | ------ | ------------------------------------------- | | **New Object** | Object | The object without the selected properties. | Given: ```json theme={null} { "id": 1042, "customer": { "name": "Ada", "email": "ada@example.com" } } ``` Removing `customer.email` preserves the rest of `customer`. Missing paths are ignored. Use **Pick Properties** when the fields to keep are easier to list than the fields to remove. # Empty Object Source: https://learn.workflow.dog/reference/actions/objects/empty-object Provide a new object with no properties. The **Empty Object** action returns `{}`. Use it as a starting value for **Set Properties**, a default object for a branch, or an explicit empty payload. ## Outputs | Output | Type | Description | | ---------- | ------ | -------------------------------- | | **Object** | Object | A new object with no properties. | # Find Matching Object Source: https://learn.workflow.dog/reference/actions/objects/find-matching-object Find the first or all objects whose property meets a condition. The **Find Matching Object** action searches a list using one property path and a configurable comparison. Return the first match for lookup workflows, or all matches for filtering workflows. ## Inputs | Input | Type | Required | Description | | -------------------------- | --------------- | --------- | ------------------------------------------------------------------- | | **Objects** | List of objects | Yes | The objects to search, in priority order. | | **Property Name** | String | Yes | The top-level key or nested path whose value is tested. | | **Match Mode** | Match mode | Yes | The comparison to perform. Defaults to **Exact Value**. | | **Search Value** | Varies | Sometimes | Required by value, text, regex, and numeric modes. | | **Find Multiple Objects?** | Boolean | No | Returns every match instead of only the first. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------------- | ------ | ----------------------------------------- | | **Found Object** | Object | The first matching object in input order. | When nothing matches, no object value is found. | Output | Type | Description | | ----------------- | --------------- | ------------------------------------- | | **Found Objects** | List of objects | Every matching object in input order. | When nothing matches, the output is an empty list. ## Match modes | Mode | Search Value | A property matches when… | | ------------------------- | ------------------ | ------------------------------------------------------ | | **Exact Value** | Any | It is loosely equal to the search value. | | **Empty** | None | It is exactly an empty string. | | **Not Empty** | None | It is anything other than an empty string. | | **Contains Text** | String | Its text form contains the search text, ignoring case. | | **Matches Regex** | Regular expression | Its text form matches the pattern. | | **Greater Than** | Number | It is a number greater than the search value. | | **Less Than** | Number | It is a number less than the search value. | | **Greater Than or Equal** | Number | It is a number at least as large as the search value. | | **Less Than or Equal** | Number | It is a number no larger than the search value. | | **Is True** | None | It is the boolean `true`. | | **Is False** | None | It is the boolean `false`. | | **Is Truthy** | None | JavaScript treats it as truthy. | | **Is Falsy** | None | JavaScript treats it as falsy. | **Property Name** supports paths such as `customer.plan` and `items[0].quantity`. ### Important comparison details * **Exact Value** uses loose primitive equality, so the number `42` can match the text `"42"`, and `null` can match a missing value. * **Empty** matches only empty text. It does not match `null`, missing properties, empty objects, or empty lists. * Consequently, **Not Empty** also matches missing properties and non-string values. * **Contains Text** converts objects and lists to JSON text and compares without case sensitivity. * Numeric modes require the property itself to be a number. * Falsy values include `false`, `0`, empty text, `null`, and missing values. For **Matches Regex**, turn off the regex's **Global** flag. Reusing a global regex across several objects can advance its internal match position and skip otherwise valid matches. # Get Keys as List Source: https://learn.workflow.dog/reference/actions/objects/get-keys Return an object's top-level property names in a list. The **Get Keys as List** action returns all enumerable top-level keys from an object in their normal object iteration order. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ---------------------- | | **Object** | Object | Yes | The object to inspect. | ## Outputs | Output | Type | Description | | -------- | --------------- | -------------------------------------- | | **Keys** | List of strings | The object's top-level property names. | For `{"name":"Ada","active":true}`, the output is `["name", "active"]`. Nested keys are not flattened. # Get Properties Source: https://learn.workflow.dog/reference/actions/objects/get-properties Expose selected values from one object as separate outputs. The **Get Properties** action reads a repeatable list of property paths from one object. Every property input creates a corresponding output, which makes specific fields easy to connect without passing the entire object downstream. ## Inputs | Input | Type | Required | Description | | -------------- | --------------- | -------- | ----------------------------------- | | **Object** | Object | Yes | The object to read. | | **Properties** | List of strings | No | The keys or nested paths to expose. | ## Outputs The node adds one output for every **Properties** entry: | Output | Type | Description | | ------------------- | ---- | ---------------------------------------- | | **Value for "key"** | Any | The value found at that property's path. | If an entry is not yet configured, its output is labeled **Value for Key 1**, **Value for Key 2**, and so on. ## Nested paths Dot and bracket notation can read nested values. Given: ```json theme={null} { "customer": { "name": "Ada", "addresses": [{ "city": "Boston" }] } } ``` Add `customer.name` and `customer.addresses[0].city` to expose `Ada` and `Boston` as two outputs. If a path does not exist, its output has an undefined value. The action does not fail and does not substitute `null`. # Get Properties From Each Source: https://learn.workflow.dog/reference/actions/objects/get-properties-for-each Collect selected property values across a list of objects. The **Get Properties From Each** action reads the same property paths from every object in a list. Each requested property becomes an output list aligned with the input objects. ## Inputs | Input | Type | Required | Description | | -------------- | --------------- | -------- | ------------------------------------- | | **Objects** | List of objects | No | The objects to read, in output order. | | **Properties** | List of strings | No | The keys to collect from each object. | ## Outputs Every property entry creates a list output: | Output | Type | Description | | -------------------- | ----------- | --------------------------------------------- | | **Values for "key"** | List of any | That property's value from each input object. | For: ```json theme={null} [ { "name": "Ada", "score": 98 }, { "name": "Grace", "score": 95 } ] ``` Requesting `name` and `score` creates outputs equivalent to: ```json theme={null} ["Ada", "Grace"] [98, 95] ``` The output lists preserve input order and have one position per object. A missing property contributes an undefined value at that position. Dot and bracket paths such as `customer.name` or `items[0].sku` can collect nested values. # Get Values as List Source: https://learn.workflow.dog/reference/actions/objects/get-values Return an object's top-level values in a list. The **Get Values as List** action returns the values of an object's enumerable top-level properties. Their order corresponds to **Get Keys as List** for the same object. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ---------------------- | | **Object** | Object | Yes | The object to inspect. | ## Outputs | Output | Type | Description | | ---------- | ----------- | ------------------------------ | | **Values** | List of any | The object's top-level values. | For `{"name":"Ada","active":true}`, the output is `["Ada", true]`. Nested objects remain individual values. # Has Key? Source: https://learn.workflow.dog/reference/actions/objects/has-key Check whether an object contains a property or nested path. The **Has Key?** action checks whether a property path exists in an object. It returns `true` even when the property's value is `null`, `false`, or empty text. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | ---------------------------------------- | | **Object** | Object | Yes | The object to inspect. | | **Key** | String | Yes | A top-level key or nested property path. | ## Outputs | Output | Type | Description | | ---------- | ------- | ----------------------------------------------- | | **Result** | Boolean | `true` when the path exists; otherwise `false`. | Dot and bracket paths are supported. Given: ```json theme={null} { "customer": { "addresses": [{ "city": "Boston" }] } } ``` Both `customer.addresses` and `customer.addresses[0].city` return `true`. This checks existence, not whether the value is useful or non-empty. A key whose value is `undefined` can still be treated differently by later actions. # Is Empty? Source: https://learn.workflow.dog/reference/actions/objects/is-empty Check whether an object has no top-level properties. The **Is Empty?** action returns `true` when an object has zero enumerable top-level keys. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | -------------------- | | **Object** | Object | Yes | The object to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------------ | | **Result** | Boolean | `true` when the object has no keys; otherwise `false`. | `{}` is empty. `{"value": null}` is not empty because it still has the `value` property. # Is Object? Source: https://learn.workflow.dog/reference/actions/objects/is-object Check whether a value has JavaScript's non-null object type. The **Is Object?** action checks the runtime type of any workflow value. ## Inputs | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------------ | | **Result** | Boolean | `true` for a non-null object value; otherwise `false`. | Plain objects and arrays return `true`. Text, numbers, booleans, and `null` return `false`. This is a broad runtime check. It does not guarantee that the value is a plain key/value object; lists also count as objects. # Map Keys Source: https://learn.workflow.dog/reference/actions/objects/map-keys Rename or move property paths within an object. The **Map Keys** action copies an object, then applies a repeatable set of old-path to new-path mappings. Each mapping moves the value to its new location and removes the old path. ## Inputs | Input | Type | Required | Description | | ---------------- | --------------- | --------- | ----------------------------------------- | | **Object** | Object | Yes | The object whose paths will be changed. | | **Key Mappings** | Mapping entries | No | Old and new path pairs, applied in order. | | **Old Key** | String | Per entry | The existing key or nested path. | | **New Key** | String | Per entry | The destination key or nested path. | ## Outputs | Output | Type | Description | | ---------- | ------ | -------------------------------------- | | **Result** | Object | A copied object with mappings applied. | ## Rename and restructure Given: ```json theme={null} { "first_name": "Ada", "contact": { "email": "ada@example.com" } } ``` Map `first_name` to `name` and `contact.email` to `customer.email`: ```json theme={null} { "name": "Ada", "contact": {}, "customer": { "email": "ada@example.com" } } ``` Dot and bracket notation are supported for both paths. A missing old path is skipped. Mappings run in order and can overwrite an existing destination. A later mapping also sees the changes made by earlier mappings, so avoid chains and overlapping paths unless that sequence is intentional. # Map Keys For Each Source: https://learn.workflow.dog/reference/actions/objects/map-keys-for-each Apply the same key-path mappings to every object in a list. The **Map Keys For Each** action renames or moves paths in every object in a list. It preserves list order and returns newly copied objects. ## Inputs | Input | Type | Required | Description | | ---------------- | --------------- | --------- | -------------------------------------------- | | **Array** | List of objects | Yes | The objects to transform. | | **Key Mappings** | Mapping entries | No | Old and new path pairs applied to each item. | | **Old Key** | String | Per entry | The existing key or nested path. | | **New Key** | String | Per entry | The destination key or nested path. | ## Outputs | Output | Type | Description | | ---------- | --------------- | ------------------------------------------------ | | **Result** | List of objects | The transformed objects in their original order. | ## Example Map `first_name` to `name` for: ```json theme={null} [ { "first_name": "Ada", "id": 1 }, { "first_name": "Grace", "id": 2 } ] ``` The result is: ```json theme={null} [ { "name": "Ada", "id": 1 }, { "name": "Grace", "id": 2 } ] ``` Nested paths are supported, and missing old paths are skipped for only the objects that lack them. Mappings run in order on each object. Existing destination values can be overwritten, and overlapping mappings can affect one another. # Merge Objects Source: https://learn.workflow.dog/reference/actions/objects/merge-objects Combine objects in order with optional deep merging. The **Merge Objects** action combines a repeatable list of objects. When the same property appears more than once, the value from the later object takes precedence. ## Inputs | Input | Type | Required | Description | | -------------- | --------------- | -------- | -------------------------------------------------------------------- | | **Objects** | List of objects | No | The objects to combine, in precedence order. | | **Deep Merge** | Boolean | No | Merges nested values instead of replacing them. Defaults to `false`. | ## Outputs | Output | Type | Description | | ----------------- | ------ | -------------------- | | **Merged Object** | Object | The combined object. | ## Shallow and deep merging Nested objects are treated as complete values. Merging: ```json theme={null} { "customer": { "name": "Ada", "plan": "pro" } } { "customer": { "active": true } } ``` returns: ```json theme={null} { "customer": { "active": true } } ``` Turn on **Deep Merge** to combine nested properties: ```json theme={null} { "customer": { "name": "Ada", "plan": "pro", "active": true } } ``` Deep merging arrays combines them by index rather than simply appending or replacing the complete list. If array behavior matters, shape those values before merging. # Object Source: https://learn.workflow.dog/reference/actions/objects/object Build and merge one or more property sets into a final object. The **Object** action is a flexible object builder. Each repeatable input can be connected as an object or configured as its own set of key/value properties. All inputs are then combined in order. ## Inputs | Input | Type | Required | Description | | ----------------- | --------------- | --------- | ------------------------------------------------------- | | **Input Objects** | List of objects | No | Objects or configured property sets to combine. | | **Key** | String | Per entry | A property name or nested property path. | | **Value** | Any | Per entry | The value assigned to the key. | | **Deep Merge** | Boolean | No | Merges overlapping nested objects. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------------- | ------ | ------------------------------------- | | **Final Object** | Object | The completed object from all inputs. | ## Build with property paths Property keys are expanded as paths before the objects are merged. Configure: | Key | Value | | --------------- | ----- | | `customer.name` | `Ada` | | `customer.plan` | `pro` | To create: ```json theme={null} { "customer": { "name": "Ada", "plan": "pro" } } ``` ## Merge precedence Later input objects override earlier ones. With **Deep Merge** off, an overlapping nested object is replaced as a whole. Turn it on to preserve non-conflicting nested properties. Deep merging arrays combines values by index. Use dedicated list actions when you need append, concatenate, or replacement semantics. # Pick Properties Source: https://learn.workflow.dog/reference/actions/objects/pick-properties Return a new object containing only selected property paths. The **Pick Properties** action creates an object from a repeatable list of properties selected from the input. It is useful for shaping payloads and removing fields that should not leave the workflow. ## Inputs | Input | Type | Required | Description | | -------------- | --------------- | -------- | ----------------------------------------- | | **Object** | Object | Yes | The source object. | | **Properties** | List of strings | No | Top-level keys or nested paths to retain. | ## Outputs | Output | Type | Description | | -------------- | ------ | -------------------------------------------- | | **New Object** | Object | A new object containing the selected values. | Given: ```json theme={null} { "id": 1042, "customer": { "name": "Ada", "email": "ada@example.com" } } ``` Picking `id` and `customer.email` returns: ```json theme={null} { "id": 1042, "customer": { "email": "ada@example.com" } } ``` Missing paths are ignored. An empty property list returns an empty object. # Set Properties Source: https://learn.workflow.dog/reference/actions/objects/set-properties Add or replace properties on a copy of an object. The **Set Properties** action copies an optional source object, then applies a repeatable list of key/value entries. Use it to enrich an object without discarding its existing fields. ## Inputs | Input | Type | Required | Description | | ------------------- | ----------------- | --------- | ------------------------------------------------ | | **Original Object** | Object | No | The object to copy. Defaults to an empty object. | | **Properties** | Key/value entries | No | Fields to add or replace. | | **Key** | String | Per entry | A top-level key or nested property path. | | **Value** | Any | Per entry | The value assigned at that path. | ## Outputs | Output | Type | Description | | -------------- | ------ | ------------------------------------------- | | **New Object** | Object | The copied object with all entries applied. | ## Example Starting with: ```json theme={null} { "id": 1042, "customer": { "name": "Ada" } } ``` Set `customer.active` to `true` and `status` to `ready`: ```json theme={null} { "id": 1042, "customer": { "name": "Ada", "active": true }, "status": "ready" } ``` Dot and bracket paths create nested objects or arrays when needed. Later entries can overwrite values set by earlier entries. The source object is cloned before changes are applied, so the output can be modified without intentionally mutating the connected input value. # Transform Properties Source: https://learn.workflow.dog/reference/actions/objects/transform-properties Run another workflow once for each property in an object. The **Transform Properties** action applies a selected workflow to every top-level property of an object. It preserves each original key and replaces its value with the selected workflow's output data. This is a sub-workflow action. The selected workflow runs separately for each property and must use a **Sub-Workflow** trigger. Use **Return Data** in that workflow to provide the transformed value. ## Inputs | Input | Type | Required | Description | | --------------------- | -------- | -------- | ------------------------------------------------------ | | **Selected Workflow** | Workflow | Yes | The workflow used to transform each property. | | **Object** | Object | Yes | The object whose top-level properties are transformed. | ## Outputs | Output | Type | Description | | ---------------------- | ------ | ------------------------------------------------- | | **Transformed Object** | Object | The original keys mapped to sub-workflow outputs. | ## Configure the selected workflow For each property, the selected workflow's **Data In** contains: ```json theme={null} { "key": "propertyName", "value": "original property value" } ``` Use `value` for the transformation and `key` when the logic depends on which property is being processed. Connect the transformed value to **Return Data**. That returned data becomes the new value under the original key. For example, if the input is: ```json theme={null} { "firstName": " Ada ", "lastName": " LOVELACE " } ``` A selected workflow that trims and lowercases its `value`, then returns that string, produces: ```json theme={null} { "firstName": "ada", "lastName": "lovelace" } ``` ## Execution behavior * Only top-level properties are iterated. * Properties are processed one at a time in object-entry order. * If the selected workflow returns no output data, that property's new value is `null`. * If any sub-workflow run fails, **Transform Properties** fails rather than returning a partial object. * Normal workflow recursion-depth limits still apply. **Return Data** can return a primitive, list, or object. Design that returned value as the exact replacement each original property should receive. # Yes/No Question Source: https://learn.workflow.dog/reference/actions/openai/binary-decision Ask an OpenAI model for a boolean decision. **Yes/No Question** turns a natural-language question and optional context into a strict boolean. Use it when a workflow needs an AI judgment that can connect directly to conditional logic. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for the request. | | **Model** | OpenAI model | Yes | Defaults to GPT-5 Mini. | | **Question** | String | Yes | A question that can be answered yes or no. | | **Additional Text** | String | No | The content or facts the model should judge. | ## Output | Output | Type | Description | | ------------ | ------- | ---------------------------------- | | **Decision** | Boolean | `true` for yes and `false` for no. | ## Example: decide whether a message needs escalation * **Question** — `Does this customer message describe an urgent safety risk?` * **Additional Text** — Connect the incoming message. Route **Decision** into an **If**-style branch: `true` can alert an on-call person, while `false` continues normal processing. Make the decision criteria explicit. “Is this important?” is ambiguous; “Does this mention account takeover, exposed credentials, or unauthorized access?” gives the model a usable rule. # Chat Source: https://learn.workflow.dog/reference/actions/openai/chat Send a prompt, files, and optional instructions to an OpenAI model. The **Chat** action sends a single prompt to an OpenAI model. Use it for free-form text generation, questions about images or PDFs, web-assisted research, and responses that must match a JSON schema. Chat is stateless: each run sends the current prompt, system prompt, and files. It does not remember earlier workflow runs or previous Chat actions. ## Quick start Add an OpenAI account when the node asks for a **Third-party account**. The account must contain a valid OpenAI API key. Connect a string to **Prompt**, or set a fixed value on the node. Include all of the context the model needs for this run. **GPT-5.1** is selected by default. Standard models expose web search and temperature controls; reasoning models expose reasoning effort instead. Connect **Response** to the next action. If you enable structured output, connect properties from **Structured Response** instead. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | --------- | -------------------------------------------------------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The OpenAI API key used to make the request. | | **Prompt** | String | Yes | The user message sent to the model. | | **Model** | Model | Yes | The model that handles the request. Defaults to **GPT-5.1**. | | **System Prompt** | String | No | Instructions that define the model's role, constraints, or response style. | | **Files** | List of files | No | Images or PDFs sent with the prompt. Add more file inputs when the model needs multiple documents. | | **Structured Output** | Boolean | No | Replaces the text response with an object that follows a JSON schema. Defaults to off. | | **JSON Schema** | String | Sometimes | Required when **Structured Output** is enabled. The schema's outer type must be `object`. | ### Model controls Standard models support: * **Web Search** — Lets the model search the web before answering. Defaults to off. * **Temperature** — Controls how varied the response can be, from `0` (more focused) to `2` (more varied). Defaults to `1`. Available models: * GPT-5.1 * GPT-5 Nano * GPT-5 Mini * GPT-5 * GPT-4.1 Mini * GPT-4.1 * GPT-4o Mini * GPT-4o Reasoning models replace web search and temperature with **Reasoning Effort**: * `low` — Faster responses for straightforward tasks. This is the default. * `medium` — More reasoning for tasks with several constraints. * `high` — The most reasoning for difficult analysis. Available models: * o4-mini * o3 * o3-mini If model-specific controls disappear after you change models, the node has switched control sets. Standard and reasoning controls are mutually exclusive. ## Outputs When **Structured Output** is off, the node has one output: | Output | Type | Description | | ------------ | ------ | -------------------------------- | | **Response** | String | The model's complete text reply. | When **Structured Output** is on, **Response** is replaced by: | Output | Type | Description | | ----------------------- | ------ | ------------------------------------------- | | **Structured Response** | Object | The parsed object described by your schema. | You can expose schema properties as individual outputs, then connect only the values a later action needs. ## Return structured data Structured output is useful when later actions need predictable fields instead of prose. For example, this schema turns a support message into a summary, priority, and category: ```json theme={null} { "type": "object", "properties": { "summary": { "type": "string", "description": "A one-sentence summary of the request" }, "priority": { "type": "string", "enum": ["low", "normal", "high"] }, "category": { "type": "string", "enum": ["billing", "bug", "question"] } }, "required": ["summary", "priority", "category"], "additionalProperties": false } ``` Turn on **Structured Output**. The **JSON Schema** input and **Structured Response** output appear, while the text **Response** output is removed. Paste a valid JSON schema into **JSON Schema**. It must parse as JSON and contain an outer `type` of `object` with a `properties` map. Use **Add detected properties to output** on the node to add `summary`, `priority`, and `category` as connectable properties. Route `priority` into conditional logic, store `category`, or send `summary` in a notification without parsing a text response. Enabling structured output changes the node's output from **Response** to **Structured Response**. Check downstream connections when you toggle this setting on an existing workflow. ## Work with files Add one **Files** item for each image or PDF the model should inspect. Every file is sent in the same user message as the prompt. Good prompts state what to do with the attachments: ```text theme={null} Compare the attached invoices. Return the vendor, invoice number, due date, and total for each document. Flag any duplicate invoice numbers. ``` When structured output is enabled, describe the expected fields in the schema instead of asking the model to invent a response format in the prompt. ## Example: triage a support request Use Chat in the middle of a workflow to turn an incoming message into fields that other actions can route: 1. Pass the new support message to **OpenAI: Chat**. 2. Connect the returned `category` to **Choose Value by Case**. 3. From each case, send the message to the matching support queue. Configure the node with: * **Prompt** — The incoming subject and message body. * **System Prompt** — `Classify the request using only the supplied message.` * **Structured Output** — On. * **JSON Schema** — The support-triage schema above. The routing action can use `category` directly, while notifications and logs can use `summary` and `priority`. ## Troubleshooting Check that the value is valid JSON, the outer `type` is `object`, and `properties` is an object. JSON does not allow comments or trailing commas. You selected a reasoning model. Choose a standard model to use **Web Search** or **Temperature**. **Structured Output** is enabled. The node now returns **Structured Response** instead of **Response**. Chat does not preserve conversation history. Include the required history in the current prompt or load it from another action before Chat runs. # Classify Text Source: https://learn.workflow.dog/reference/actions/openai/classify Assign text to one or more categories with OpenAI. **Classify Text** maps a string to categories you define. It returns both the selected category name and a boolean output for every configured category, so downstream branches do not need to compare strings. ## Inputs | Input | Type | Required | Description | | ----------------------------- | -------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for classification. | | **Model** | OpenAI model | Yes | Defaults to GPT-5 Mini. | | **Text** | String | Yes | The content to classify. | | **Include 'Other' Category** | Boolean | No | Adds `other` for text that matches none of the supplied categories. | | **Allow Multiple Categories** | Boolean | No | Lets more than one category be selected. | | **Categories** | List | Yes | At least two key/description entries in the current implementation. | Each category contains: * **Key** — The exact string returned by the model. * **Description** — Optional guidance that distinguishes this category. Category keys must be unique. Use short, stable keys such as `billing` or `security`; put nuance in the description. ## Outputs **Selected Category** contains one category key. Each configured category also creates an **Is "key"** boolean output. **Selected Categories** contains a list of keys. Every **Is "key"** output indicates whether that category was selected. When **Include 'Other' Category** is on, **Is Other** is also available. ## Example: route inbound email | Key | Description | | --------- | ---------------------------------------------- | | `billing` | Invoices, charges, refunds, or payment methods | | `bug` | Something is broken or behaves unexpectedly | | `sales` | Pricing, evaluation, or purchase questions | Enable **Other** so unrelated messages have a safe route. Leave multiple categories off when every email must have one owning queue. # Extract Text Source: https://learn.workflow.dog/reference/actions/openai/extract Pull a configured set of text fields from unstructured content. **Extract Text** asks OpenAI to find specific features in a source string. It creates one output for every feature, in the same order as the feature list. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ----------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for extraction. | | **Model** | OpenAI model | Yes | Defaults to GPT-5 Mini. | | **Text** | String | Yes | The unstructured source content. | | **Features** | List of strings | Yes | One or more unique values describing what to extract. | Example features for an invoice: * `vendor name` * `invoice number` * `total amount with currency` * `payment due date in ISO format` ## Outputs The action creates **Extracted Feature 1**, **Extracted Feature 2**, and later outputs that line up with the feature inputs. An output is empty when the model cannot find that feature. Do not repeat a feature. Duplicate feature strings cause the action to fail. Include the desired format in the feature description. “Due date” may return prose; “due date in `YYYY-MM-DD` format” is easier for later actions to use. # Generate Image Source: https://learn.workflow.dog/reference/actions/openai/generate-image Create an image from a prompt with DALL·E or GPT Image. **Generate Image** sends a text prompt to an OpenAI image model and returns the generated image as a file. Available controls change with the selected model. ## Common inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for generation. | | **Prompt** | String | Yes | A visual description of the desired image. | | **Model** | Enum | Yes | DALL·E 2, DALL·E 3, or GPT Image 1. Defaults to DALL·E 2. | | **Image Size** | Enum | Yes | The available dimensions for the selected model. | ## Model controls Square sizes: `256×256`, `512×512`, and `1024×1024`. The default is `1024×1024`. Sizes: `1024×1024`, `1792×1024`, and `1024×1792`. * **Quality** — Standard or HD. * **Style** — Natural or Vivid. Sizes: `1024×1024`, `1536×1024`, `1024×1536`, or Auto. * **Quality** — Auto, High, Medium, or Low. * **Background** — Auto, Transparent, or Opaque. * **Output Format** — PNG, JPEG, or WebP. * **Output Compression** — `0` to `100` for JPEG and WebP. ## Output | Output | Type | Description | | --------- | ---- | ------------------------------------------------------------------------------- | | **Image** | File | The generated image. DALL·E output is PNG; GPT Image follows **Output Format**. | Describe the subject, setting, composition, lighting, palette, and intended use. A specific art direction is more reliable than a list of adjectives. Transparent backgrounds are a GPT Image 1 feature. Choose PNG or WebP when the downstream workflow must preserve transparency. # Produce Text Source: https://learn.workflow.dog/reference/actions/openai/produce Generate one clean text result for each prompt. **Produce Text** takes a list of prompts and returns one separate string for each. The model is instructed to provide only the requested text without extra commentary. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------ | | **Third-party account** | OpenAI account | Yes | The API key used for generation. | | **Model** | OpenAI model | Yes | Defaults to GPT-5 Mini. | | **Prompts** | List of strings | Yes | One or more generation instructions. | ## Outputs Each prompt creates a corresponding **Produced Text 1**, **Produced Text 2**, and later output. All prompts are sent in one model request, but each result is returned through its own connection. ## Example Use three prompts to generate: 1. A subject line under 50 characters. 2. A two-sentence summary of the source text. 3. A short call to action. Connect each produced output to the field that needs it. Use **Chat** instead when you need one response that synthesizes several instructions or must return a structured object. # Transcribe Audio Source: https://learn.workflow.dog/reference/actions/openai/transcribe Convert an audio file to text with OpenAI. **Transcribe Audio** sends an audio file to an OpenAI transcription model and returns the recognized speech as one string. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for transcription. | | **Audio** | Audio file | Yes | A file whose MIME type begins with `audio/`. | | **Model** | Enum | Yes | Whisper-1, GPT-4o Transcribe, or GPT-4o Mini Transcribe. Defaults to Whisper-1. | ## Output | Output | Type | Description | | -------- | ------ | ------------------------ | | **Text** | String | The complete transcript. | This action returns plain transcript text. It does not expose timestamps, speaker labels, or segment metadata. Preserve the source file's correct audio MIME type. A video file containing audio is not accepted unless another action first extracts or converts it to an audio file. # Text to Speech Source: https://learn.workflow.dog/reference/actions/openai/tts Turn text into a spoken audio file with OpenAI. **Text to Speech** generates spoken audio from a string. Choose a voice, speed, model, and file format, then connect the resulting file to storage, email, or another media action. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ---------------------------------------------------------------------------- | | **Third-party account** | OpenAI account | Yes | The API key used for synthesis. | | **Text** | String | Yes | The content to speak. | | **Model** | Enum | Yes | TTS-1, TTS-1 HD, or GPT-4o Mini TTS. Defaults to TTS-1. | | **Voice** | Enum | Yes | Alloy, Ash, Ballad, Coral, Echo, Fable, Onyx, Nova, Sage, Shimmer, or Verse. | | **Speed** | Number | No | From `0.25×` to `4×`. Defaults to `1×`. | | **Response Format** | Enum | Yes | MP3, Opus, AAC, FLAC, or PCM. Defaults to MP3. | | **Instructions** | String | No | Delivery direction available only for GPT-4o Mini TTS. | Example instructions: ```text theme={null} Speak warmly and clearly, with a brief pause after each sentence. ``` ## Output | Output | Type | Description | | --------- | ---- | ----------------------------------------------------------------- | | **Audio** | File | The generated audio, named from the first part of the input text. | Use TTS-1 for a general-purpose result, TTS-1 HD when fidelity matters more, or GPT-4o Mini TTS when you need explicit delivery instructions. # Delete Message Source: https://learn.workflow.dog/reference/actions/outlook/delete-message Move an Outlook message to Deleted Items or permanently delete it. The **Delete Message** action removes one Outlook message. By default, Microsoft moves it to Deleted Items; permanent deletion bypasses that recoverable step. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------- | -------- | ------------------------------------------ | | **Third-party account** | Microsoft account | Yes | Outlook account containing the message. | | **Message ID** | String | Yes | Microsoft ID of the message. | | **Permanent Delete** | Boolean | No | Bypass Deleted Items. Defaults to `false`. | **Permanent Delete** is destructive and the action returns no output. Leave it off when the message may need to be recovered. # Draft Email Source: https://learn.workflow.dog/reference/actions/outlook/draft-email Create an unsent email draft in Microsoft Outlook. The **Draft Email** action saves a new message in Outlook without sending it. Recipients, subject, and body can be left empty for a person to complete later. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ------------------------------------------ | | **Third-party account** | Microsoft account | Yes | Outlook account that owns the draft. | | **Recipients** | List of email strings | No | `To` addresses. | | **CC** | List of email strings | No | Carbon-copy addresses. | | **Subject** | String | No | Draft subject. Defaults to empty. | | **Body** | String | No | Draft content. Defaults to empty. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files included in the draft. | ## Outputs | Output | Type | Description | | ------------------- | ------ | ----------------------------------- | | **Message ID** | String | Immutable ID of the created draft. | | **Conversation ID** | String | Conversation assigned to the draft. | ## Example To prepare an account summary for review: 1. Generate the summary with an earlier action. 2. Use the generated text as the Outlook draft's **Body**. 3. After the draft is created, notify the account owner that it is ready to review. # Draft Reply Source: https://learn.workflow.dog/reference/actions/outlook/draft-reply Create an unsent reply or reply-all draft in Outlook. The **Draft Reply** action creates a threaded Outlook reply without sending it. Use it when a person needs to review, edit, or approve the response. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ------------------------------------------ | | **Third-party account** | Microsoft account | Yes | Outlook account that owns the draft. | | **Message ID** | String | Yes | Message being answered. | | **Reply All** | Boolean | No | Include Outlook's reply-all recipients. | | **Body** | String | No | Draft content. Defaults to empty. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files attached to the reply draft. | ## Outputs | Output | Type | Description | | ------------ | ------ | -------------------------------- | | **Draft ID** | String | Immutable ID of the reply draft. | Review recipients before sending a draft created with **Reply All**. # Forward Source: https://learn.workflow.dog/reference/actions/outlook/forward Forward an Outlook message with optional content and attachments. The **Forward** action creates and sends a forward of an existing Outlook message. You can add new content and additional attachments. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ----------------------------------------------- | | **Third-party account** | Microsoft account | Yes | Outlook account that sends the forward. | | **Message ID** | String | Yes | Microsoft ID of the original message. | | **Recipients** | List of email strings | Yes | One or more destination addresses. | | **Body** | String | No | Additional content included with the forward. | | **Body Type** | `Plain Text` or `HTML` | No | Encoding for the additional body. Default text. | | **Attachments** | List of files | No | Additional files to include. | ## Outputs | Output | Type | Description | | -------------- | ------ | ------------------------------------------ | | **Forward ID** | String | Immutable ID created for the sent forward. | **Attachments** adds new files to the forward. Outlook itself constructs the forwarded-message content from the source Message ID. # Get Conversation Source: https://learn.workflow.dog/reference/actions/outlook/get-conversation Load every message in an Outlook conversation from oldest to newest. The **Get Conversation** action retrieves every mailbox message with a matching Outlook conversation ID. It follows Microsoft pagination, sorts messages by received time, and returns the complete conversation oldest first. ## Inputs | Input | Type | Required | Description | | ------------------------ | ----------------- | -------- | ---------------------------------------------------------- | | **Third-party account** | Microsoft account | Yes | Account whose mailbox is searched. | | **Conversation ID** | String | Yes | Outlook conversation ID from a trigger, draft, or message. | | **Download Attachments** | Boolean | No | Download files for every message. Defaults to `false`. | Leave attachment downloading off when you only need conversation text. It adds a request for each message that reports attachments. ## Outputs **Messages** is a list ordered from oldest to newest. Each item includes: | Field | Type | Description | | ------------------- | ------------- | ------------------------------------------- | | **Message ID** | String | Microsoft message ID. | | **Conversation ID** | String | Conversation ID returned by Microsoft. | | **Sender Name** | String | Sender display name. | | **Sender Address** | String | Sender email address. | | **Subject** | String | Message subject. | | **Plain Text** | String | Body requested as text. | | **HTML** | String | Body requested as HTML. | | **Date/Time** | Date | Received time. | | **Is Read** | Boolean | Outlook read state. | | **Attachments** | List of files | Available only when downloading is enabled. | Toggling **Download Attachments** changes the nested output shape by adding or removing **Attachments**. Check downstream connections after changing it. ## Troubleshooting Trimmed Conversation ID matching is exact. Confirm the ID comes from the same Microsoft mailbox and has not been confused with a Message ID. # Get Message Source: https://learn.workflow.dog/reference/actions/outlook/get-message Retrieve message content and metadata from Microsoft Outlook. The **Get Message** action loads one Outlook message by its Microsoft message ID. It requests the message twice so both plain-text and HTML body forms are available. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------- | -------- | --------------------------------- | | **Third-party account** | Microsoft account | Yes | Account used to read the message. | | **Message ID** | String | Yes | Microsoft ID of the message. | ## Outputs | Output | Type | Description | | ------------------- | ------------- | -------------------------------------------- | | **Sender Name** | String | Sender display name, when present. | | **Sender Address** | String | Sender email address, when present. | | **Subject** | String | Message subject. | | **Plain Text** | String | Message body requested as text. | | **HTML** | String | Message body requested as HTML. | | **Attachments** | List of files | Attachment output; currently returned empty. | | **Date/Time** | Date | Time the message was received. | | **Is Read** | Boolean | Current Outlook read state. | | **Conversation ID** | String | Conversation containing the message. | The current Get Message node does not expose attachment downloading, so **Attachments** is an empty list. The **New Email** trigger downloads attachments, and **Get Conversation** can download them when enabled. ## Example Connect a stored Outlook message ID to **Get Message**. The action returns the message's **Conversation ID**, which you can pass to **Get Conversation** when you need the rest of the conversation. # Mark as Read Source: https://learn.workflow.dog/reference/actions/outlook/mark-as-read Mark one Microsoft Outlook message as read. The **Mark as Read** action sets an Outlook message's read state to `true`. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------- | -------- | --------------------------------------- | | **Third-party account** | Microsoft account | Yes | Outlook account containing the message. | | **Message ID** | String | Yes | Microsoft ID of the message to update. | This action returns no output. Use **Get Message** when a later branch needs the current **Is Read** value. # Mark as Unread Source: https://learn.workflow.dog/reference/actions/outlook/mark-as-unread Mark one Microsoft Outlook message as unread. The **Mark as Unread** action sets an Outlook message's read state to `false`. Use it to return processed mail to a person's attention. ## Inputs | Input | Type | Required | Description | | ----------------------- | ----------------- | -------- | --------------------------------------- | | **Third-party account** | Microsoft account | Yes | Outlook account containing the message. | | **Message ID** | String | Yes | Microsoft ID of the message to update. | This action changes the message and returns no output. # Send Reply Source: https://learn.workflow.dog/reference/actions/outlook/reply Send a reply or reply-all to a Microsoft Outlook message. The **Send Reply** action creates a reply draft for a message, adds the supplied body and attachments, then sends it. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | --------------------------------------------- | | **Third-party account** | Microsoft account | Yes | Outlook account that sends the reply. | | **Message ID** | String | Yes | Microsoft ID of the message being answered. | | **Reply All** | Boolean | No | Include the original conversation recipients. | | **Body** | String | Yes | Reply content. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files to attach to the reply. | ## Outputs | Output | Type | Description | | ------------ | ------ | ---------------------------------------- | | **Reply ID** | String | Immutable ID created for the sent reply. | **Reply All** can send the response to every recipient selected by Outlook. Leave it off for a reply only to the original sender. # Send Email Source: https://learn.workflow.dog/reference/actions/outlook/send-email Send a plain-text or HTML email from Microsoft Outlook. The **Send Email** action creates and sends a message from a connected Microsoft account. It supports multiple recipients, CC addresses, and file attachments. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------------- | -------- | ------------------------------------------ | | **Third-party account** | Microsoft account | Yes | Outlook account that sends the message. | | **Recipients** | List of email strings | Yes | One or more `To` addresses. | | **CC** | List of email strings | No | Carbon-copy addresses. | | **Subject** | String | Yes | Message subject. | | **Body** | String | Yes | Plain-text or HTML content. | | **Body Type** | `Plain Text` or `HTML` | No | Body encoding. Defaults to **Plain Text**. | | **Attachments** | List of files | No | Files attached to the message. | ## Outputs | Output | Type | Description | | ------------------- | ------ | -------------------------------------------- | | **Message ID** | String | Immutable Microsoft ID for the sent message. | | **Conversation ID** | String | Outlook conversation containing the message. | The action first creates a draft with an immutable ID, then sends that draft. Store **Conversation ID** when later steps need the complete thread. Set **Body Type** to **HTML** before supplying markup. Untrusted values should be escaped or sanitized before they are inserted into HTML. # Run Query Source: https://learn.workflow.dog/reference/actions/postgres/run-query Execute a parameterized SQL query on PostgreSQL. **Run Query** connects to a PostgreSQL account, executes one SQL statement, and returns its result rows and affected-row count. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------------ | -------- | ------------------------------------------------------------------ | | **Third-party account** | PostgreSQL account | Yes | Host, database, credentials, port, and SSL settings. | | **Query** | String | Yes | A non-empty SQL statement. | | **Parameters** | List of any values | No | Values bound to `$1`, `$2`, `$3`, and later placeholders in order. | ```sql theme={null} select id, email from customers where plan = $1 and created_at >= $2 order by created_at desc; ``` Add `pro` as parameter 1 and the cutoff date as parameter 2. Use parameters for values instead of joining untrusted text into SQL. Parameter placeholders protect values, but they cannot stand in for table or column names. ## Outputs | Output | Type | Description | | ------------- | --------------- | ------------------------------------------------------------------ | | **Rows** | List of objects | Rows returned by the query. Each object uses column names as keys. | | **Row Count** | Number | The number of rows returned or affected. | The database connection is closed after the query succeeds or fails. # Create Contact Source: https://learn.workflow.dog/reference/actions/resend/create-contact Add a contact to a Resend audience. **Create Contact** adds an email address and optional name to a Resend audience. | Input | Type | Required | Description | | ------------------------------ | -------------- | -------- | -------------------------------------------------- | | **Third-party account** | Resend account | Yes | The API key used for the audience. | | **Audience ID** | String | Yes | The destination audience. | | **Email** | Email | Yes | The contact's address. | | **First Name** / **Last Name** | String | No | Optional contact name fields. | | **Subscribed** | Boolean | No | Whether the contact is subscribed. Defaults to on. | | Output | Type | Description | | -------------- | ------ | ---------------------------------------- | | **Contact ID** | String | Resend's identifier for the new contact. | # Delete Contact Source: https://learn.workflow.dog/reference/actions/resend/delete-contact Permanently remove a contact from a Resend audience. **Delete Contact** permanently removes one contact from one Resend audience. | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------------- | | **Third-party account** | Resend account | Yes | The API key used for the audience. | | **Audience ID** | String | Yes | The audience containing the contact. | | **Contact ID or Email** | String | Yes | Resend's contact ID or the contact's email address. | Deletion is different from unsubscribing. Use **Unsubscribe Contact** when the record should remain in the audience with an opted-out state. # Get Email by ID Source: https://learn.workflow.dog/reference/actions/resend/retrieve-email Retrieve a Resend email and its latest delivery event. **Get Email by ID** fetches the stored message details for a Resend email. ## Input | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------------------- | | **Third-party account** | Resend account | Yes | The account that sent the email. | | **Email ID** | String | Yes | A non-empty ID returned by a send or schedule action. | ## Outputs | Output | Type | Description | | --------------------------------------------- | ---------------- | ------------------------------------------------------------- | | **Email ID** | String | The email identifier. | | **From** | String | The sender. | | **Recipients**, **CC**, **BCC**, **Reply To** | Lists of strings | Message recipients. | | **Subject** | String | The subject line. | | **HTML** / **Plain Text** | String | Message content; either can be empty if it was not provided. | | **Created At** | Date | When the email was created. | | **Last Event** | String | The latest Resend event, such as sent, delivered, or bounced. | **Last Event** is a status value, not a timestamp. Use it to branch on the latest known delivery state. # Schedule Email Source: https://learn.workflow.dog/reference/actions/resend/schedule-email Schedule a Resend email for a future time. **Schedule Email** creates a Resend email with a future send time. ## Inputs The message fields match **Send Email**: **From**, one or more **Recipients**, **Subject**, **HTML Content**, optional **Plain Text**, **CC**, **BCC**, and **Reply To**. **Schedule Time** is required and accepts either: * Natural language such as `in 1 hour` or `tomorrow at 3pm`. * An ISO 8601 timestamp such as `2026-08-05T15:00:00Z`. ## Output | Output | Type | Description | | ------------ | ------ | -------------------------------------------- | | **Email ID** | String | Resend's identifier for the scheduled email. | Natural-language times can be ambiguous. Use an ISO 8601 timestamp with an explicit offset or `Z` when the exact timezone matters. # Send Email Source: https://learn.workflow.dog/reference/actions/resend/send-email Send a transactional email immediately with Resend. Resend **Send Email** sends an HTML email immediately, with optional text, copy recipients, reply-to addresses, and tracking tags. ## Inputs | Input | Type | Required | Description | | ----------------------- | ------------------------ | -------- | ------------------------------------------------- | | **Third-party account** | Resend account | Yes | The API key used to send. | | **From** | String | Yes | A sender such as `Acme `. | | **Recipients** | List of emails | Yes | One or more destination addresses. | | **CC** / **BCC** | Lists of emails | No | Copy recipients. | | **Subject** | String | Yes | A non-empty subject. | | **HTML Content** | String | Yes | The HTML message body. | | **Plain Text** | String | No | A text-only alternative. | | **Reply To** | List of strings | No | Addresses that receive replies. | | **Tags** | List of name/value pairs | No | Resend metadata for categorization. | Tag names and values should contain only letters, numbers, underscores, and dashes. ## Output | Output | Type | Description | | ------------ | ------ | --------------------------------- | | **Email ID** | String | Resend's identifier for the send. | Store **Email ID** when a later action must retrieve delivery details. # Unsubscribe Contact Source: https://learn.workflow.dog/reference/actions/resend/unsubscribe-contact Opt a contact out of a Resend audience. **Unsubscribe Contact** changes an existing Resend contact to unsubscribed without deleting the contact record. | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------------- | | **Third-party account** | Resend account | Yes | The API key used for the audience. | | **Audience ID** | String | Yes | The audience containing the contact. | | **Contact ID or Email** | String | Yes | Resend's contact ID or the contact's email address. | The action has no output and continues after Resend confirms the update. # Scrape URL Source: https://learn.workflow.dog/reference/actions/scrapfly/scrape Extract page content through Scrapfly with rendering and anti-bot controls. **Scrape URL** retrieves a page through Scrapfly and can render JavaScript, bypass anti-scraping protection, reuse a browser session, and execute custom JavaScript before returning content. ## Inputs | Input | Type | Required | Description | | ---------------------------- | ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------- | | **Third-party account** | Scrapfly account | Yes | The Scrapfly API key. | | **URL** | String | Yes | The page to scrape. | | **Format** | Enum | Yes | Raw HTML, clean HTML, plain text, Markdown, Markdown without links/images, or JSON. Defaults to clean HTML. | | **Anti-Scraping Protection** | Boolean | No | Enable Scrapfly's anti-bot handling. | | **Render JavaScript** | Boolean | No | Use browser rendering. Defaults to on. | | **Session** | String | No | An alphanumeric session name, up to 255 characters, used to reuse cookies, fingerprint, and proxy. | | **Cache** | Boolean | No | Reuse eligible cached results. | | **Proxy Pool** | Enum | No | Datacenter or residential proxies. | | **Proxy Country** | String | No | Scrapfly's country-location value. | | **Operating System** | Enum | No | Windows 11, macOS, Linux, or Chrome OS. Random when omitted. | | **Headers** | List of name/value pairs | No | Custom request headers. Header names are sent lowercase. | ### JavaScript rendering controls These inputs appear only while **Render JavaScript** is on: | Input | Type | Description | | --------------------- | ------- | --------------------------------------------------------- | | **Rendering Wait** | Number | Milliseconds to wait after page load. Defaults to `1000`. | | **JavaScript Code** | String | Browser-side code executed after the rendering wait. | | **Wait For Selector** | String | CSS selector to wait for after custom JavaScript runs. | | **Auto Scroll** | Boolean | Scroll to load viewport-triggered content. | ## Outputs | Output | Type | Description | | --------------------- | ------ | ------------------------------------------------------------------------ | | **Content** | String | Page content in the selected format. | | **Status Code** | Number | The page's HTTP status. | | **Final URL** | String | The final URL after redirects. | | **JavaScript Result** | Any | The return value from custom code; shown only with JavaScript rendering. | Start with clean HTML and JavaScript rendering on. Enable anti-scraping protection, a residential proxy, or a session only when the target requires them, since advanced Scrapfly features can affect request cost. # Take Screenshot Source: https://learn.workflow.dog/reference/actions/scrapfly/screenshot Capture a rendered webpage as an image with Scrapfly. **Take Screenshot** renders a URL through Scrapfly and returns a screenshot file. It supports viewport, full-page, vertical-scroll, and element-specific capture. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Scrapfly account | Yes | The Scrapfly API key. | | **URL** | String | Yes | The page to capture. | | **Format** | Enum | Yes | JPEG, PNG, WebP, or GIF. Defaults to WebP in the editor. | | **Capture** | Enum | Yes | Viewport, full page, or vertical scroll. Defaults to viewport. | | **Element Selector** | String | No | CSS selector or XPath. Overrides **Capture**. | | **Width** / **Height** | Number | No | Browser dimensions from `100` to `4096`. Defaults to `1920 × 1080`. | | **Dark Mode** | Boolean | No | Request a dark color scheme. | | **Block Banners** | Boolean | No | Hide cookie banners and covering overlays. | | **Print Media Format** | Boolean | No | Render print CSS. | | **Auto Scroll** | Boolean | No | Scroll to load dynamic content. | | **Wait For Selector** | String | No | Wait for a CSS selector or XPath before capture. | | **Rendering Wait** | Number | No | Additional milliseconds after load. Defaults to `1000`. | | **Proxy Country** | String | No | Scrapfly's proxy-country value. | | **Cache** | Boolean | No | Reuse eligible cached captures. | ## Output | Output | Type | Description | | -------------- | ---------- | ------------------------------------------------- | | **Screenshot** | Image file | The captured image, named from the page hostname. | **Element Selector** replaces the capture mode rather than cropping the finished full-page image. ## Troubleshooting Enable **Auto Scroll**, add **Wait For Selector**, or increase **Rendering Wait** so the page can finish loading before capture. Enable **Block Banners**. If the target uses a custom overlay, capture a specific element or use **Scrape URL** with custom JavaScript. # Balanced Select Source: https://learn.workflow.dog/reference/actions/selector/balanced Choose the option with the lowest current balance. **Balanced Select** favors the least-used option. It can track balances for this node automatically or use counts supplied by the workflow. ## Modes Add one or more **Options** and leave **Manage state internally?** enabled. The node stores a balance for each option within the project, selects the first option with the lowest balance, then adds **Increment** to that option's balance. | Input | Type | Required | Description | | ------------- | -------------- | -------- | ---------------------------------------------- | | **Options** | Repeatable any | Yes | Values to distribute selections across. | | **Increment** | Number | No | Amount added after selection. Defaults to `1`. | Disable **Manage state internally?** when counts come from a database, queue, or another workflow action. Each **Option** has: * **Value** — The value that can be selected. * **Current Balance** — Its current numeric amount. The action returns the first option with the lowest balance. It does not update externally provided balances. ## Output | Output | Type | Description | | ------------ | ---- | ------------------------------------------ | | **Selected** | Any | The value belonging to the lowest balance. | In managed mode, balances belong to this node instance and are stored by option position. Reordering, adding, or removing options can associate existing counts with different values. Simultaneous runs can inspect the same stored balance before either update is saved. If strict one-at-a-time distribution is required, serialize runs or provide balances from a transactional external source. # Random Select Source: https://learn.workflow.dog/reference/actions/selector/random Choose one option at random on each run. ## Input | Input | Type | Required | Description | | ----------- | -------------- | -------- | ---------------------------------------- | | **Options** | Repeatable any | Yes | At least one value that may be selected. | ## Output | Output | Type | Description | | ------------ | ---- | ----------------------------- | | **Selected** | Any | One randomly selected option. | Every position has the same probability. Duplicate values occupy multiple positions and therefore increase that value's chance of selection. Random selection is nondeterministic. Two runs with the same options can return different results. # Round Robin Source: https://learn.workflow.dog/reference/actions/selector/round-robin Cycle through options in order across workflow runs. **Round Robin** returns the first option on its first run, the second on its next run, and wraps back to the beginning after the last option. ## Input | Input | Type | Required | Description | | ----------- | -------------- | -------- | ------------------------------------- | | **Options** | Repeatable any | Yes | At least one value in rotation order. | ## Output | Output | Type | Description | | ------------ | ---- | ----------------------------------------- | | **Selected** | Any | The option at the current rotation index. | The current index is stored for this node instance within the project. With `[A, B, C]`, successive runs return `A`, `B`, `C`, `A`. Changing the number or order of options does not reset the stored index. The next run applies that index to the new list. Simultaneous runs can read the same index before either saves the next one. Serialize runs when each option must be chosen exactly once per cycle. # Collapse Whitespace Source: https://learn.workflow.dog/reference/actions/text/collpase-whitespace Limit consecutive spaces and line breaks while preserving the text. The **Collapse Whitespace** action shortens runs of spaces and line breaks to configurable maximums. Use it to clean copied text without removing all paragraph structure. The source filename intentionally uses `collpase-whitespace`. The action shown in the workflow builder is named **Collapse Whitespace**. ## Inputs | Input | Type | Required | Description | | --------------------- | ------- | -------- | ------------------------------------------------------------------------- | | **Text** | String | Yes | The text to clean. | | **Collapse Spaces** | Boolean | No | Limits runs of literal space characters. Defaults to `true`. | | **Max Spaces** | Number | No | Maximum spaces left in a run. Must be non-negative; defaults to `1`. | | **Collapse Newlines** | Boolean | No | Limits consecutive line breaks. Defaults to `true`. | | **Max Newlines** | Number | No | Maximum line breaks left in a run. Must be non-negative; defaults to `2`. | ## Outputs | Output | Type | Description | | ------------- | ------ | ----------------------------------------------- | | **Collapsed** | String | The text after the selected limits are applied. | ## How the limits work Only runs longer than the configured maximum are changed. With the defaults: * Two or more consecutive spaces become one space. * Three or more consecutive line breaks become two line breaks. * Tabs and other whitespace are left unchanged. * Windows-style `\r\n` line breaks are normalized to `\n` only when a run is collapsed. Set a maximum to `0` to remove matching runs entirely. Turn either collapse toggle off to preserve that kind of whitespace regardless of its maximum. Use **Trim Whitespace** after this action if leading or trailing whitespace should also be removed. # Contains Text Source: https://learn.workflow.dog/reference/actions/text/contains-text Check whether one piece of text appears anywhere inside another. The **Contains Text** action searches a string for an exact piece of text and returns a boolean. Use it to route workflows based on keywords, identifiers, or short phrases. ## Inputs | Input | Type | Required | Description | | --------------- | ------- | -------- | ---------------------------------------------------------------- | | **Text** | String | Yes | The text to search. | | **Search** | String | Yes | The exact sequence of characters to find. | | **Ignore Case** | Boolean | No | Compares lowercase versions of both values. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------------------- | | **Result** | Boolean | `true` when **Search** occurs in **Text**; otherwise `false`. | ## Example With **Text** set to `Order REF-204 is ready` and **Search** set to `ref-204`, the result is `false`. Turn on **Ignore Case** to return `true`. The search is literal. Characters such as `.`, `*`, and `?` have no special meaning. Use **Matches Regex** when you need pattern matching. # Count Occurrences Source: https://learn.workflow.dog/reference/actions/text/count-occurrences Count literal text or regular-expression matches inside a string. The **Count Occurrences** action counts how many times a literal string or regular-expression separator appears in text. Switch **Use Regex** to choose the matching mode. ## Inputs | Input | Type | Required | Description | | ------------------ | ------------------ | --------- | ------------------------------------------------------------- | | **Text** | String | Yes | The text to search. | | **Use Regex** | Boolean | Yes | Shows either the literal-text or regex inputs. | | **Search Text** | String | Sometimes | The literal text to count when **Use Regex** is off. | | **Ignore Case** | Boolean | No | Makes literal matching case-insensitive. Defaults to `false`. | | **Search Pattern** | Regular expression | Sometimes | The pattern used when **Use Regex** is on. | ## Outputs | Output | Type | Description | | --------- | ------ | -------------------------------- | | **Count** | Number | The number of occurrences found. | ## Choose a matching mode Literal mode searches for the exact characters in **Search Text**. Turn on **Ignore Case** to compare lowercase versions of the text and search value. With **Text** set to `Error: error: ERROR` and **Search Text** set to `error`, the count is `1` by default or `3` when case is ignored. Regex mode accepts a value from **Regular Expression**. Use a pattern when the matching text varies, such as `INV-\d+`. Regex flags are preserved. A case-insensitive pattern can count different letter cases without using the literal-mode **Ignore Case** option. Avoid capture groups in the regex used for this action. The implementation counts the pieces produced by splitting the text, and captured values are included in that result. Use non-capturing groups such as `(?:foo|bar)` when grouping is required. The action counts non-overlapping occurrences. For example, searching for `aa` in `aaa` returns `1`. # Ends With Source: https://learn.workflow.dog/reference/actions/text/ends-with Check whether text finishes with a specific sequence of characters. The **Ends With** action returns whether a string ends with an exact suffix. It is useful for checking file extensions, domain endings, and naming conventions. ## Inputs | Input | Type | Required | Description | | --------------- | ------- | -------- | ---------------------------------------------------------------- | | **Text** | String | Yes | The text to check. | | **Search** | String | Yes | The suffix expected at the end of the text. | | **Ignore Case** | Boolean | No | Compares lowercase versions of both values. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------------------- | | **Result** | Boolean | `true` when **Text** ends with **Search**; otherwise `false`. | ## Example `report.PDF` ends with `.pdf` only when **Ignore Case** is enabled. The action does not trim whitespace. A trailing space or line break is part of the text and can cause an otherwise matching suffix to return `false`. # Generate UUID Source: https://learn.workflow.dog/reference/actions/text/generate-uuid Create a random version 4 UUID. The **Generate UUID** action creates a new random UUID v4 each time it runs. Use the result as a correlation ID, idempotency key, temporary record ID, or other workflow-scoped identifier. ## Outputs | Output | Type | Description | | -------- | ------ | ------------------------------------------ | | **UUID** | String | A newly generated UUID in standard format. | An output looks like: ```text theme={null} 3f2504e0-4f89-4d3a-9a0c-0305e82c3301 ``` The action produces a different value on every run. Store the output if later workflow steps or future runs need to reuse the same identifier. # Is Email? Source: https://learn.workflow.dog/reference/actions/text/is-email Check whether text has a valid email-address format. The **Is Email?** action validates the shape of an email address and returns a boolean. Use it before routing or storing user-supplied contact data. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------- | | **Text** | String | Yes | The value to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | ----------------------------------------------------------------- | | **Result** | Boolean | `true` when the text has a valid email format; otherwise `false`. | This checks syntax only. It does not verify that the address, domain, or mailbox exists. # Is Text? Source: https://learn.workflow.dog/reference/actions/text/is-string Check whether a workflow value is text. The **Is Text?** action checks the runtime type of any value. It returns `true` only for strings; it does not convert the value first. ## Inputs | Input | Type | Required | Description | | --------- | ---- | -------- | ------------------- | | **Value** | Any | Yes | The value to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------- | | **Result** | Boolean | `true` when **Value** is text; otherwise `false`. | For example, `"42"` returns `true`, while the number `42` returns `false`. # Is URL? Source: https://learn.workflow.dog/reference/actions/text/is-url Check whether text is a valid absolute URL. The **Is URL?** action validates a string as a URL and returns a boolean. Use it to guard actions that expect a complete link. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------- | | **Text** | String | Yes | The value to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------------- | | **Result** | Boolean | `true` when the text is a valid URL; otherwise `false`. | Supply a complete URL such as `https://example.com/report`. A hostname or relative path by itself may not be accepted. # Is UUID? Source: https://learn.workflow.dog/reference/actions/text/is-uuid Check whether text is a valid UUID. The **Is UUID?** action validates a string as a UUID and returns a boolean. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------- | | **Text** | String | Yes | The value to check. | ## Outputs | Output | Type | Description | | ---------- | ------- | -------------------------------------------------------- | | **Result** | Boolean | `true` when the text is a valid UUID; otherwise `false`. | The validator accepts standard UUID text such as `3f2504e0-4f89-41d3-9a0c-0305e82c3301`. It is not limited to UUID v4. # Join Text Source: https://learn.workflow.dog/reference/actions/text/join Combine multiple text values with an optional separator. The **Join Text** action combines a repeatable collection of strings in order. The separator is inserted between adjacent items, never before the first or after the last. ## Inputs | Input | Type | Required | Description | | ------------- | --------------- | -------- | ----------------------------------------------------------------- | | **Separator** | String | No | Text placed between items. Defaults to empty text. | | **Texts** | List of strings | No | The ordered pieces to join. The node starts with two item inputs. | ## Outputs | Output | Type | Description | | ---------- | ------ | ---------------------------------- | | **Joined** | String | All supplied text pieces combined. | ## Examples | Texts | Separator | Joined | | --------------------------- | ---------- | ------------------ | | `red`, `green`, `blue` | `, ` | `red, green, blue` | | `first line`, `second line` | Line Break | Two lines of text | | `ACME`, `1042` | Empty | `ACME1042` | Connect **Line Break** as the separator when building a message from several paragraphs. # Text Length Source: https://learn.workflow.dog/reference/actions/text/length Count the characters in a piece of text. The **Text Length** action returns the number of JavaScript string units in the input. Use it for minimum-length checks, limits, or simple text metrics. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | -------------------- | | **Text** | String | Yes | The text to measure. | ## Outputs | Output | Type | Description | | ---------- | ------ | -------------------------------------- | | **Length** | Number | The measured length of the input text. | Spaces and line breaks are counted. Some emoji and combined Unicode characters can count as more than one unit. # Lowercase Source: https://learn.workflow.dog/reference/actions/text/lowercase Convert every letter in a string to lowercase. The **Lowercase** action converts text with JavaScript's standard lowercase rules. Non-letter characters remain unchanged. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | -------------------- | | **Text** | String | Yes | The text to convert. | ## Outputs | Output | Type | Description | | -------- | ------ | -------------------------------------- | | **text** | String | The input text converted to lowercase. | For example, `Invoice #A19` becomes `invoice #a19`. # Matches Regex Source: https://learn.workflow.dog/reference/actions/text/matches-regex Test whether a regular expression matches any part of a string. The **Matches Regex** action tests a string with a reusable **Regular Expression** value. It returns `true` when the pattern finds a match anywhere in the text. ## Inputs | Input | Type | Required | Description | | --------- | ------------------ | -------- | ------------------------------ | | **Text** | String | Yes | The text to test. | | **Regex** | Regular expression | Yes | The pattern used for the test. | ## Outputs | Output | Type | Description | | ---------- | ------- | ------------------------------------------------- | | **Result** | Boolean | `true` when the regex matches; otherwise `false`. | ## Match the entire value Regex matching is not automatically anchored. A pattern of `\d+` returns `true` for `Order 1042 shipped` because a substring matches. Add anchors when the whole value must follow the pattern: ```text theme={null} ^\d+$ ``` With that pattern, `1042` matches and `Order 1042` does not. Enable the **Multiline** flag only when `^` and `$` should also apply to individual lines. # Line Break Source: https://learn.workflow.dog/reference/actions/text/newline Create text containing a chosen number of line breaks. The **Line Break** action returns a string made entirely of newline characters. It is useful as a separator for **Join Text** or as the separator passed to **Split Text**. ## Inputs | Input | Type | Required | Description | | --------- | ------ | -------- | --------------------------------------------- | | **Count** | Number | No | A non-negative whole number. Defaults to `1`. | ## Outputs | Output | Type | Description | | -------- | ------ | -------------------------------------------------- | | **Text** | String | A string containing exactly **Count** line breaks. | Set **Count** to `2` to create a blank line between joined paragraphs. A count of `0` returns an empty string. # Random Text Source: https://learn.workflow.dog/reference/actions/text/random Generate a random string from selected character groups. The **Random Text** action creates a string of a configured length. Choose whether its characters may include uppercase letters, lowercase letters, numbers, and symbols. ## Inputs | Input | Type | Required | Description | | --------------------- | ------- | -------- | ------------------------------------------------------------- | | **Length** | Number | No | Positive whole-number output length. Defaults to `10`. | | **Include Uppercase** | Boolean | No | Adds `A–Z` to the character set. Defaults to `true`. | | **Include Lowercase** | Boolean | No | Adds `a–z` to the character set. Defaults to `true`. | | **Include Numbers** | Boolean | No | Adds `0–9` to the character set. Defaults to `true`. | | **Include Symbols** | Boolean | No | Adds `!@#$%^&*_-=` to the character set. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------ | -------------------------------------------------- | | **Random** | String | A newly generated string of **Length** characters. | The defaults produce a 10-character alphanumeric string such as `nQ7Lu0xP2a`. Every enabled group contributes characters to one shared pool; the result is not guaranteed to contain a character from every selected group. Keep at least one character group enabled. With every group disabled, there are no characters to choose from and the action cannot produce a result. This action uses general-purpose pseudorandom selection. Do not use its output as a password, authentication token, API secret, or other security-sensitive credential. # Regular Expression Source: https://learn.workflow.dog/reference/actions/text/regex Define a reusable regular-expression pattern and flags. The **Regular Expression** action builds a regex value for other text actions. Use it with **Matches Regex**, **Extract Text with Regex**, **Replace Text**, **Split Text**, or **Count Occurrences**. ## Inputs | Input | Type | Required | Description | | ----------- | ------ | -------- | -------------------------------------------------------------------- | | **Pattern** | String | Yes | A non-empty JavaScript regular-expression pattern. Defaults to `.*`. | | **Flags** | String | No | The selected regex flags. The node defaults to `ig`. | ### Flags | Flag | Setting | Effect | | ---- | --------------- | -------------------------------------------------------- | | `g` | **Global** | Finds or replaces every match instead of only the first. | | `i` | **Ignore case** | Matches letters without case sensitivity. | | `m` | **Multiline** | Makes `^` and `$` work at line boundaries. | | `s` | **Dot-all** | Allows `.` to match line-break characters. | ## Outputs | Output | Type | Description | | --------- | ------------------ | ---------------------------------------- | | **Regex** | Regular expression | The compiled pattern and selected flags. | ## Example: invoice IDs Set **Pattern** to: ```text theme={null} \bINV-\d{4}\b ``` Keep **Global** on to find every ID and **Ignore case** on if `inv-1042` should also match. Connect **Regex** to **Extract Text with Regex** to return the matches. Enter the pattern without wrapping `/` characters. For example, use `\d+`, not `/\d+/g`; choose flags separately. An invalid pattern fails when the action runs. # Replace Text Source: https://learn.workflow.dog/reference/actions/text/replace Replace literal text or regex matches inside a string. The **Replace Text** action searches a string and substitutes the matching content. It supports straightforward literal replacement and reusable regular expressions. ## Inputs | Input | Type | Required | Description | | ------------------------- | ------------------ | --------- | --------------------------------------------------------------- | | **Text** | String | Yes | The text to modify. | | **Use Regex** | Boolean | Yes | Shows either the literal-text or regex inputs. | | **Search Text** | String | Sometimes | Literal characters to replace when **Use Regex** is off. | | **Ignore Case** | Boolean | No | Makes literal matching case-insensitive. Defaults to `false`. | | **Only First Occurrence** | Boolean | No | Replaces only the first literal match. Defaults to `false`. | | **Whole Words** | Boolean | No | Limits literal matches to word boundaries. Defaults to `false`. | | **Search Pattern** | Regular expression | Sometimes | Pattern used when **Use Regex** is on. | | **Replacement** | String | Yes | Text inserted for each match. Empty text removes matches. | ## Outputs | Output | Type | Description | | ------------ | ------ | ------------------------------------- | | **Replaced** | String | The text after replacements are made. | ## Literal replacement Literal mode escapes regex punctuation in **Search Text**, so a value such as `.` matches a period instead of any character. By default, every exact match is replaced. For example, replace `draft` with `final` in: ```text theme={null} draft-report-draft ``` The default result is `final-report-final`. Turn on **Only First Occurrence** to produce `final-report-draft`. **Whole Words** uses regex word boundaries. It works best for letters, numbers, and underscores; punctuation and some non-Latin word boundaries may behave differently than natural-language word detection. ## Regex replacement Regex mode uses the flags configured on **Search Pattern**. A regex with the `g` flag replaces every match; without `g`, only the first match is replaced. Replacement tokens supported by JavaScript are available, including `$&` for the complete match and `$1`, `$2`, and so on for capture groups. For example, use this pattern: ```text theme={null} (\d{4})-(\d{2})-(\d{2}) ``` And this replacement: ```text theme={null} $2/$3/$1 ``` The value `2026-07-24` becomes `07/24/2026`. Literal-mode options disappear when **Use Regex** is enabled. Configure case sensitivity, global matching, and boundaries in the **Regular Expression** action instead. # Extract Text with Regex Source: https://learn.workflow.dog/reference/actions/text/search-regex Find every regex match and return its capture groups. The **Extract Text with Regex** action searches a string and returns a list of all matches. Each result contains the complete matched text and a repeatable list of values captured by parentheses in the pattern. ## Inputs | Input | Type | Required | Description | | ------------------ | ------------------ | -------- | --------------------------------- | | **Text** | String | Yes | The text to search. | | **Search Pattern** | Regular expression | Yes | The pattern used to find matches. | ## Outputs | Output | Type | Description | | ------------------ | --------------- | ----------------------------------------------------- | | **Matches** | List of objects | Every match, in the order it appears in the text. | | **Match** | String | The complete text matched by one result. | | **Capture Groups** | List of strings | The values captured by the pattern's numbered groups. | The action finds all matches even if the connected regex does not have the **Global** flag. Its other flags, such as **Ignore case**, **Multiline**, and **Dot-all**, are preserved. ## Example: extract invoice details Create a **Regular Expression** with: ```text theme={null} Invoice\s+(INV-\d+):\s+\$(\d+(?:\.\d{2})?) ``` For `Invoice INV-1042: $75.50`, the first result contains: * **Match** — `Invoice INV-1042: $75.50` * First capture group — `INV-1042` * Second capture group — `75.50` Connect the entire **Matches** list when a later action can iterate over it, or expose individual repeat outputs when you expect a fixed number of matches. If the pattern has no capture groups, each result still has **Match**, while **Capture Groups** is empty. If nothing matches, **Matches** is an empty list. # Slice Text Source: https://learn.workflow.dog/reference/actions/text/slice Extract part of a string by start and end index. The **Slice Text** action returns the portion of a string between two indexes. Indexes are zero-based, and the character at **End** is not included. ## Inputs | Input | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------------------------------------ | | **Text** | String | Yes | The text to extract from. | | **Start** | Number | No | The first included index. Defaults to `0`. | | **End** | Number | No | The first excluded index. When omitted, the slice runs to the end. | ## Outputs | Output | Type | Description | | --------- | ------ | ------------------------------ | | **Slice** | String | The extracted portion of text. | ## Index behavior * Positive indexes count from the beginning, starting at `0`. * Negative indexes count backward from the end; `-1` refers to the final character. * An index outside the string is clamped to its valid bounds. * If the resolved end comes before the resolved start, the result is empty. For `workflow`, a start of `0` and end of `4` returns `work`. A start of `-4` with no end returns `flow`. # Split Text Source: https://learn.workflow.dog/reference/actions/text/split Break a string into a list using literal text or a regex separator. The **Split Text** action divides a string wherever a separator occurs and returns the pieces in order. Choose between a literal separator and a reusable regular expression. ## Inputs | Input | Type | Required | Description | | --------------------- | ------------------ | --------- | ----------------------------------------------- | | **Text** | String | Yes | The text to split. | | **Use Regex** | Boolean | Yes | Shows the literal or regex separator input. | | **Separator Text** | String | Sometimes | Exact separator used when **Use Regex** is off. | | **Separator Pattern** | Regular expression | Sometimes | Pattern used when **Use Regex** is on. | ## Outputs | Output | Type | Description | | --------- | --------------- | ------------------------------------------------------ | | **Split** | List of strings | The text pieces before, between, and after separators. | ## Examples Split `red,green,blue` with a **Separator Text** of `,` to return: ```json theme={null} ["red", "green", "blue"] ``` Connect **Line Break** as the separator to split text into lines. Split `red, green; blue` with a pattern of `\s*[,;]\s*` to accept either punctuation mark and discard nearby spaces: ```json theme={null} ["red", "green", "blue"] ``` A separator at the beginning or end produces an empty first or last item. Adjacent separators produce empty items between them. Capturing parentheses in a regex separator add the captured separator text to the output list. Use non-capturing groups such as `(?:,|;)` when those values should not become list items. # Starts With Source: https://learn.workflow.dog/reference/actions/text/starts-with Check whether text begins with a specific sequence of characters. The **Starts With** action returns whether a string begins with an exact prefix. Use it to recognize reference formats, URL schemes, commands, or other fixed openings. ## Inputs | Input | Type | Required | Description | | --------------- | ------- | -------- | ---------------------------------------------------------------- | | **Text** | String | Yes | The text to check. | | **Search** | String | Yes | The prefix expected at the beginning of the text. | | **Ignore Case** | Boolean | No | Compares lowercase versions of both values. Defaults to `false`. | ## Outputs | Output | Type | Description | | ---------- | ------- | --------------------------------------------------------------- | | **Result** | Boolean | `true` when **Text** starts with **Search**; otherwise `false`. | ## Example With **Text** set to `INV-1042` and **Search** set to `INV-`, the action returns `true`. Leading spaces and line breaks count. Use **Trim Whitespace** first if the prefix should be checked after surrounding whitespace is removed. # Title Case Source: https://learn.workflow.dog/reference/actions/text/titlecase Turn words and identifiers into start-cased text. The **Title Case** action converts text to start case. It separates common word boundaries—including spaces, punctuation, camel case, and underscores—then capitalizes each resulting word. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | -------------------- | | **Text** | String | Yes | The text to convert. | ## Outputs | Output | Type | Description | | -------- | ------ | ------------------------------------- | | **text** | String | The start-cased version of the input. | ## Examples | Input | Output | | ---------------- | ----------------- | | `customer_name` | `Customer Name` | | `billingAddress` | `Billing Address` | | `MONTHLY-report` | `MONTHLY Report` | This is identifier-friendly start casing, not a grammar-aware publishing style. It does not apply rules for articles, prepositions, or brand names. # Convert to Text Source: https://learn.workflow.dog/reference/actions/text/to-string Coerce a workflow value into text. The **Convert to Text** action turns an incoming value into a string. Use it when a later action requires text but the current value is a number, boolean, or another coercible type. ## Inputs | Input | Type | Required | Description | | --------- | ---- | -------- | --------------------- | | **Value** | Any | Yes | The value to convert. | ## Outputs | Output | Type | Description | | -------- | ------ | ------------------------- | | **Text** | String | The coerced string value. | Common primitive conversions include `42` → `"42"` and `true` → `"true"`. Conversion is not JSON serialization. Complex values may not produce the structured text you expect; serialize them explicitly when the exact format matters. # Trim Whitespace Source: https://learn.workflow.dog/reference/actions/text/trim Remove whitespace from both ends of a string. The **Trim Whitespace** action removes leading and trailing whitespace while leaving whitespace inside the text unchanged. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ----------------- | | **Text** | String | Yes | The text to trim. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------------ | | **Trimmed** | String | The text without leading or trailing whitespace. | Spaces, tabs, and line breaks at either end are removed. To reduce repeated whitespace within the text, use **Collapse Whitespace**. # Uppercase Source: https://learn.workflow.dog/reference/actions/text/uppercase Convert every letter in a string to uppercase. The **Uppercase** action converts text with JavaScript's standard uppercase rules. Non-letter characters remain unchanged. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | -------------------- | | **Text** | String | Yes | The text to convert. | ## Outputs | Output | Type | Description | | -------- | ------ | -------------------------------------- | | **TEXT** | String | The input text converted to uppercase. | For example, `Invoice #a19` becomes `INVOICE #A19`. # Cancel Booking Source: https://learn.workflow.dog/reference/actions/tidycal/cancel-booking Cancel a TidyCal booking by ID. **Cancel Booking** marks an existing TidyCal booking as cancelled. | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ------------------------------------------------ | | **Third-party account** | TidyCal account | Yes | The account containing the booking. | | **Booking ID** | Positive integer | Yes | The booking to cancel. | | **Reason** | String | No | An optional cancellation reason sent to TidyCal. | The action has no output. # Create Booking Source: https://learn.workflow.dog/reference/actions/tidycal/create-booking Book a TidyCal timeslot for a contact. **Create Booking** creates an appointment for a TidyCal booking type. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | --------------------------------------------------------------------------- | | **Third-party account** | TidyCal account | Yes | The account that owns the booking type. | | **Booking Type** | String or number | Yes | A booking type ID such as `418343` or URL slug such as `15-minute-meeting`. | | **Start Time** | Date | Yes | When the appointment begins. | | **Name** | String | Yes | The person making the booking. | | **Email** | Email | Yes | The person's email address. | | **Timezone** | String | Yes | The timezone used for the booking. | ## Output | Output | Type | Description | | -------------- | ------ | ----------------------------------------- | | **Booking ID** | Number | TidyCal's identifier for the new booking. | Check availability before creating the booking. This action fails when the booking type cannot be found or TidyCal rejects the requested time. # Get Booking Source: https://learn.workflow.dog/reference/actions/tidycal/get-booking Retrieve complete details for a TidyCal booking. **Get Booking** fetches one TidyCal booking by its ID. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ----------------------------------- | | **Third-party account** | TidyCal account | Yes | The account containing the booking. | | **Booking ID** | Positive integer | Yes | The booking to retrieve. | ## Outputs The action returns **Booking ID**, **Booking Type**, **Starts At**, **Ends At**, **Timezone**, **Meeting URL**, **Contact ID**, **Contact Name**, **Contact Email**, **Created At**, and **Cancelled At**. **Questions** is a list of `{ question, answer }` objects containing the custom booking-form responses. **Cancelled At** and **Meeting URL** can be empty when they do not apply. # List Available Timeslots Source: https://learn.workflow.dog/reference/actions/tidycal/list-available-timeslots Find open times for a TidyCal booking type. **List Available Timeslots** returns open intervals for a booking type within a date range. ## Inputs | Input | Type | Required | Description | | ----------------------- | ---------------- | -------- | ----------------------------------------------------------------- | | **Third-party account** | TidyCal account | Yes | The account that owns the booking type. | | **Booking Type** | String or number | Yes | The booking type ID or URL slug. | | **Starts After** | Date | No | The beginning of the search window. Defaults to the current time. | | **Ends Before** | Date | Yes | The end of the search window. | ## Output **Timeslots** is a list of objects with: * **Start Time** * **End Time** * **Available Slots** — Remaining capacity, including group-booking capacity. **Ends Before** must be later than **Starts After**. The action fails when the range is reversed or the booking type does not exist. # List Bookings Source: https://learn.workflow.dog/reference/actions/tidycal/list-bookings List TidyCal bookings with optional date filters. **List Bookings** retrieves bookings from a TidyCal account, optionally limited to a time window. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------ | | **Third-party account** | TidyCal account | Yes | The account to inspect. | | **Starts After** | Date | No | Include bookings starting on or after this time. | | **Ends Before** | Date | No | Include bookings ending before this time. | ## Output **Bookings** is a list. Each item includes booking ID and type, start and end times, timezone, meeting URL, contact details, creation and cancellation timestamps, and a list of custom question/answer pairs. Leave both dates empty to retrieve the account's available booking history, or set a narrow range before processing every booking downstream. # Add Attachment Source: https://learn.workflow.dog/reference/actions/trello/add-attachment Attach a public URL to a Trello card. **Add Attachment** adds a URL attachment to a Trello card and can use it as the card cover. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | --------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Attachment URL** | URL | Yes | The public URL to attach. | | **Name** | String | No | An optional attachment display name. | | **Set Cover** | Boolean | No | Use the attachment as the cover. Default off. | ## Outputs | Output | Type | Description | | ----------------- | ------ | ------------------------------------------- | | **Attachment** | Object | The created attachment's normalized fields. | | **Attachment ID** | String | Trello's identifier for the attachment. | **Attachment** exposes **ID**, **Name**, **URL**, **Bytes**, **Added At**, **MIME Type**, **Is Upload**, and **Position**. Some metadata may be empty for URL attachments. # Add Checklist Item Source: https://learn.workflow.dog/reference/actions/trello/add-checklist-item Add an item to a Trello checklist. **Add Checklist Item** creates a task within an existing Trello checklist. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------------ | | **Third-party account** | Trello account | Yes | An account with write access to the checklist. | | **Checklist ID** | String | Yes | The destination Trello checklist. | | **Name** | String | Yes | The checklist item name. | | **Position** | Choice | No | Put it at the `top` or `bottom`. Defaults to `bottom`. | | **Completed** | Boolean | No | Create the item as complete. Defaults to off. | | **Due** | Date | No | The checklist item due date. | ## Outputs | Output | Type | Description | | ----------- | ------ | ----------------------------------------------- | | **Item** | Object | The created checklist item's normalized fields. | | **Item ID** | String | Trello's identifier for the item. | **Item** exposes **ID**, **Checklist ID**, **Name**, **State**, **Completed**, **Position**, **Due**, and **Member ID**. # Add Comment Source: https://learn.workflow.dog/reference/actions/trello/add-comment Add a comment to a Trello card. **Add Comment** posts a non-empty text comment to a Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Text** | String | Yes | The comment text. | ## Outputs | Output | Type | Description | | -------------- | ------ | ---------------------------------------- | | **Comment** | Object | The created comment's normalized fields. | | **Comment ID** | String | Trello's action ID for the comment. | **Comment** exposes **ID**, **Text**, **Commented At**, **Creator Name**, and **Creator Username**. # Add Labels Source: https://learn.workflow.dog/reference/actions/trello/add-labels Add existing labels to a Trello card. **Add Labels** adds one or more labels without changing the card's other labels. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ---------------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Labels** | List of strings | Yes | Label IDs, names, or colors. Matching is case-insensitive. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------ | | **Card** | Object | The card after its labels are added. | | **Card ID** | String | The updated card's ID. | Label IDs take precedence over names, and names take precedence over colors. Duplicate references are applied only once. A color or name that matches multiple labels is ambiguous. Use a label ID to identify the intended label. # Add Members Source: https://learn.workflow.dog/reference/actions/trello/add-members Assign board members to a Trello card. **Add Members** assigns one or more members without replacing the card's current members. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Members** | List of strings | Yes | Member IDs, usernames, or full names. Matching is case-insensitive. | ## Outputs | Output | Type | Description | | ----------- | ------ | ---------------------------------------- | | **Card** | Object | The card after the members are assigned. | | **Card ID** | String | The updated card's ID. | Member IDs take precedence over usernames, and usernames take precedence over full names. A full name shared by multiple board members is ambiguous. Use a member ID or unique username instead. # Create Card Source: https://learn.workflow.dog/reference/actions/trello/create-card Create a card in a Trello list. **Create Card** adds a card to a Trello list and can assign labels, members, dates, and an initial position. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------ | | **Third-party account** | Trello account | Yes | An account with write access to the board. | | **List ID** | String | Yes | The destination Trello list. | | **Name** | String | Yes | The card name. | | **Description** | String | No | The card description. | | **Labels** | List of strings | No | Label IDs, names, or colors. Matching is case-insensitive. | | **Members** | List of strings | No | Member IDs, usernames, or full names. Matching ignores case. | | **Position** | Choice | No | Put the card at the `top` or `bottom`. Defaults to `bottom`. | | **Due** | Date | No | The card due date. | | **Start** | Date | No | The card start date. | | **Due Complete** | Boolean | No | Whether the due date is complete. Defaults to off. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------- | | **Card** | Object | The created card and its normalized fields. | | **Card ID** | String | Trello's identifier for the created card. | **Card** exposes the card's name, description, archived state, board and list IDs, URLs, position, dates, member IDs, label IDs, and last activity time. Label colors and full member names can be ambiguous. Use IDs when more than one board label or member could match. # Create Checklist Source: https://learn.workflow.dog/reference/actions/trello/create-checklist Create a checklist on a Trello card. **Create Checklist** adds an empty checklist to a Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------------ | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Name** | String | Yes | The checklist name. | | **Position** | Choice | No | Put it at the `top` or `bottom`. Defaults to `bottom`. | ## Outputs | Output | Type | Description | | ---------------- | ------ | ------------------------------------------ | | **Checklist** | Object | The created checklist's normalized fields. | | **Checklist ID** | String | Trello's identifier for the checklist. | **Checklist** exposes **ID**, **Card ID**, **Board ID**, **Name**, **Position**, **Items**, **Item Count**, and **Completed Item Count**. # Delete Attachment Source: https://learn.workflow.dog/reference/actions/trello/delete-attachment Permanently remove an attachment from a Trello card. **Delete Attachment** permanently removes one attachment from a Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Attachment ID** | String | Yes | The attachment to delete. | ## Output | Output | Type | Description | | ----------------- | ------ | -------------------------- | | **Attachment ID** | String | The deleted attachment ID. | Deleting an attachment cannot be undone by this action. # Delete Checklist Source: https://learn.workflow.dog/reference/actions/trello/delete-checklist Permanently delete a Trello checklist. **Delete Checklist** permanently removes a checklist and its items from Trello. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ---------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the checklist. | | **Checklist ID** | String | Yes | The Trello checklist to delete. | The action has no output. Continue the workflow after Trello confirms the checklist was deleted. Deleting a checklist also removes its checklist items and cannot be undone by this action. # Delete Checklist Item Source: https://learn.workflow.dog/reference/actions/trello/delete-checklist-item Permanently delete an item from a Trello checklist. **Delete Checklist Item** permanently removes one item from a Trello checklist. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ---------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the checklist. | | **Checklist ID** | String | Yes | The checklist that contains the item. | | **Item ID** | String | Yes | The Trello checklist item to delete. | The action has no output. Continue the workflow after Trello confirms the item was deleted. Deleting a checklist item cannot be undone by this action. # Get Card Source: https://learn.workflow.dog/reference/actions/trello/get-card Get a Trello card by ID, short link, or URL. **Get Card** retrieves one Trello card using any common Trello card reference. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------ | | **Card** | Object | The card and its normalized fields. | | **Card ID** | String | Trello's identifier for the returned card. | The card object exposes **ID**, **Name**, **Description**, **Closed**, **Board ID**, **List ID**, **URL**, **Short URL**, **Position**, **Due**, **Start**, **Due Complete**, **Member IDs**, **Label IDs**, and **Last Activity At**. # Get List Cards Source: https://learn.workflow.dog/reference/actions/trello/get-list-cards Get cards from a Trello list. **Get List Cards** retrieves cards currently associated with one Trello list. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with access to the list. | | **List ID** | String | Yes | The Trello list to inspect. | | **Filter** | Choice | No | `open`, `closed`, or `all`. Defaults to `open`. | ## Outputs | Output | Type | Description | | --------- | --------------- | ----------------------------- | | **Cards** | List of objects | Cards in the selected list. | | **Count** | Number | The number of cards returned. | Each card includes its IDs, name, description, archived state, URLs, position, dates, members, labels, and last activity time. # List Attachments Source: https://learn.workflow.dog/reference/actions/trello/list-attachments List attachments on a Trello card. **List Attachments** retrieves every attachment associated with one Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | ## Outputs | Output | Type | Description | | --------------- | --------------- | ----------------------------------- | | **Attachments** | List of objects | Attachments on the card. | | **Count** | Number | The number of attachments returned. | Each attachment exposes **ID**, **Name**, **URL**, **Bytes**, **Added At**, **MIME Type**, **Is Upload**, and **Position**. # List Board Lists Source: https://learn.workflow.dog/reference/actions/trello/list-board-lists List the columns on a Trello board. **List Board Lists** retrieves the lists, or columns, on one Trello board. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with access to the board. | | **Board ID** | String | Yes | The board whose lists should be returned. | | **Filter** | Choice | No | `open`, `closed`, or `all`. Defaults to `open`. | ## Outputs | Output | Type | Description | | --------- | --------------- | ----------------------------- | | **Lists** | List of objects | Lists on the selected board. | | **Count** | Number | The number of lists returned. | Each list exposes **ID**, **Name**, **Closed**, **Board ID**, and **Position**. Pass a list ID to **Create Card** or **Get List Cards**. # List Board Members Source: https://learn.workflow.dog/reference/actions/trello/list-board-members List members of a Trello board. **List Board Members** retrieves the people who belong to one Trello board. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------ | | **Third-party account** | Trello account | Yes | An account with access to the board. | | **Board ID** | String | Yes | The board whose members are listed. | ## Outputs | Output | Type | Description | | ----------- | --------------- | ------------------------------- | | **Members** | List of objects | Members of the selected board. | | **Count** | Number | The number of members returned. | Each member exposes **ID**, **Full Name**, and **Username**. Member IDs are the safest values to pass to card actions when two people have the same full name. # List Boards Source: https://learn.workflow.dog/reference/actions/trello/list-boards List Trello boards available to the connected account. **List Boards** retrieves boards that the connected Trello account can access. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ----------------------------------------------- | | **Third-party account** | Trello account | Yes | The account whose boards are listed. | | **Filter** | Choice | No | `open`, `closed`, or `all`. Defaults to `open`. | ## Outputs | Output | Type | Description | | ---------- | --------------- | -------------------------------- | | **Boards** | List of objects | The boards available to account. | | **Count** | Number | The number of boards returned. | Each board exposes **ID**, **Name**, **Description**, **Closed**, **URL**, **Short URL**, and **Last Activity At**. Use the returned board ID with **List Board Lists**, **List Board Members**, or a Trello card trigger. # List Card Checklists Source: https://learn.workflow.dog/reference/actions/trello/list-card-checklists List checklists and their items on a Trello card. **List Card Checklists** retrieves every checklist on one card, including its checklist items. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | ## Outputs | Output | Type | Description | | -------------- | --------------- | ---------------------------------- | | **Checklists** | List of objects | Checklists on the card. | | **Count** | Number | The number of checklists returned. | Each checklist exposes **ID**, **Card ID**, **Board ID**, **Name**, **Position**, **Items**, **Item Count**, and **Completed Item Count**. Each item contains its ID, checklist ID, name, state, completion status, position, due date, and assigned member ID. # List Comments Source: https://learn.workflow.dog/reference/actions/trello/list-comments List comments on a Trello card. **List Comments** retrieves recent comment actions from one Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------ | | **Third-party account** | Trello account | Yes | An account with access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Limit** | Number | No | Comments to return, from 1 to 1000. Default 100. | ## Outputs | Output | Type | Description | | ------------ | --------------- | -------------------------------- | | **Comments** | List of objects | The returned card comments. | | **Count** | Number | The number of comments returned. | Each comment exposes **ID**, **Text**, **Commented At**, **Creator Name**, and **Creator Username**. Creator details can be empty when Trello omits them. # Remove Labels Source: https://learn.workflow.dog/reference/actions/trello/remove-labels Remove selected labels from a Trello card. **Remove Labels** removes one or more labels without changing the card's other labels. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ---------------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Labels** | List of strings | Yes | Label IDs, names, or colors. Matching is case-insensitive. | ## Outputs | Output | Type | Description | | ----------- | ------ | -------------------------------------- | | **Card** | Object | The card after its labels are removed. | | **Card ID** | String | The updated card's ID. | Use **Update Card** with an empty **Labels** list when every label should be removed. # Remove Members Source: https://learn.workflow.dog/reference/actions/trello/remove-members Unassign selected members from a Trello card. **Remove Members** unassigns one or more members without changing the card's other members. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Members** | List of strings | Yes | Member IDs, usernames, or full names. Matching is case-insensitive. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------ | | **Card** | Object | The card after the members are unassigned. | | **Card ID** | String | The updated card's ID. | Use **Update Card** with an empty **Members** list when every member should be removed. # Search Cards Source: https://learn.workflow.dog/reference/actions/trello/search-cards Search Trello cards by text. **Search Cards** searches accessible Trello cards by text and can restrict the search to one board. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | ------------------------------------------------------ | | **Third-party account** | Trello account | Yes | The account used to search Trello. | | **Query** | String | Yes | Non-empty search text. | | **Board ID** | String | No | Restrict results to one board. | | **Limit** | Number | No | Cards per page, from 1 to 1000. Defaults to 50. | | **Page** | Number | No | Zero-based results page, from 0 to 100. Defaults to 0. | | **Partial** | Boolean | No | Match partial words. Defaults to off. | ## Outputs | Output | Type | Description | | --------- | --------------- | --------------------------------- | | **Cards** | List of objects | Cards matching the search. | | **Count** | Number | The number of cards on this page. | Increase **Page** to retrieve later results. **Count** describes only the returned page, not every possible match. # Update Card Source: https://learn.workflow.dog/reference/actions/trello/update-card Edit, move, complete, archive, or reopen a Trello card. **Update Card** changes one or more fields on an existing Trello card. ## Inputs | Input | Type | Required | Description | | ----------------------- | --------------- | -------- | ------------------------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | A card ID, short link, or complete card URL. | | **Name** | String | No | A new card name. | | **Description** | String | No | A new card description. | | **Labels** | List of strings | No | Replacement label IDs, names, or colors; an empty list removes all. | | **Members** | List of strings | No | Replacement member IDs, usernames, or names; empty removes all. | | **List ID** | String | No | Move the card to this list. | | **Closed** | Boolean | No | Archive the card when on, or reopen it when off. | | **Position** | Choice | No | Move the card to the `top` or `bottom` of its list. | | **Due** | Date | No | Set a new due date. | | **Clear Due Date** | Boolean | No | Remove the due date. | | **Start** | Date | No | Set a new start date. | | **Clear Start Date** | Boolean | No | Remove the start date. | | **Due Complete** | Boolean | No | Set whether the due date is complete. | Provide at least one field to update. **Due** cannot be combined with **Clear Due Date**, and **Start** cannot be combined with **Clear Start Date**. ## Outputs | Output | Type | Description | | ----------- | ------ | ----------------------------------------- | | **Card** | Object | The card after Trello applies the update. | | **Card ID** | String | The updated card's ID. | **Labels** and **Members** replace the complete existing sets. Use **Add Labels**, **Remove Labels**, **Add Members**, or **Remove Members** to make an incremental change. # Update Checklist Item Source: https://learn.workflow.dog/reference/actions/trello/update-checklist-item Edit a Trello checklist item. **Update Checklist Item** renames, completes, reschedules, or repositions an item in a Trello checklist. ## Inputs | Input | Type | Required | Description | | ----------------------- | -------------- | -------- | -------------------------------------------------- | | **Third-party account** | Trello account | Yes | An account with write access to the card. | | **Card ID or URL** | String | Yes | The parent card's ID, short link, or complete URL. | | **Item ID** | String | Yes | The Trello checklist item to update. | | **Name** | String | No | A new item name. | | **State** | Choice | No | Mark the item `complete` or `incomplete`. | | **Position** | Choice | No | Move the item to the `top` or `bottom`. | | **Due** | Date | No | A new item due date. | Provide at least one field to update. ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------ | | **Item** | Object | The checklist item after the update. | | **Item ID** | String | The updated checklist item ID. | The item object includes its checklist ID, name, state, completion status, position, due date, and assigned member ID. # Build URL Source: https://learn.workflow.dog/reference/actions/utilities/build-url Construct an absolute URL from a base, path, query parameters, and fragment. The **Build URL** action assembles and safely serializes a URL. It resolves an optional path against the base URL, sets query parameters, and adds a fragment. ## Inputs | Input | Type | Required | Description | | -------------------- | ----------------- | --------- | ------------------------------------------------------ | | **Base URL** | String | Yes | A valid absolute base URL. | | **Path** | String | No | A relative or absolute path resolved against the base. | | **Query Parameters** | Key/value entries | No | Parameter names and string values to set. | | **Name** | String | Per entry | The query-parameter name. | | **Value** | String | Per entry | The query-parameter value. | | **Fragment** | String | No | The hash fragment, with or without a leading `#`. | ## Outputs | Output | Type | Description | | ------- | ------ | ---------------------------- | | **URL** | String | The complete serialized URL. | ## Example Configure: | Setting | Value | | --------------- | ----------------------------- | | **Base URL** | `https://api.example.com/v1/` | | **Path** | `customers/42` | | Query `include` | `orders` | | **Fragment** | `details` | The result is: ```text theme={null} https://api.example.com/v1/customers/42?include=orders#details ``` Parameter names and values are percent-encoded automatically. A parameter set here replaces an existing base-URL parameter with the same name. URL path resolution follows browser rules. A relative path preserves the last base segment only when the base path ends in `/`; a path beginning with `/` replaces the base path from the host root. # Decode URI Component Source: https://learn.workflow.dog/reference/actions/utilities/decode-uri-component Convert percent-encoded URL text back to readable text. The **Decode URI Component** action reverses percent encoding for one URL component. ## Inputs | Input | Type | Required | Description | | ----------- | ------ | -------- | ------------------------- | | **Encoded** | String | Yes | The percent-encoded text. | ## Outputs | Output | Type | Description | | -------- | ------ | ----------------- | | **Text** | String | The decoded text. | For example, `quarterly%20report%20%26%20notes` becomes `quarterly report & notes`. A `+` remains a plus sign. This action does not apply HTML form-query rules that sometimes interpret `+` as a space. Invalid or incomplete percent escapes, such as `%E0%A4%A`, cause the action to fail. # Delay Source: https://learn.workflow.dog/reference/actions/utilities/delay Pause the current workflow for up to five seconds. The **Delay** action waits for a duration before the next connected action can run. Use it for short pacing intervals—not long-term scheduling. ## Inputs | Input | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------------------------------ | | **Duration** | Number | Yes | Seconds to wait, from `0` through `5`. The runtime default is `1`. | This action has no data outputs. Workflow execution continues after the wait finishes. Decimal durations are supported; `0.5` waits for approximately half a second. Actual timing may be slightly longer under load. Values below `0` or above `5` are rejected. Use a schedule or another purpose-built waiting mechanism for delays longer than five seconds. # Encode URI Component Source: https://learn.workflow.dog/reference/actions/utilities/encode-uri-component Percent-encode text for use as one part of a URL. The **Encode URI Component** action escapes text so it can safely occupy a single URL component, such as a query value, path segment, or fragment value. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------- | | **Text** | String | Yes | The text to encode. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------- | | **Encoded** | String | The percent-encoded text. | For example: ```text theme={null} quarterly report & notes ``` becomes: ```text theme={null} quarterly%20report%20%26%20notes ``` This encodes one component, not a complete URL. Use **Build URL** when constructing a URL from several parts. # Encode URI Parameters Source: https://learn.workflow.dog/reference/actions/utilities/encode-uri-params Turn parameter entries into a URL query string. The **Encode URI Parameters** action serializes key/value entries into query string format without adding the leading `?`. ## Inputs | Input | Type | Required | Description | | -------------- | ----------------- | --------- | ---------------------------------- | | **Parameters** | Key/value entries | No | The query parameters to serialize. | | **Name** | String | Per entry | The parameter name. | | **Value** | String | Per entry | The parameter value. | ## Outputs | Output | Type | Description | | ----------- | ------ | --------------------------------------- | | **Encoded** | String | The query string without a leading `?`. | For `search = red shoes` and `page = 2`, the result is: ```text theme={null} search=red+shoes&page=2 ``` Names and values are encoded with standard URL query rules. Empty parameter sets produce empty text. Parameter entries form an object, so each name can occur only once. Use a different approach when an API requires repeated keys such as `tag=a&tag=b`. # Escape HTML Source: https://learn.workflow.dog/reference/actions/utilities/escape-html Replace HTML-sensitive characters with safe entities. The **Escape HTML** action converts characters that could be interpreted as markup into HTML entities. Use it when inserting plain user-supplied text into an HTML string. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | ------------------------- | | **Text** | String | Yes | The plain text to escape. | ## Outputs | Output | Type | Description | | ----------- | ------ | -------------------------------------- | | **Escaped** | String | The text with HTML characters escaped. | For example: ```html theme={null} Hello ``` becomes: ```html theme={null} <strong title="A & B">Hello</strong> ``` The action escapes `&`, `<`, `>`, double quotes, and single quotes. It does not sanitize or validate an existing HTML document. # Execute Code Source: https://learn.workflow.dog/reference/actions/utilities/execute-code Run custom JavaScript or TypeScript with Bun and return named exports. The **Execute Code** action runs a JavaScript or TypeScript module in a temporary Bun container. Use it when a workflow needs a transformation that available actions cannot express. Custom code can make network requests, import packages, consume resources, and expose any values connected as inputs. Review the code and every input before running it, especially credentials or personal data. ## Inputs | Input | Type | Required | Description | | ------------------------------ | ------------------------ | --------- | ----------------------------------------------------------------------- | | **Code** | String | Yes | The module source to execute. | | **Language** | JavaScript or TypeScript | Yes | The source language. Defaults to **TypeScript**. | | **Input Variables** | Key/value entries | No | JSON-serializable values exposed to the module. | | **Name** | String | Per entry | The property name in the input object. | | **Value** | JSON value | Per entry | The value available under that name. | | **Include Timestamps In Logs** | Boolean | No | Prefixes captured log lines with local timestamps. Defaults to `false`. | ## Outputs | Output | Type | Description | | ----------- | ------ | ------------------------------------------------------------ | | **Outputs** | Object | The JSON-serializable named exports from the module. | | **Logs** | String | Captured standard output and standard error, joined as text. | You can expose properties from **Outputs** as individual node outputs, then connect only the values later actions need. ## Read inputs and return outputs Import the default export from `./inputs`, then export each result as a named value: ```ts theme={null} import inputs from "./inputs" const subtotal = Number(inputs.subtotal) const taxRate = Number(inputs.taxRate) export const tax = subtotal * taxRate export const total = subtotal + tax console.log(`Calculated total for ${subtotal}`) ``` Configure **Input Variables** with `subtotal` and `taxRate`. The action returns: ```json theme={null} { "tax": 8, "total": 108 } ``` The message written with `console.log` appears in **Logs**, not **Outputs**. Use identifier-like input names such as `customerId` or `lineItems`. They are easier to access as `inputs.customerId` and produce useful TypeScript editor hints. ## Import packages Code runs with the Bun runtime, so standard imports are supported: ```ts theme={null} import inputs from "./inputs" import { groupBy } from "lodash-es" export const grouped = groupBy(inputs.orders, "status") ``` Bun can resolve npm package imports during execution. Version specifiers may be used when the exact package version matters. ## Serialization rules Inputs and outputs cross the action boundary as JSON: * Inputs may contain strings, numbers, booleans, `null`, lists, and objects. * Exported functions, symbols, `undefined`, and other non-JSON values are not reliable outputs. * `BigInt`, circular objects, and other values that JSON cannot serialize cause the run to fail. * Class instances lose behavior when serialized; return plain data instead. The code is executed as a module. Only exported values are returned. Local variables stay private unless you add a named export. ## Troubleshooting Confirm that its **Input Variables** name matches the property read from the default `./inputs` export. Names are case-sensitive. Add named exports such as `export const result = value`. Logging a value does not return it. Check every exported value for JSON compatibility. Remove functions, `BigInt`, circular references, and unsupported runtime objects. Check the package name and import path. If reproducibility matters, specify a supported npm version in the import rather than relying on the latest resolved package. # HTML to Markdown Source: https://learn.workflow.dog/reference/actions/utilities/html-to-md Convert HTML markup into Markdown text. The **HTML to Markdown** action converts an HTML string into a Markdown representation. Use it to make web or email content easier to store, summarize, or send through text-oriented actions. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | --------------------------- | | **HTML** | String | Yes | The HTML markup to convert. | ## Outputs | Output | Type | Description | | ------------ | ------ | ---------------------------- | | **Markdown** | String | The converted Markdown text. | For example: ```html theme={null}

Status

The build is ready.

``` becomes Markdown similar to: ```markdown theme={null} ## Status The build is **ready**. - Tests passed - Review complete ``` HTML and Markdown do not have identical feature sets. Complex tables, custom elements, inline styles, and layout markup may be simplified or omitted. # HTML to Text Source: https://learn.workflow.dog/reference/actions/utilities/html-to-text Convert HTML markup into readable plain text. The **HTML to Text** action removes markup while preserving readable structure for headings, paragraphs, lists, and links. Use it before keyword matching, plain-text notifications, or AI prompts that do not need HTML. ## Inputs | Input | Type | Required | Description | | -------- | ------ | -------- | --------------------------- | | **HTML** | String | Yes | The HTML markup to convert. | ## Outputs | Output | Type | Description | | -------- | ------ | ------------------------- | | **Text** | String | The converted plain text. | For example: ```html theme={null}

Hello Ada.

Your order is ready.

``` produces readable text with the two paragraph contents and no `

` or `` tags. This is a content conversion, not an HTML sanitizer. The output is plain text, but conversion choices such as line wrapping and link rendering follow the action's built-in defaults. # Markdown to HTML Source: https://learn.workflow.dog/reference/actions/utilities/markdown-to-html Render Markdown text as HTML. The **Markdown to HTML** action renders headings, emphasis, links, lists, code blocks, and other supported Markdown syntax into an HTML string. ## Inputs | Input | Type | Required | Description | | ------------ | ------ | -------- | ---------------------------- | | **Markdown** | String | Yes | The Markdown text to render. | ## Outputs | Output | Type | Description | | -------- | ------ | ------------------------- | | **HTML** | String | The rendered HTML markup. | For example: ```markdown theme={null} ## Status The build is **ready**. ``` renders approximately: ```html theme={null}

Status

The build is ready.

``` The generated HTML is not sanitized. Markdown can contain raw HTML, links, and other content that is unsafe to render in a trusted page or email without a separate sanitization policy. # Resolve Account Secret Source: https://learn.workflow.dog/reference/actions/utilities/resolve-account-secret Expose the credential data stored in a connected third-party account. The **Resolve Account Secret** action returns the raw secret object behind a third-party account. It is intended for advanced integrations whose generic HTTP or code step must use credentials that no dedicated action supports. This action exposes credentials in plain text to the workflow graph and run data. Use it only when no safer account-aware action is available. Never send the output to logs, messages, analytics, or untrusted services. ## Inputs | Input | Type | Required | Description | | ----------- | ------------------- | -------- | ------------------------------------------- | | **Account** | Third-party account | Yes | The connected account whose secret is read. | ## Outputs | Output | Type | Description | | ---------- | ------ | ------------------------------------ | | **Secret** | Object | The account's raw credential fields. | The available fields depend on the account type. An API-key account may expose a key, while an OAuth account may include access or refresh tokens. ## Handle the output safely * Connect only the specific secret field required by the next trusted action. * Do not copy secrets into static node configuration. * Do not include the secret in **Execute Code** logs or error messages. * Remove this action after replacing a custom integration with a dedicated account-aware action. Resolving a secret does not refresh, rotate, or validate the credential. It returns the value currently stored for the selected account. # Validate JSON Schema Source: https://learn.workflow.dog/reference/actions/utilities/validate-json-schema Validate any value against JSON Schema and expose validation results. The **Validate JSON Schema** action checks workflow data against a JSON Schema. It returns a boolean and every validation error. For object schemas, it also creates outputs for the schema's top-level properties. ## Inputs | Input | Type | Required | Description | | ---------- | ------ | -------- | --------------------------- | | **Data** | Any | Yes | The value to validate. | | **Schema** | String | Yes | A JSON-encoded JSON Schema. | ## Outputs | Output | Type | When shown | Description | | ------------- | --------------- | ----------------------------- | ---------------------------------------------- | | **Is Valid** | Boolean | Always | Whether **Data** satisfies the schema. | | **Errors** | List of strings | Always | All validation errors; empty when valid. | | **Validated** | Varies | Non-object schemas | The original data value after validation. | | Property name | Varies | Object schema with properties | The original value of that top-level property. | The schema editor uses top-level `type` and `properties` to configure the additional outputs. String, number, integer, boolean, and object properties receive matching workflow types; arrays and unknown schema types remain untyped. ## Example: validate a customer Use this schema: ```json theme={null} { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "age": { "type": "integer", "minimum": 18 }, "active": { "type": "boolean" } }, "required": ["name", "age"], "additionalProperties": false } ``` The node exposes `name`, `age`, and `active` as outputs. For: ```json theme={null} { "name": "Ada", "age": 17, "active": true } ``` **Is Valid** is `false`, and **Errors** includes an entry similar to: ```text theme={null} /age: must be >= 18 ``` The property outputs still expose the supplied values, even when validation fails. Use **Is Valid** to guard any branch that consumes them. Validation does not coerce types or remove additional properties. The string `"18"` does not satisfy an `integer` schema, and the returned values are the original input values. ## Error behavior Validation failures are normal results: **Is Valid** becomes `false`, and **Errors** describes every detected problem. By contrast, malformed JSON or an invalid schema causes the action itself to fail before data can be validated. JSON does not allow comments, trailing commas, or single-quoted strings. Parse the schema as JSON and try again. The schema defines the output because the property exists under `properties`, but the input data did not provide that own top-level key. Check **Is Valid** and **Errors** before using the output. The validator collects all errors it can detect in one pass. Fix the reported schema-level or parent-value problem first; additional nested checks may only become meaningful afterward. # Sub-Workflow Source: https://learn.workflow.dog/reference/triggers/core/callable Run this workflow when another workflow calls it. The **Sub-Workflow** trigger turns a workflow into a reusable operation. Call it with **Run Workflow**, **Loop Workflow**, **Schedule Workflow**, or an action that accepts a callable workflow. ## Quick start Select **When another workflow calls this one** as the trigger. Add **Data from Trigger**. Its **Data In** output contains the caller's payload. Add **Return Data** and connect the value the caller should receive. In another workflow, add **Run Workflow**, select this workflow, and connect a payload. ## Trigger data | Output | Type | Description | | ----------- | ---- | ----------------------------------- | | **Data In** | Any | The payload supplied by the caller. | If the workflow does not use **Return Data**, a waiting caller receives `null`. Scheduled callers do not wait for a response. Sub-workflow runs do not accrue usage costs. Recursive calls are rate-limited to 10 calls per second to prevent infinite recursion. A failure in this workflow propagates to callers that wait for completion, such as **Run Workflow** and **Loop Workflow**. # Mail Hook Source: https://learn.workflow.dog/reference/triggers/core/email-hook Run a workflow whenever its unique email address receives a message. The **Mail Hook** trigger gives the workflow a unique inbound email address. Send or forward a message to that address to start a run. ## Quick start The trigger panel displays this workflow's unique address. Use **Copy Address**, then add it as a recipient, forwarding destination, or automation target in any email service. Add **Data from Trigger** and connect the sender, subject, body, or attachments to later actions. ## Trigger data | Output | Type | Description | | ------------------------- | --------------- | ------------------------------------------------------ | | **Sender Name** | String | Display name of the sender, when provided. | | **Sender Address** | String | Sender's email address, when provided. | | **Subject** | String | Message subject. | | **Plain Text** | String | Plain-text message body. | | **HTML** | String | HTML message body. | | **Is Reply?** | Boolean | Whether the message has an `In-Reply-To` header. | | **Message ID** | String | RFC 822 message identifier without angle brackets. | | **Plus Path** | String | Text after `+` in the workflow recipient address. | | **Additional Recipients** | List of strings | To, CC, and BCC addresses other than the hook address. | | **Attachments** | List of files | Message attachments with filename and content type. | Some message fields may be `null` when the sending system does not provide them. ## Route with plus addressing Add a suffix before the `@` to carry a lightweight routing value: ```text theme={null} workflow-address+invoices@run.example.com ``` The run receives `invoices` as **Plus Path** while still targeting the same workflow. Additional recipient addresses are deduplicated. The exact address that triggered the workflow is excluded from that list. Treat inbound email as untrusted input. Validate sender addresses, file types, and message content before performing sensitive actions. # Schedule Source: https://learn.workflow.dog/reference/triggers/core/schedule Run a workflow on one or more recurring schedules. The **Schedule** trigger runs a workflow at recurring times. Each schedule has its own recurrence and IANA timezone, and a workflow can have multiple schedules. ## Configure a schedule Choose **Add Schedule**. A new schedule starts at 9:00 AM every day in your browser's current timezone. Set an exact time or an interval, then choose days of the month, days of the week, and months as needed. Common presets include Hourly, Daily, Daily at 9 AM, Weekdays at 9 AM, and Monthly. Keep the detected timezone or choose another one. The schedule follows that zone, including daylight-saving changes. Add more schedules if the workflow should run at several recurring times. Duplicate recurrence-and-timezone pairs are rejected. ## Trigger data | Output | Type | Description | | ------------- | ----------- | ---------------------------------------- | | **Timestamp** | Date & Time | The time at which the event was emitted. | Use **Data from Trigger** to access **Timestamp** inside the workflow. The timestamp records when the scheduled event occurs. Queue load and retries can cause the workflow itself to begin slightly later. A schedule is recurring. Delete schedules you no longer need instead of merely removing their data from the workflow graph. # Label Added to Email Source: https://learn.workflow.dog/reference/triggers/gmail/label-added Start a workflow when Gmail adds a label to a message. The **Label Added to Email** trigger starts a workflow when one or more labels are newly applied to a Gmail message. Watch every label change or filter for one exact label name. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------------------------------- | | **Google Account** | Google account | Yes | Gmail account to watch. | | **Label Filter** | String | No | Exact label name to require. Matching is case-insensitive. | Leave **Label Filter** empty to trigger for any newly added label. A configured filter matches a complete label name, not a partial name. ## Trigger data | Output | Type | Description | | ---------------- | --------------- | ----------------------------------------------------- | | **Message ID** | String | Gmail ID of the changed message. | | **Thread ID** | String | Gmail conversation ID. | | **Added Labels** | List of strings | Names of all labels added in the Gmail history event. | A single trigger run can contain several **Added Labels**. With a filter set, the run still exposes the complete list from that label-change event. ## Example: process manually approved mail Set **Label Filter** to `Approved`, then pass **Message ID** to **Gmail: Get Message by ID**. Use the retrieved message as the input to the rest of the approved-mail workflow. This lets a person approve a message in Gmail before the automation reads its contents or takes action. ## Troubleshooting Filtering compares complete label names while ignoring capitalization. `Approved` does not match `Approved/Priority`. This trigger watches labels being added, not removed. # New Email Source: https://learn.workflow.dog/reference/triggers/gmail/new-email Start a workflow when a new message arrives in a Gmail inbox. The **New Email** trigger starts a workflow when the connected Gmail account receives a new inbox message. It can limit runs to subjects containing specific text and provides parsed message bodies, attachments, and headers. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ------------------------------------------------------------- | | **Google Account** | Google account | Yes | Gmail inbox to watch. | | **Subject Filter** | String | No | Required text within the subject. Matching is case-sensitive. | Leave **Subject Filter** empty to accept every qualifying new inbox message. The trigger only dispatches messages addressed to the watched mailbox. ## Trigger data | Output | Type | Description | | ------------------ | ----------------- | ---------------------------------------------------- | | **Message ID** | String | Gmail ID of the message. | | **Thread ID** | String | Gmail conversation ID. | | **Sender Name** | String | Parsed sender display name, when present. | | **Sender Address** | String | Parsed sender email address, when present. | | **Subject** | String | Message subject. | | **Plain Text** | String | Plain-text MIME content, when present. | | **HTML** | String | HTML MIME content, when present. | | **Is Reply?** | Boolean | Whether the message has an `In-Reply-To` header. | | **Attachments** | List of files | Files downloaded from the message. | | **Headers** | Object of strings | Lowercase email-header names mapped to their values. | Message formats vary. **Plain Text**, **HTML**, sender name, or attachments can be empty when the source message does not contain them. ## Example: triage a support inbox Set **Subject Filter** to `[Support]`, then pass **Plain Text** through **Remove Reply Text** before classifying the message. Use the cleaned text and classification as inputs to **Draft Reply**. Removing quoted conversation history first helps the classifier and draft focus on the customer's newest message. ## Troubleshooting The filter is case-sensitive. Confirm the message arrived in the watched account's Inbox after the trigger was configured and that the subject contains the exact filter text. WorkflowDog-authored mail sent back to the same watched account is excluded from this incoming trigger to avoid self-triggering loops. # Sent Email Source: https://learn.workflow.dog/reference/triggers/gmail/sent-email Start a workflow when the connected Gmail account sends a message. The **Sent Email** trigger starts a workflow for messages sent by the connected Gmail account. Use it to log outbound conversations, synchronize a CRM, or continue a process after a person sends mail. ## Configuration | Field | Type | Required | Description | | -------------------------------- | -------------- | -------- | ---------------------------------------------------------- | | **Google Account** | Google account | Yes | Gmail account whose sent mail is watched. | | **Subject Filter** | String | No | Required subject text. Matching is case-sensitive. | | **Trigger on automated emails?** | Boolean | No | Include messages sent by WorkflowDog. Defaults to `false`. | Enabling **Trigger on automated emails?** can create an infinite loop when the resulting workflow sends another Gmail message that matches this trigger. Add a reliable filter or guard before enabling it. ## Trigger data | Output | Type | Description | | ------------------ | ----------------- | ------------------------------------------------ | | **Message ID** | String | Gmail ID of the sent message. | | **Thread ID** | String | Gmail conversation ID. | | **Sender Name** | String | Parsed sender display name, when present. | | **Sender Address** | String | Parsed sender email address. | | **Subject** | String | Message subject. | | **Plain Text** | String | Plain-text MIME content, when present. | | **HTML** | String | HTML MIME content, when present. | | **Is Reply?** | Boolean | Whether the message has an `In-Reply-To` header. | | **Attachments** | List of files | Files downloaded from the sent message. | | **Headers** | Object of strings | Lowercase header names mapped to their values. | ## Example: log outbound customer mail Keep **Trigger on automated emails?** off, then use the message headers and sender details to find the corresponding customer. Connect the customer lookup to your CRM action and record the sent message as an activity. This captures mail sent by a person without allowing CRM-generated follow-ups to start the workflow again. ## Troubleshooting That is the default safeguard. Enable **Trigger on automated emails?** only after ensuring the workflow cannot trigger itself repeatedly. Matching is case-sensitive and looks for the filter as a substring of the subject. Remove surrounding whitespace and copy the exact capitalization. # Google Form Response Source: https://learn.workflow.dog/reference/triggers/google-forms/form-response Start a workflow when a response is submitted to a Google Form. The **Google Form Response** trigger starts a workflow for each newly received response to one form. It exposes the respondent, question IDs, text answers, and quiz score without requiring a polling action in the workflow. ## Set up the trigger Select an account with permission to read responses for the form. Open the form in Google Forms and copy its editing URL. Paste the URL into **Form URL**, then save the trigger configuration. Test with a response submitted after the trigger has been configured. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ------------------------------------------------------ | | **Google Account** | Google account | Yes | Account used to watch the form and read its responses. | | **Form URL** | URL | Yes | Editing URL of the Google Form to watch. | When the trigger is initialized, it records the current time and watches for later responses. It does not intentionally replay existing form submissions. Each Google notification fetches at most 100 new responses. A burst larger than that between notifications is not paginated by the current trigger. ## Trigger data | Output | Type | Description | | -------------------- | --------------- | ---------------------------------------------------- | | **Response ID** | String | Google's identifier for the response. | | **Respondent Email** | String | Respondent email address when the form collects one. | | **Answers** | List of answers | One item per answered question. | | **Total Score** | Number | Total score when the form is configured as a quiz. | Each **Answers** item contains: | Field | Type | Description | | ---------------- | --------------- | -------------------------------------------------------------- | | **Question ID** | String | Google's identifier for the question. | | **Text Answers** | List of strings | Submitted text values. A question can contain multiple values. | The trigger currently exposes text answers. File-upload answer details are not included in the node output. ## Example: route intake responses Pass **Answers** to a repeat action and inspect **Question ID** for each item. Route recognized question IDs to the fields they represent, then create or update the corresponding record. Question IDs are stable identifiers and are safer for routing than relying on question order. ## Troubleshooting Confirm the URL is the form's editing URL, the connected account can read responses, and the response was submitted after the trigger was configured. Google only supplies an email when the form is configured to collect one. Checkbox-style or other multi-answer questions can produce more than one value. Process **Text Answers** as a list. # Form Submission Source: https://learn.workflow.dog/reference/triggers/http/form Start a workflow when an HTML form is submitted. The **Form Submission** trigger gives a workflow a public form endpoint. It accepts `POST` form submissions—including uploaded files—and can optionally serve an HTML form from the same URL on `GET`. ## Configure the form Open the trigger configuration and copy its unique endpoint. Set the form's `action` to the trigger URL and its method to `POST`. Turn on **HTML Response** and enter HTML content. A `GET` request then returns that HTML instead of running the workflow. Use an HTTP response action to return a confirmation page, file, redirect, or status after a `POST`. ```html theme={null}
``` ## Configuration | Setting | Type | Default | Description | | ----------------- | ------- | ------- | ------------------------------------------------ | | **HTML Response** | Boolean | Off | Serve the configured HTML for `GET` requests. | | **HTML Content** | String | Empty | The page returned when HTML Response is enabled. | ## Trigger outputs | Output | Type | Description | | ---------- | ----------------- | ------------------------------------------------------------------ | | **Path** | String | The endpoint path. | | **Method** | `GET` or `POST` | The request method. | | **Fields** | Object | Submitted fields and uploaded files. Repeated values become lists. | | **Query** | Object of strings | Query parameters supplied with a `POST`. | When **HTML Response** is off, a `GET` request runs the workflow and exposes its query parameters through **Fields**. # URL Source: https://learn.workflow.dog/reference/triggers/http/url Start a workflow from a general-purpose HTTP endpoint. The **URL** trigger gives the workflow a unique endpoint that accepts common HTTP methods and arbitrary text or binary request bodies. Use it when you need more control than the JSON-only **Webhook** trigger provides. ## Set up the endpoint Copy the endpoint shown in the trigger configuration. Call the URL with `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. Add query parameters and headers as needed. End the workflow with an HTTP response action such as **Respond Text**, **Respond JSON**, **Respond File**, or **Redirect**. ## Trigger outputs | Output | Type | Description | | ----------- | ----------------- | --------------------------------------------------------------------------------------- | | **Path** | String | The path that was called. | | **Method** | Enum | `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. | | **Headers** | Object | Request headers with lowercase names. Cookie and forwarded-address headers are omitted. | | **Query** | Object of strings | Query parameters. | | **Body** | String | Text request content, or a base64 string for binary content. | Requests are limited to 10 MB. If no response action runs, the caller receives a generic workflow-status response rather than a custom body. # Webhook Source: https://learn.workflow.dog/reference/triggers/http/webhook Start a workflow from a POST request containing JSON. The **Webhook** trigger exposes a unique endpoint for services that send JSON webhooks. It accepts only `POST` requests and parses the request body as JSON. ## Set up a webhook Open the trigger and copy its unique URL. Use the URL as the service's webhook or callback destination. Select properties from **Data**, then finish the workflow with **Respond Text**, **Respond JSON**, **Respond Status**, or **Redirect** if the sender expects a response. ## Trigger outputs | Output | Type | Description | | ----------- | ----------------- | --------------------------------------------------------------------------------------- | | **Data** | Any | The parsed JSON request body. | | **Path** | String | The endpoint path that was called. | | **Query** | Object of strings | Query parameters. | | **Headers** | Object | Request headers with lowercase names. Cookie and forwarded-address headers are omitted. | JSON requests are limited to 100 MB. Other methods return `405 Method Not Allowed`. Use the **URL** trigger instead when the sender uses another method, sends plain text or binary data, or requires access to the request method. # Triggers Source: https://learn.workflow.dog/reference/triggers/index Reference documentation for every trigger available in WorkflowDog. A trigger is the event that starts a workflow. It can react to an incoming HTTP request, a schedule, a new message or booking, a form submission, or another service event. This reference documents every trigger currently available in the editor. Browse by package in the navigation or search for the trigger by its node-picker name. ## How trigger outputs work When an event arrives, the trigger turns its data into outputs. Those outputs are the starting values for the rest of the workflow—for example, an incoming email's sender, an HTTP request body, or a scheduled execution time. Some triggers change their outputs when you select a different event type or configuration. Make that choice before connecting the trigger to later actions. ## Test before enabling Select the account, event type, schedule, route, or other source settings documented for the trigger. Send a test request or create a real service event so the workflow receives the same shape of data it will see in production. Confirm optional properties, files, and lists before relying on them in downstream actions. Once the trigger and downstream actions behave as expected, enable the workflow so it can receive future events. External triggers depend on the connected account and the service's delivery behavior. Removing permissions, deleting a webhook or watch, or disabling the workflow can stop new events from arriving. Need a step that runs after a trigger? Browse the complete [Actions reference](/reference/actions). # New Email Source: https://learn.workflow.dog/reference/triggers/outlook/new-email Start a workflow when a message arrives in an Outlook inbox. The **New Email** trigger starts a workflow when Microsoft creates a message in the connected account's Inbox. It can filter by subject and downloads non-inline attachments for the run. ## Configuration | Field | Type | Required | Description | | --------------------- | ----------------- | -------- | -------------------------------------------------- | | **Microsoft Account** | Microsoft account | Yes | Outlook Inbox to watch. | | **Subject Filter** | String | No | Required subject text. Matching is case-sensitive. | Leave **Subject Filter** empty to accept every qualifying new Inbox message. ## Trigger data | Output | Type | Description | | ------------------- | ------------- | ------------------------------------------ | | **Message ID** | String | Microsoft message ID. | | **Conversation ID** | String | Outlook conversation ID. | | **Sender Name** | String | Sender display name, when present. | | **Sender Address** | String | Sender email address, when present. | | **Subject** | String | Message subject. | | **Plain Text** | String | Message body requested as text. | | **HTML** | String | Message body requested as HTML. | | **Date/Time** | Date | Time the message was received. | | **Attachments** | List of files | Downloaded non-inline message attachments. | Messages sent back to the same account by WorkflowDog are excluded when they carry WorkflowDog's automation header. This prevents common self-triggering loops. ## Example: archive incoming documents Set **Subject Filter** to `Statement` to limit runs to statement emails. Connect **Attachments** to a repeat action, then store each file during the loop. The workflow creates one run per matching email and processes every non-inline attachment in that message. ## Troubleshooting Matching is case-sensitive and searches for the configured text anywhere in the subject. The trigger's attachment list is intended for file attachments and does not include inline attachments. # New TidyCal Booking Source: https://learn.workflow.dog/reference/triggers/tidycal/new-booking Start a workflow when a new TidyCal booking appears. The **New TidyCal Booking** trigger monitors one connected TidyCal account and starts the workflow for newly created, non-cancelled bookings. ## Set up the trigger Select the **TidyCal Account** to monitor, then enable the workflow. The current implementation monitors all booking types in that account. WorkflowDog polls TidyCal for new bookings. The workflow may start shortly after the booking is created rather than at the exact creation instant. ## Trigger outputs | Output | Type | Description | | ----------------------------------------------------- | --------------- | --------------------------------- | | **Booking ID** | Number | The new booking's ID. | | **Booking Type** | String | The booking type URL slug. | | **Starts At** / **Ends At** | Date | Appointment boundaries. | | **Timezone** | String | The booking timezone. | | **Meeting URL** | String | The meeting link when present. | | **Contact ID** / **Contact Name** / **Contact Email** | Mixed | Contact details. | | **Questions** | List of objects | Custom question and answer pairs. | Cancelled bookings are ignored by the polling source. # Card Archived Source: https://learn.workflow.dog/reference/triggers/trello/card-archived Start a workflow when an open Trello card is archived. The **Card Archived** trigger starts a workflow when a card's closed state changes from open to archived on the selected board. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------- | | **Trello Account** | Trello account | Yes | Account that can access the board. | | **Board ID** | String | Yes | The Trello board to watch. | ## Trigger data | Output | Type | Description | | ----------------------------------------------- | ------ | ---------------------------------------------- | | **Action ID** / **Action Type** | String | Trello action identifier and type. | | **Occurred At** | Date | When the card was archived. | | **Card ID** / **Card Name** | String | The archived card. | | **Board ID** / **Board Name** | String | The board, when supplied by Trello. | | **List ID** / **List Name** | String | The card's list, when supplied by Trello. | | **Previous List ID** / **Previous List Name** | String | Empty unless Trello supplies move data. | | **Comment Text** | String | Empty for archive events. | | **Member Creator ID** / **Name** / **Username** | String | The action's creator, when supplied by Trello. | Reopening a card does not match this trigger. Archiving also matches **Card Updated** when that trigger watches the same board. # Card Commented Source: https://learn.workflow.dog/reference/triggers/trello/card-commented Start a workflow when a Trello card receives a comment. The **Card Commented** trigger starts a workflow when someone comments on a card on the selected Trello board. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------- | | **Trello Account** | Trello account | Yes | Account that can access the board. | | **Board ID** | String | Yes | The Trello board to watch. | ## Trigger data | Output | Type | Description | | ----------------------------------------------- | ------ | ----------------------------------------------- | | **Action ID** / **Action Type** | String | Trello action identifier and type. | | **Occurred At** | Date | When the comment was added. | | **Card ID** / **Card Name** | String | The commented card. | | **Board ID** / **Board Name** | String | The board, when supplied by Trello. | | **List ID** / **List Name** | String | The card's list, when supplied by Trello. | | **Previous List ID** / **Previous List Name** | String | Empty for comment events. | | **Comment Text** | String | The text of the new comment. | | **Member Creator ID** / **Name** / **Username** | String | The comment's creator, when supplied by Trello. | This trigger responds to newly added comments, not edits or deletions of existing comments. # Card Created Source: https://learn.workflow.dog/reference/triggers/trello/card-created Start a workflow when a card is created on a Trello board. The **Card Created** trigger starts a workflow when Trello creates, copies, emails, or converts a checklist item into a card on the selected board. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------- | | **Trello Account** | Trello account | Yes | Account that can access the board. | | **Board ID** | String | Yes | The Trello board to watch. | ## Trigger data | Output | Type | Description | | ----------------------------------------------- | ------ | ---------------------------------------------- | | **Action ID** / **Action Type** | String | Trello action identifier and action type. | | **Occurred At** | Date | When Trello recorded the action. | | **Card ID** / **Card Name** | String | The created card. | | **Board ID** / **Board Name** | String | The board, when supplied by Trello. | | **List ID** / **List Name** | String | The card's list, when supplied by Trello. | | **Previous List ID** / **Previous List Name** | String | Empty for normal create events. | | **Comment Text** | String | Empty for normal create events. | | **Member Creator ID** / **Name** / **Username** | String | The action's creator, when supplied by Trello. | The trigger begins watching after its Trello account and board are saved. It does not replay cards that already exist. # Card Moved Source: https://learn.workflow.dog/reference/triggers/trello/card-moved Start a workflow when a Trello card moves between lists. The **Card Moved** trigger starts a workflow when a card moves from one list to another on the selected board. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------- | | **Trello Account** | Trello account | Yes | Account that can access the board. | | **Board ID** | String | Yes | The Trello board to watch. | ## Trigger data | Output | Type | Description | | ----------------------------------------------- | ------ | ---------------------------------------------- | | **Action ID** / **Action Type** | String | Trello action identifier and type. | | **Occurred At** | Date | When the move occurred. | | **Card ID** / **Card Name** | String | The moved card. | | **Board ID** / **Board Name** | String | The board containing the card. | | **List ID** / **List Name** | String | The destination list. | | **Previous List ID** / **Previous List Name** | String | The source list. | | **Comment Text** | String | Empty for move events. | | **Member Creator ID** / **Name** / **Username** | String | The person who moved the card, when available. | A list move also matches **Card Updated**. Avoid enabling both triggers for the same downstream work unless duplicate workflow runs are intentional. # Card Updated Source: https://learn.workflow.dog/reference/triggers/trello/card-updated Start a workflow when a Trello card changes. The **Card Updated** trigger starts a workflow for Trello `updateCard` actions, including field edits, list moves, archiving, and reopening. ## Configuration | Field | Type | Required | Description | | ------------------ | -------------- | -------- | ---------------------------------- | | **Trello Account** | Trello account | Yes | Account that can access the board. | | **Board ID** | String | Yes | The Trello board to watch. | ## Trigger data | Output | Type | Description | | ----------------------------------------------- | ------ | ------------------------------------------------ | | **Action ID** / **Action Type** | String | Trello action identifier and type. | | **Occurred At** | Date | When the update occurred. | | **Card ID** / **Card Name** | String | The affected card. | | **Board ID** / **Board Name** | String | The board, when supplied by Trello. | | **List ID** / **List Name** | String | The current or destination list, when available. | | **Previous List ID** / **Previous List Name** | String | The source list for a move; otherwise empty. | | **Comment Text** | String | Empty for update events. | | **Member Creator ID** / **Name** / **Username** | String | The action's creator, when supplied by Trello. | This broad trigger includes the events selected by **Card Moved** and **Card Archived**. Enabling overlapping triggers can start more than one run for the same Trello action.