--- title: Workflows description: Automate email sequences with triggers and conditions --- ## What are workflows Workflows automate email sequences based on user behavior. Build onboarding drips, re-engagement campaigns, and event-triggered emails—all without writing code. A workflow consists of: - **Trigger** — What starts the workflow (event, segment entry, schedule) - **Steps** — Actions like sending emails, waiting, or checking conditions - **Transitions** — Connections between steps that define the flow ## Common use cases ### Welcome series Send a 3-email onboarding sequence when users sign up: 1. User triggers `signed_up` event 2. Send welcome email immediately 3. Wait 1 day 4. Send getting started guide 5. Wait 2 days 6. Send feature tips ### Abandoned cart recovery Re-engage users who add items but don't purchase: 1. User triggers `cart_abandoned` event 2. Wait 1 hour 3. Send reminder email with cart contents 4. Wait for `purchase` event (timeout: 24 hours) 5. If purchased → Exit workflow 6. If timeout → Send discount offer ### Trial expiration Notify users before trial ends and encourage upgrade: 1. Trigger daily at 9am 2. Check if trial expires in 3 days 3. If yes → Send upgrade reminder 4. Wait for `subscription_created` event (timeout: 3 days) 5. If subscribed → Send thank you email 6. If timeout → Send last chance offer ### Re-engagement campaign Win back inactive users: 1. Contact enters "Inactive Users" segment 2. Send "We miss you" email 3. Wait for `login` event (timeout: 7 days) 4. If logged in → Exit workflow 5. If timeout → Send special offer ## Creating workflows ### In the dashboard 1. Go to **Workflows** 2. Click **Create Workflow** 3. Name your workflow 4. Choose trigger type 5. Add steps using visual builder 6. Connect steps with transitions 7. Activate workflow ### Via API ```bash curl -X POST {{API_URL}}/workflows \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Welcome Series", "eventName": "signed_up", "enabled": true }' ``` Then add steps and transitions through the dashboard or API. ## Trigger types ### Event trigger Starts when a specific event is tracked: ```json { "triggerType": "EVENT", "triggerConfig": { "eventName": "signed_up" } } ``` Track the event with `/v1/track` to start the workflow. ### Segment entry Starts when contact joins a segment: ```json { "triggerType": "SEGMENT_ENTRY", "triggerConfig": { "segmentId": "premium-users" } } ``` Requires segment to have `trackMembership: true`. ### Segment exit Starts when contact leaves a segment: ```json { "triggerType": "SEGMENT_EXIT", "triggerConfig": { "segmentId": "trial-users" } } ``` ### Schedule Runs on a cron schedule: ```json { "triggerType": "SCHEDULE", "triggerConfig": { "schedule": "0 9 * * *" } } ``` Evaluates all contacts—use conditions to filter who continues. ## Workflow steps ### Send Email Send a template to the contact: ```json { "type": "SEND_EMAIL", "config": { "templateId": "welcome-template" } } ``` ### Delay Wait before continuing: ```json { "type": "DELAY", "config": { "duration": 86400, "unit": "seconds" } } ``` Common durations: - 1 hour: `3600` - 1 day: `86400` - 1 week: `604800` ### Wait for Event Pause until an event occurs or timeout: ```json { "type": "WAIT_FOR_EVENT", "config": { "eventName": "purchase", "timeout": 604800 } } ``` Create two transitions: one for "success" (event occurred) and one for "timeout". ### Condition Branch based on contact data: ```json { "type": "CONDITION", "config": { "field": "data.plan", "operator": "equals", "value": "premium" } } ``` Create two transitions: "true" and "false". ### Update Contact Modify contact fields: ```json { "type": "UPDATE_CONTACT", "config": { "data": { "onboardingCompleted": true, "completedAt": "{{now}}" } } } ``` ### Webhook Call an external API: ```json { "type": "WEBHOOK", "config": { "url": "https://api.example.com/webhook", "method": "POST", "body": { "email": "{{email}}", "event": "workflow_completed" } } } ``` ### Exit End the workflow: ```json { "type": "EXIT" } ``` ## Re-entry behavior Control whether contacts can enter a workflow multiple times: ### Prevent re-entry (default) **allowReentry: false** - Contact can only enter once, ever - Subsequent triggers are ignored - Use for one-time journeys **Best for:** - User onboarding sequences - Welcome series - Trial expiration flows - One-time educational content **Example:** ```json { "name": "Onboarding Series", "eventName": "user_signed_up", "allowReentry": false, "enabled": true } ``` Even if the `user_signed_up` event fires multiple times for the same contact, they'll only enter once. ### Allow re-entry **allowReentry: true** - Contact can enter multiple times - Each trigger starts a new execution - Multiple executions can run simultaneously **Best for:** - Recurring events (weekly newsletters, monthly reports) - Behavior-triggered campaigns (cart abandonment, content engagement) - Event-specific sequences (order confirmations, webinar reminders) **Example:** ```json { "name": "Cart Abandoned Reminder", "eventName": "cart_abandoned", "allowReentry": true, "enabled": true } ``` User abandons cart multiple times → Each triggers a new workflow execution. ## Execution context Pass event-specific data when workflows are triggered automatically. ### What is context? Context is temporary data passed with a workflow execution that's available in templates but not saved to the contact record. **Contact data vs Context:** - **Contact data** — Persistent, saved to contact, used for segmentation - **Execution context** — Temporary, specific to this workflow run, not saved ### Using context in templates Context data is available in workflow email templates alongside contact data: ```html

