Automations API
Automations are event-driven flows built with the Visual Sequence Builder. Unlike sequences (which enroll contacts on a linear path), automations trigger from external events such as webhooks, schedules, or CRM changes, and execute a graph of actions.
Automations use the same canvas infrastructure as visual sequences. Create an automation by setting flow_type: "automation" and builder_mode: "visual" on a sequence. See the Visual Builder API for canvas, node, and edge management.
Webhook Trigger
Trigger an Automation
POST /api/webhooks/automation/:tenantId/:nodeIdAuthentication: Public endpoint. No Bearer token required.
Fires the webhook trigger node on an automation. The request payload is passed through to the automation as trigger data, available via template variables.
Headers
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be application/json |
X-Webhook-Secret | No | If the webhook trigger node has a secretToken configured, this header must match it. Requests with an invalid secret are rejected with 401. |
Request Body
Any valid JSON payload. The fields become available as {{trigger.fieldName}} in downstream nodes.
{
"event": "payment.completed",
"customer_email": "jane@acme.com",
"amount": 499.00,
"plan": "growth"
}Response (200)
{
"received": true,
"runId": "uuid"
}Error Codes
| Status | Description |
|---|---|
| 400 | Invalid JSON body |
| 401 | Secret token mismatch |
| 404 | Tenant or node not found |
| 422 | Node is not a webhook trigger or automation is not active |
Automation Runs
Each time an automation fires, a run record is created in the automation_runs table. Runs track execution status and per-node logs.
Run Schema
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
tenant_id | uuid | Tenant that owns the automation |
sequence_id | uuid | The automation (sequence with flow_type = 'automation') |
trigger_node_id | text | ID of the node that initiated the run |
trigger_payload | jsonb | The full payload received from the trigger |
status | text | Current run status (see below) |
node_log | jsonb | Per-node execution log (see below) |
error | text | Error message if the run failed |
started_at | timestamptz | When execution began |
completed_at | timestamptz | When execution finished (null if still running) |
created_at | timestamptz | Record creation timestamp |
Status Values
| Status | Description |
|---|---|
running | Automation is currently executing nodes |
completed | All nodes executed successfully |
failed | Execution stopped due to an error |
cancelled | Run was manually cancelled |
Node Log Structure
The node_log field is a JSON array recording the result of each node executed during the run:
[
{
"nodeId": "node-1",
"nodeType": "webhook_trigger",
"status": "completed",
"startedAt": "2026-03-28T10:00:00.000Z",
"completedAt": "2026-03-28T10:00:00.050Z",
"output": {
"event": "payment.completed",
"customer_email": "jane@acme.com"
}
},
{
"nodeId": "node-2",
"nodeType": "http_request",
"status": "completed",
"startedAt": "2026-03-28T10:00:00.060Z",
"completedAt": "2026-03-28T10:00:01.200Z",
"output": {
"statusCode": 200,
"body": { "success": true }
}
},
{
"nodeId": "node-3",
"nodeType": "slack_message",
"status": "failed",
"startedAt": "2026-03-28T10:00:01.210Z",
"completedAt": "2026-03-28T10:00:01.500Z",
"error": "Channel #sales not found"
}
]Node Configuration Reference
Each node type has a config object inside data. Below is the schema for every automation node type.
webhook_trigger
Starts an automation when an external system sends an HTTP POST.
| Field | Type | Required | Description |
|---|---|---|---|
webhookPath | string | Auto | The generated webhook URL path. Read-only, assigned on node creation. |
secretToken | string | No | If set, incoming requests must include a matching X-Webhook-Secret header. |
{
"type": "webhook_trigger",
"data": {
"label": "Stripe Payment Webhook",
"config": {
"webhookPath": "/api/webhooks/automation/tenant-uuid/node-uuid",
"secretToken": "whsec_abc123"
}
}
}schedule_trigger
Starts an automation on a recurring schedule.
| Field | Type | Required | Description |
|---|---|---|---|
scheduleType | string | Yes | One of: daily, weekly, monthly, custom |
time | string | Yes | Time in HH:mm format (24-hour) |
timezone | string | Yes | IANA timezone (e.g. America/New_York) |
daysOfWeek | number[] | For weekly | Days of the week (0 = Sunday, 6 = Saturday) |
customCron | string | For custom | Standard cron expression (5 fields) |
{
"type": "schedule_trigger",
"data": {
"label": "Daily 9am Report",
"config": {
"scheduleType": "daily",
"time": "09:00",
"timezone": "America/New_York"
}
}
}crm_event_trigger
Starts an automation when a CRM event occurs (e.g. contact created, opportunity stage changed).
| Field | Type | Required | Description |
|---|---|---|---|
eventType | string | Yes | CRM event type (e.g. contact.created, opportunity.stage_changed) |
filterField | string | No | Optional field to filter on (e.g. stage, source) |
filterValue | string | No | Value the filter field must match |
{
"type": "crm_event_trigger",
"data": {
"label": "New Enterprise Deal",
"config": {
"eventType": "opportunity.created",
"filterField": "deal_size",
"filterValue": "enterprise"
}
}
}http_request
Makes an outbound HTTP request to an external API.
| Field | Type | Required | Description |
|---|---|---|---|
method | string | Yes | HTTP method: GET, POST, PUT, PATCH, DELETE |
url | string | Yes | Target URL. Supports template variables. |
headers | object | No | Key-value pairs for request headers |
bodyTemplate | string | No | JSON body template. Supports template variables. |
{
"type": "http_request",
"data": {
"label": "Enrich Contact via Clearbit",
"config": {
"method": "GET",
"url": "https://api.clearbit.com/v2/people/find?email={{trigger.customer_email}}",
"headers": {
"Authorization": "Bearer sk_clearbit_xxx"
}
}
}
}slack_message
Sends a message to a Slack channel via the connected Slack integration.
| Field | Type | Required | Description |
|---|---|---|---|
channel | string | Yes | Slack channel name (e.g. #sales) or channel ID |
messageTemplate | string | Yes | Message text. Supports template variables and Slack markdown. |
{
"type": "slack_message",
"data": {
"label": "Notify Sales Channel",
"config": {
"channel": "#sales",
"messageTemplate": "New payment from {{trigger.customer_email}} for ${{trigger.amount}} on the {{trigger.plan}} plan."
}
}
}crm_update
Updates an existing CRM record (contact, opportunity, or account).
| Field | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | One of: contact, opportunity, account |
fieldMappings | object | Yes | Key-value pairs mapping CRM fields to values. Supports template variables. |
{
"type": "crm_update",
"data": {
"label": "Tag Contact as Paying",
"config": {
"entityType": "contact",
"fieldMappings": {
"lifecycle_stage": "customer",
"last_payment_amount": "{{trigger.amount}}"
}
}
}
}create_record
Creates a new CRM record.
| Field | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | One of: contact, opportunity, account, note, task |
fieldMappings | object | Yes | Key-value pairs for the new record. Supports template variables. |
{
"type": "create_record",
"data": {
"label": "Create Follow-Up Task",
"config": {
"entityType": "task",
"fieldMappings": {
"title": "Follow up with {{trigger.customer_email}}",
"due_date": "+3d",
"priority": "high"
}
}
}
}data_transform
Transforms data between nodes using mapping rules.
| Field | Type | Required | Description |
|---|---|---|---|
transformType | string | Yes | One of: map, filter, merge |
mappings | object | Yes | Transformation rules. Structure depends on transformType. |
{
"type": "data_transform",
"data": {
"label": "Extract Customer Info",
"config": {
"transformType": "map",
"mappings": {
"email": "{{trigger.customer_email}}",
"revenue": "{{trigger.amount}}",
"tier": "{{trigger.plan}}"
}
}
}
}Template Variables Reference
Automation nodes support template variables to pass data between steps. Variables use double-brace syntax: {{source.field}}.
Trigger Data
Access fields from the trigger payload:
{{trigger.fieldName}}For example, if the webhook receives { "customer_email": "jane@acme.com", "amount": 499 }:
{{trigger.customer_email}}resolves tojane@acme.com{{trigger.amount}}resolves to499
Upstream Node Output
Access the output of a previously executed node by referencing its type and position in the flow:
{{http_request_1.fieldName}}The suffix number corresponds to the execution order of that node type within the run. For example, if your flow has two HTTP request nodes:
{{http_request_1.body.status}}— output from the first HTTP request node{{http_request_2.body.customer.name}}— output from the second HTTP request node
Nested Fields
Use dot notation for nested JSON fields:
{{trigger.customer.address.city}}
{{http_request_1.body.data.id}}Resolution Rules
- Variables are resolved at execution time, just before each node runs.
- If a referenced field does not exist, the variable resolves to an empty string.
- All values are coerced to strings when inserted into templates.
- Trigger data is available to every node in the flow.
- Node outputs are only available to downstream nodes (nodes that execute after the source node).
Related
- Visual Builder API — Canvas, node, and edge management
- Sequences API — Sequence listing and enrollment
- Webhooks API — Outbound webhook subscriptions (different from automation triggers)