Workflow Overview
Core workflow concepts, lifecycle, and execution model
Workflow Overview
Workflows are the core building blocks of the Workflows API. This guide explains the fundamental concepts you need to understand when building automated processes.
What is a Workflow?
A workflow is a declarative automation that defines:
- When to run (the trigger)
- What to do (the steps)
- How to handle data (variables and templates)
Workflows enable you to:
- Connect systems - Integrate Stripe, Salesforce, HubSpot, QuickBooks, and more
- Transform data - Map and reshape data between different formats
- Make decisions - Branch logic based on conditions
- Wait for events - Pause for human approval or external events
- Handle errors - Automatic retries with configurable strategies
graph LR
A[Trigger] --> B[Step 1]
B --> C[Step 2]
C --> D{Condition}
D -->|Yes| E[Step 3a]
D -->|No| F[Step 3b]
E --> G[Output]
F --> GWorkflow Lifecycle
Every workflow progresses through a defined set of states:
stateDiagram-v2
[*] --> draft: Create
draft --> active: Activate
active --> paused: Pause
paused --> active: Resume
active --> archived: Archive
paused --> archived: Archive
draft --> archived: Archive| State | Description | Can Execute? | Can Edit? |
|---|---|---|---|
draft | Initial state after creation | No | Yes |
active | Ready to receive triggers and execute | Yes | Yes (creates new version) |
paused | Temporarily disabled | No | Yes |
archived | Soft deleted | No | No |
State Transitions
curl -X POST http://localhost:3000/api/v1/workflows/{id}/activate \
-H "x-api-key: YOUR_API_KEY"curl -X POST http://localhost:3000/api/v1/workflows/{id}/pause \
-H "x-api-key: YOUR_API_KEY"curl -X POST http://localhost:3000/api/v1/workflows/{id}/resume \
-H "x-api-key: YOUR_API_KEY"curl -X DELETE http://localhost:3000/api/v1/workflows/{id} \
-H "x-api-key: YOUR_API_KEY"Workflow Structure
A workflow is defined as a JSON object with these key components:
{
"name": "Invoice on Deal Close",
"description": "Create a QuickBooks invoice when a Salesforce deal is won",
// 1. TRIGGER - When does this workflow run?
"trigger": {
"type": "webhook",
"provider": "salesforce",
"events": ["opportunity.closed_won"]
},
// 2. STEPS - What actions does it perform?
"steps": [
{
"id": "transform-data",
"type": "transform",
"name": "Map Deal to Invoice",
"config": {
"mapping": {
"customer_email": "{{input.account.email}}",
"amount": "{{input.opportunity.amount}}",
"description": "{{input.opportunity.name}}"
}
}
},
{
"id": "create-invoice",
"type": "action",
"name": "Create QuickBooks Invoice",
"config": {
"connector": "quickbooks",
"action": "createInvoice",
"params": {
"customerEmail": "{{steps.transform-data.output.customer_email}}",
"amount": "{{steps.transform-data.output.amount}}",
"memo": "{{steps.transform-data.output.description}}"
}
}
}
],
// 3. VARIABLES - Reusable configuration values
"variables": {
"taxRate": 0.0825,
"defaultTerms": "Net 30"
}
}Triggers
Triggers define when a workflow executes. The Workflows API supports multiple trigger types:
| Type | Description | Use Case |
|---|---|---|
webhook | External system sends an event | Stripe payment, custom webhooks |
schedule | Time-based execution | Daily reports, weekly syncs |
api | Manual execution via API | On-demand processing, testing |
salesforce_event | Salesforce Platform Events or CDC | Record changes, custom events |
hubspot_event | HubSpot property changes | Contact/deal updates |
slack_event | Slack Events API | Messages, mentions, reactions |
slack_slash_command | Slack slash commands | /invoice, /approve |
slack_interactive | Slack interactive components | Button clicks, modal submissions |
gmail_event | Gmail Pub/Sub events | New emails, label changes |
Webhook Triggers
Webhook triggers listen for events from external providers:
{
"trigger": {
"type": "webhook",
"provider": "stripe",
"events": ["invoice.paid", "invoice.payment_failed"]
}
}Supported providers: stripe, salesforce, hubspot, quickbooks, pandadoc, netsuite, slack
See Webhook Triggers for provider-specific configuration.
Schedule Triggers
Schedule triggers use cron expressions for time-based execution:
{
"trigger": {
"type": "schedule",
"cron": "0 9 * * MON",
"timezone": "America/New_York"
}
}See Schedule Triggers for cron syntax and examples.
API Triggers
API triggers allow manual workflow execution:
{
"trigger": {
"type": "api"
}
}curl -X POST http://localhost:3000/api/v1/workflows/{id}/run \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"customer_id": "cus_123"}}'Steps
Steps define what a workflow does. Each step executes sequentially (unless using parallel execution).
Step Types
| Type | Description | Example |
|---|---|---|
action | Call an integration | Create Stripe invoice, update Salesforce record |
transform | Map and reshape data | Convert webhook payload to invoice format |
condition | Branch based on logic | If amount > $1000, require approval |
wait | Pause execution | Wait 24 hours, delay before retry |
parallel | Execute steps concurrently | Notify Slack AND send email |
loop | Iterate over a collection | Process each line item |
approval | Human-in-the-loop | Wait for manager approval |
agent | AI-powered processing | Extract invoice data, classify expense |
code | Custom JavaScript | Run sandboxed code for complex logic |
slack | Slack building block | Send message, open modal |
email | Email building block | Send templated email |
gmail | Gmail building block | Read/send Gmail messages |
Step Structure
Every step has this base structure:
{
"id": "unique-step-id",
"type": "action",
"name": "Human-readable name",
"action": "stripe.createInvoice",
"config": {
// Step-specific configuration
},
"retryConfig": {
"maxAttempts": 3,
"initialDelayMs": 1000,
"maxDelayMs": 30000,
"backoffMultiplier": 2
},
"errorHandling": {
"strategy": "fail",
"fallback": {}
},
"timeoutMs": 30000
}See Steps Documentation for detailed configuration of each step type.
Template Variables
Template variables allow dynamic data access throughout your workflow using {{expression}} syntax.
Available Contexts
| Context | Syntax | Description |
|---|---|---|
| Input | {{input.field}} | Trigger payload data |
| Steps | {{steps.stepId.output.field}} | Previous step outputs |
| Variables | {{variables.name}} | Workflow-defined variables |
| Environment | {{env.VAR_NAME}} | Environment variables |
| System | {{now}}, {{runId}} | System-provided values |
Examples
{
"steps": [
{
"id": "send-email",
"type": "action",
"config": {
"connector": "email",
"action": "send",
"params": {
// Access trigger input
"to": "{{input.customer.email}}",
// Access previous step output
"subject": "Invoice #{{steps.create-invoice.output.invoice_number}}",
// Access workflow variables
"cc": "{{variables.financeEmail}}",
// Use expressions
"body": "Amount due: ${{input.amount / 100}}"
}
}
}
]
}Nested Access
Access nested properties using dot notation:
{{input.customer.billing.address.city}}
{{steps.fetch-deal.output.opportunity.account.owner.email}}Conditional Expressions
Use Handlebars-style conditionals in templates:
{{#if input.is_priority}}URGENT: {{/if}}New invoice createdWorkflow Execution
When a workflow executes, it creates a run that tracks the execution state.
sequenceDiagram
participant T as Trigger
participant W as Workflow Engine
participant S1 as Step 1
participant S2 as Step 2
participant DB as Database
T->>W: Event received
W->>DB: Create run (pending)
W->>S1: Execute step
S1-->>W: Output
W->>DB: Update step status
W->>S2: Execute step
S2-->>W: Output
W->>DB: Run completedRun States
| State | Description |
|---|---|
pending | Run created, waiting to start |
running | Currently executing steps |
suspended | Paused for human approval or external event |
completed | All steps finished successfully |
failed | A step failed after all retries |
cancelled | Manually cancelled |
Viewing Run History
# List runs for a workflow
curl "http://localhost:3000/api/v1/workflows/{id}/runs" \
-H "x-api-key: YOUR_API_KEY"
# Get run details
curl "http://localhost:3000/api/v1/runs/{runId}" \
-H "x-api-key: YOUR_API_KEY"Error Handling
The Workflows API provides robust error handling at multiple levels.
Step-Level Retries
Configure automatic retries for transient failures using retryConfig:
{
"id": "call-api",
"type": "action",
"config": { ... },
"retryConfig": {
"maxAttempts": 3,
"initialDelayMs": 1000,
"maxDelayMs": 30000,
"backoffMultiplier": 2
}
}| Option | Type | Description |
|---|---|---|
maxAttempts | number | Maximum retry attempts (1-10) |
initialDelayMs | number | Initial delay in milliseconds (min: 100) |
maxDelayMs | number | Maximum delay between retries (min: 1000) |
backoffMultiplier | number | Multiplier for exponential backoff (1-10) |
Error Strategies
Define how to handle step failures using errorHandling:
{
"id": "optional-step",
"type": "action",
"config": { ... },
"errorHandling": {
"strategy": "continue",
"fallback": {
"defaultValue": "N/A"
}
}
}| Strategy | Behavior |
|---|---|
fail | Stop workflow, mark run as failed (default) |
continue | Log error, continue to next step |
retry | Retry with configured retryConfig settings |
The optional fallback object provides default output values when a step fails with continue strategy.
Timeout Configuration
Prevent steps from hanging indefinitely with timeoutMs:
{
"id": "slow-api",
"type": "action",
"config": { ... },
"timeoutMs": 60000
}Versioning
Workflows support version control to track changes over time.
How Versioning Works
- Create - Initial workflow is version 1
- Update - Each update to an active workflow creates a new version
- Execution - Running workflows complete with their started version
- Rollback - Revert to any previous version
Version API
# List versions
curl "http://localhost:3000/api/v1/workflows/{id}/versions" \
-H "x-api-key: YOUR_API_KEY"
# Get specific version
curl "http://localhost:3000/api/v1/workflows/{id}/versions/3" \
-H "x-api-key: YOUR_API_KEY"
# Rollback to version
curl -X POST "http://localhost:3000/api/v1/workflows/{id}/versions/3/rollback" \
-H "x-api-key: YOUR_API_KEY"Version States
| State | Description |
|---|---|
current | Active version used for new runs |
archived | Previous version, available for rollback |
rollback | Version restored from rollback operation |
Best Practices
Naming Conventions
- Use descriptive workflow names:
Invoice Customer on Deal Close - Use verb-noun step IDs:
transform-payment,send-notification - Include context in descriptions
Idempotency
Design workflows to be safely re-run:
{
"id": "create-or-update",
"type": "action",
"config": {
"connector": "stripe",
"action": "createCustomer",
"params": {
"idempotencyKey": "{{input.deal_id}}"
}
}
}Error Recovery
- Use appropriate retry counts for each integration
- Set reasonable timeouts
- Use
onError: continuefor non-critical steps
Testing
- Start with
draftstatus for development - Use API trigger for manual testing
- Check run history for debugging