Hi {{firstName}}!

Order #{{orderNumber}} confirmed!

Total: ${{orderTotal}}

Tracking: View shipment

``` Where: - `{{firstName}}` comes from contact.data - `{{orderNumber}}`, `{{orderTotal}}`, `{{trackingUrl}}` come from execution context ### Common patterns **Order confirmations:** ```javascript // Event includes order details { event: 'purchase_completed', email: 'user@example.com', data: { // Saved to contact totalPurchases: 5, lifetimeValue: 599 } } // Workflow execution receives context (not saved) context: { orderNumber: 'ORD-12345', orderTotal: 99.99, trackingUrl: 'https://track.example.com/12345', deliveryDate: '2025-12-05' } ``` **Event registrations:** ```javascript context: { eventTitle: 'Email Marketing Workshop', eventDate: '2025-12-10T14:00:00Z', eventUrl: 'https://zoom.us/j/123456', speakerName: 'Jane Doe' } ``` **Cart abandonment:** ```javascript context: { cartTotal: 149.99, cartUrl: 'https://app.example.com/cart/abc123', itemCount: 3, expiresAt: '2025-12-01T10:00:00Z' } ``` ## Workflow execution When a workflow triggers: 1. Contact enters at the trigger step 2. Executes each step in sequence 3. Follows transitions between steps 4. Continues until reaching Exit step 5. Status changes from RUNNING to COMPLETED If contact unsubscribes or is deleted, workflow execution stops immediately. ## Managing workflows ### List workflows ```bash curl -X GET {{API_URL}}/workflows \ -H "Authorization: Bearer sk_your_secret_key" ``` ### Get workflow details ```bash curl -X GET {{API_URL}}/workflows/workflow_id \ -H "Authorization: Bearer sk_your_secret_key" ``` ### Activate/deactivate ```bash curl -X PATCH {{API_URL}}/workflows/workflow_id \ -H "Authorization: Bearer sk_your_secret_key" \ -H "Content-Type: application/json" \ -d '{"enabled": true}' ``` ### View executions ```bash curl -X GET "{{API_URL}}/workflows/workflow_id/executions" \ -H "Authorization: Bearer sk_your_secret_key" ``` ## Best practices **Start simple** — Begin with 2-3 emails before adding complex conditions. **Test with yourself** — Create a test contact and trigger the workflow to verify timing and content. **Monitor execution stats** — Check completion rates to identify where contacts drop off. **Use meaningful names** — Name steps clearly: "Send Welcome Email" not "Step 1". **Set appropriate timeouts** — For "Wait for Event" steps, choose realistic timeouts based on user behavior. **Handle both paths** — Every condition and wait should have both success and failure paths defined. ## Next Steps - [Track events](/guides/events) to trigger workflows - [Create segments](/guides/segments) for segment-based triggers - [Build templates](/guides/templates) to use in workflow emails - [Set up webhooks](/guides/webhooks) for external integrations