Skip to Content
API ReferenceAutomations API

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/:nodeId

Authentication: 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

HeaderRequiredDescription
Content-TypeYesMust be application/json
X-Webhook-SecretNoIf 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

StatusDescription
400Invalid JSON body
401Secret token mismatch
404Tenant or node not found
422Node 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

ColumnTypeDescription
iduuidPrimary key
tenant_iduuidTenant that owns the automation
sequence_iduuidThe automation (sequence with flow_type = 'automation')
trigger_node_idtextID of the node that initiated the run
trigger_payloadjsonbThe full payload received from the trigger
statustextCurrent run status (see below)
node_logjsonbPer-node execution log (see below)
errortextError message if the run failed
started_attimestamptzWhen execution began
completed_attimestamptzWhen execution finished (null if still running)
created_attimestamptzRecord creation timestamp

Status Values

StatusDescription
runningAutomation is currently executing nodes
completedAll nodes executed successfully
failedExecution stopped due to an error
cancelledRun 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.

FieldTypeRequiredDescription
webhookPathstringAutoThe generated webhook URL path. Read-only, assigned on node creation.
secretTokenstringNoIf 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.

FieldTypeRequiredDescription
scheduleTypestringYesOne of: daily, weekly, monthly, custom
timestringYesTime in HH:mm format (24-hour)
timezonestringYesIANA timezone (e.g. America/New_York)
daysOfWeeknumber[]For weeklyDays of the week (0 = Sunday, 6 = Saturday)
customCronstringFor customStandard 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).

FieldTypeRequiredDescription
eventTypestringYesCRM event type (e.g. contact.created, opportunity.stage_changed)
filterFieldstringNoOptional field to filter on (e.g. stage, source)
filterValuestringNoValue 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.

FieldTypeRequiredDescription
methodstringYesHTTP method: GET, POST, PUT, PATCH, DELETE
urlstringYesTarget URL. Supports template variables.
headersobjectNoKey-value pairs for request headers
bodyTemplatestringNoJSON 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.

FieldTypeRequiredDescription
channelstringYesSlack channel name (e.g. #sales) or channel ID
messageTemplatestringYesMessage 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).

FieldTypeRequiredDescription
entityTypestringYesOne of: contact, opportunity, account
fieldMappingsobjectYesKey-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.

FieldTypeRequiredDescription
entityTypestringYesOne of: contact, opportunity, account, note, task
fieldMappingsobjectYesKey-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.

FieldTypeRequiredDescription
transformTypestringYesOne of: map, filter, merge
mappingsobjectYesTransformation 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 to jane@acme.com
  • {{trigger.amount}} resolves to 499

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

  1. Variables are resolved at execution time, just before each node runs.
  2. If a referenced field does not exist, the variable resolves to an empty string.
  3. All values are coerced to strings when inserted into templates.
  4. Trigger data is available to every node in the flow.
  5. Node outputs are only available to downstream nodes (nodes that execute after the source node).

Last updated on