Action Steps
Execute integration actions in workflows
Action Steps
Action steps execute operations on external services through connectors. They are the primary way to interact with integrated systems like Stripe, Salesforce, HubSpot, QuickBooks, and more.
Configuration
{
"id": "create-invoice",
"type": "action",
"name": "Create Stripe Invoice",
"action": "stripe.createInvoice",
"config": {
"customerId": "{{input.customer_id}}",
"items": [
{
"price": "price_xxx",
"quantity": 1
}
]
}
}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique step identifier |
type | string | Yes | Must be "action" |
name | string | Yes | Human-readable name |
action | string | Yes | Action identifier (e.g., stripe.createInvoice) |
config | object | Yes | Action-specific configuration |
retryConfig | object | No | Retry configuration |
errorHandling | object | No | Error handling strategy |
timeoutMs | number | No | Timeout in milliseconds |
Action Format
Actions follow the pattern {connector}.{actionName}:
stripe.createInvoice
salesforce.updateOpportunity
hubspot.createContact
quickbooks.listCustomers
slack.sendMessageAvailable Connectors
| Connector | Description | Example Actions |
|---|---|---|
stripe | Payment processing | createInvoice, getCustomer, createSubscription |
salesforce | CRM operations | getAccount, updateOpportunity, query |
hubspot | Marketing/CRM | createContact, getDeal, searchContacts |
quickbooks | Accounting | createInvoice, getCustomer, createPayment |
pandadoc | Document signing | createDocument, sendDocument, getStatus |
netsuite | ERP operations | createCustomer, createInvoice, suiteql |
slack | Messaging | sendMessage, openModal, addReaction |
email | Email sending | send, send_template, schedule |
See Integrations for complete action documentation per connector.
Template Variables
Use template syntax to reference input and previous step outputs:
{
"id": "update-contact",
"type": "action",
"action": "hubspot.updateContact",
"config": {
"contactId": "{{steps.lookup.output.id}}",
"properties": {
"company": "{{input.company_name}}",
"lifecyclestage": "customer",
"last_order_date": "{{now}}"
}
}
}Available Template Contexts
| Context | Example | Description |
|---|---|---|
input | {{input.customer_id}} | Workflow trigger input |
steps | {{steps.step-id.output.field}} | Previous step output |
variables | {{variables.taxRate}} | Workflow variables |
env | {{env.API_URL}} | Environment variables |
now | {{now}} | Current ISO timestamp |
Nested Access
{
"config": {
"email": "{{input.customer.contact.email}}",
"amount": "{{steps.calculate.output.totals.grandTotal}}"
}
}Error Handling
Retry Configuration
Configure automatic retries for transient failures:
{
"id": "api-call",
"type": "action",
"action": "stripe.createInvoice",
"config": { ... },
"retryConfig": {
"maxAttempts": 3,
"initialDelayMs": 1000,
"maxDelayMs": 30000,
"backoffMultiplier": 2
}
}| Field | Type | Description |
|---|---|---|
maxAttempts | number | Maximum retry attempts (1-10) |
initialDelayMs | number | Initial delay in ms (min: 100) |
maxDelayMs | number | Maximum delay in ms (min: 1000) |
backoffMultiplier | number | Exponential backoff multiplier (1-10) |
Error Handling Strategy
{
"id": "optional-sync",
"type": "action",
"action": "hubspot.updateContact",
"config": { ... },
"errorHandling": {
"strategy": "continue",
"fallback": {
"synced": false,
"error": "Sync failed"
}
}
}| Strategy | Behavior |
|---|---|
fail | Stop workflow, mark run as failed (default) |
continue | Log error, continue with fallback output |
retry | Retry with retryConfig settings |
Timeout
{
"id": "slow-api",
"type": "action",
"action": "netsuite.suiteql",
"config": { ... },
"timeoutMs": 60000
}Output
Action outputs are stored and available to subsequent steps:
// Access in later steps
{{steps.create-invoice.output.id}}
{{steps.create-invoice.output.number}}
{{steps.create-invoice.output.status}}
{{steps.create-invoice.output.amount_due}}Checking Output Existence
{
"id": "check-result",
"type": "condition",
"config": {
"conditions": {
"left": "{{steps.create-invoice.output.id}}",
"operator": "exists"
},
"then": ["send-notification"],
"else": ["handle-error"]
}
}Common Patterns
Create Then Update
{
"steps": [
{
"id": "create-customer",
"type": "action",
"action": "stripe.createCustomer",
"config": {
"email": "{{input.email}}",
"name": "{{input.name}}"
}
},
{
"id": "create-invoice",
"type": "action",
"action": "stripe.createInvoice",
"config": {
"customer": "{{steps.create-customer.output.id}}",
"auto_advance": true
}
}
]
}Conditional Action
{
"steps": [
{
"id": "check-exists",
"type": "action",
"action": "hubspot.searchContacts",
"config": {
"filterGroups": [{
"filters": [{
"propertyName": "email",
"operator": "EQ",
"value": "{{input.email}}"
}]
}]
}
},
{
"id": "route-action",
"type": "condition",
"config": {
"conditions": {
"left": "{{steps.check-exists.output.total}}",
"operator": "gt",
"right": "0"
},
"then": ["update-contact"],
"else": ["create-contact"]
}
}
]
}With Fallback
{
"id": "sync-to-crm",
"type": "action",
"action": "salesforce.updateAccount",
"config": {
"id": "{{input.sf_account_id}}",
"fields": { "Website": "{{input.website}}" }
},
"errorHandling": {
"strategy": "continue",
"fallback": {
"synced": false,
"syncError": "Failed to update Salesforce"
}
}
}Connector-Specific Examples
Stripe
{
"id": "create-payment",
"type": "action",
"action": "stripe.createPaymentIntent",
"config": {
"amount": "{{input.amount}}",
"currency": "usd",
"customer": "{{input.stripe_customer_id}}",
"metadata": {
"order_id": "{{input.order_id}}"
}
}
}Salesforce
{
"id": "query-accounts",
"type": "action",
"action": "salesforce.query",
"config": {
"soql": "SELECT Id, Name, Website FROM Account WHERE Type = 'Customer' LIMIT 100"
}
}Slack
{
"id": "notify-team",
"type": "action",
"action": "slack.sendMessage",
"config": {
"channel": "#sales-notifications",
"text": "New deal closed: {{input.deal_name}} for ${{input.amount}}"
}
}Troubleshooting
Action Not Found
{
"error": {
"code": "ACTION_NOT_FOUND",
"message": "Action 'stripe.unknownAction' not found"
}
}Verify the action name matches the connector's available actions.
Connection Required
{
"error": {
"code": "CONNECTION_REQUIRED",
"message": "No active connection found for provider 'salesforce'"
}
}Ensure you have an active OAuth connection for the connector.
Rate Limited
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded for provider"
}
}Add retry configuration with exponential backoff.