Workflows
Build visual automation workflows using a drag-and-drop DAG (directed acyclic graph) editor. Workflows connect trigger nodes to action nodes, enabling complex email operations without code.
Create a workflow
/v1/workflowsCreate a new workflow in draft status.
Request body
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Workflow name. |
description | string | Optional description of what the workflow does. |
{
"id": "wf_abc123",
"name": "Bounce Handler",
"description": "Suppress permanently bounced emails and notify Slack",
"status": "draft",
"nodes": [],
"connections": [],
"created_at": "2026-03-21T00:00:00Z"
}List workflows
/v1/workflowsList all workflows for the current team.
Get a workflow
/v1/workflows/{id}Retrieve a workflow with its full node and connection graph.
Update a workflow
/v1/workflows/{id}Update workflow name, description, nodes, or connections.
Delete a workflow
/v1/workflows/{id}Delete a workflow. Active workflows must be deactivated first.
Activate or deactivate
/v1/workflows/{id}/activateToggle a workflow between active and inactive. Active workflows respond to their trigger events.
Manually trigger execution
/v1/workflows/{id}/executeManually trigger a workflow execution. Optionally pass trigger data in the request body.
List execution history
/v1/workflows/{id}/executionsList all executions for a workflow, with status and duration.
Get execution detail
/v1/workflows/{id}/executions/{exec_id}Get detailed execution results including per-node status, input/output data, and errors.
Workflow status
| Parameter | Type | Description |
|---|---|---|
draft | status | Workflow is being designed. Does not respond to triggers. |
active | status | Workflow is live and will execute when triggered. |
inactive | status | Workflow is paused. Will not respond to triggers until reactivated. |
Trigger nodes
Every workflow starts with a trigger node that defines when the workflow runs:
| Parameter | Type | Description |
|---|---|---|
email_event | trigger | Fires on email events: delivered, bounced, opened, clicked, complained. |
webhook_received | trigger | Fires when an external HTTP POST hits the workflow unique URL. |
schedule | trigger | Fires on a recurring cron schedule (e.g. daily digest, weekly report). |
manual | trigger | Triggered manually from the dashboard or via the API. |
contact_event | trigger | Fires when a contact is created, updated, unsubscribed, or added to a segment. |
broadcast_complete | trigger | Fires when a broadcast finishes sending. |
Action nodes
Action nodes define the steps in your workflow:
| Parameter | Type | Description |
|---|---|---|
send_email | action | Send a transactional email via the Txtly API. |
send_broadcast | action | Trigger a broadcast to a segment. |
http_request | action | Make an external HTTP call (any method, headers, body). |
delay | action | Wait for a specified duration before continuing. |
condition | action | Branch based on a condition. Outputs: true and false paths. |
filter | action | Continue only if a condition is met, otherwise stop this branch. |
add_segment | action | Add a contact to a segment. |
remove_segment | action | Remove a contact from a segment. |
update_contact | action | Modify contact properties. |
suppress_email | action | Add an email address to the suppression list. |
slack_notification | action | Send a message to a Slack channel via webhook. |
discord_notification | action | Send a message to a Discord webhook. |
transform_data | action | Map and transform data between nodes using JSONPath or templates. |
code | action | Run custom C# code for advanced logic. |
Execution engine
Workflows are executed as a DAG using topological sort to determine execution order. Independent branches run in parallel, while nodes within a branch run sequentially. Each node's output is available to downstream nodes as input data. Execution state is persisted at each step for observability and resume capability.
Example: Bounce Handler
[Email Bounced] --> [Condition: bounce_type == 'permanent'?]
--> true: [Suppress Email] --> [Slack: "Permanent bounce: {{email}}"]
--> false: [Delay: 1 hour] --> [Send Email: retry original]