Wraps Logo
Guide

Building Workflows

Define automated email and SMS sequences as code using a declarative DSL. Build drip campaigns, onboarding sequences, and re-engagement flows that run on the Wraps Platform.

Defining a Workflow

A workflow is a sequence of steps triggered by an event. Each workflow is defined in a TypeScript file using the defineWorkflow helper and exported as the default export.

TypeScriptwraps/workflows/welcome-sequence.ts
// wraps/workflows/welcome-sequence.tsimport {  defineWorkflow,  sendEmail,  delay,  condition,  exit,  waitForEvent,} from '@wraps.dev/client';export default defineWorkflow({  name: 'Welcome Sequence',  trigger: {    type: 'contact.created',  },  settings: {    maxEnrollments: 1, // Each contact enters once  },  steps: [    sendEmail('welcome', { template: 'welcome-email' }),    delay('wait-1-day', { days: 1 }),    condition('check-activated', {      field: 'contact.hasActivated',      operator: 'equals',      value: true,      branches: {        yes: [exit('already-active')],        no: [          sendEmail('activation-reminder', { template: 'activate' }),          delay('wait-2-days', { days: 2 }),          sendEmail('final-reminder', { template: 'last-chance' }),        ],      },    }),  ],});

Type-safe workflow definitions

All step helpers are fully typed. Your editor provides autocompletion for configuration options, trigger types, and operator values.

Trigger Types

Triggers determine when a contact enters a workflow. Each workflow has exactly one trigger.

TypeDescription
contact.createdWhen a new contact is added
contact.updatedWhen contact fields change
event.receivedWhen a custom event is received
segment.enteredWhen a contact enters a segment
segment.exitedWhen a contact exits a segment
manualManually triggered via API

Step Helpers

Wraps provides 11 step helpers to build your workflow logic. Each helper takes a unique step ID and a configuration object.

1.sendEmail(id, config)

Send an email using a template.

Config: template, from?, fromName?

2.sendSms(id, config)

Send an SMS message.

Config: template?, message?

3.delay(id, duration)

Wait before continuing.

Config: { days?, hours?, minutes? }

4.condition(id, config)

Branch based on a condition.

Config: field, operator, value, branches: { yes: [...], no: [...] }

5.waitForEvent(id, config)

Pause until an event occurs.

Config: eventName, timeout?

6.waitForEmailEngagement(id, config)

Wait for email open or click.

Config: emailStepId, engagementType ('opened' | 'clicked'), timeout?

7.exit(id, config?)

End the workflow.

Config: reason?, markAs? ('completed' | 'cancelled')

8.updateContact(id, config)

Modify contact fields.

Config: updates: [{ field, operation: 'set' | 'increment' | 'append', value }]

9.subscribeTopic(id, config)

Subscribe contact to a topic.

Config: topicId, channel ('email' | 'sms')

10.unsubscribeTopic(id, config)

Unsubscribe contact from a topic.

Config: topicId, channel ('email' | 'sms')

11.webhook(id, config)

Call an external webhook.

Config: url, method? ('POST' default), headers?, body?

Validate & Push

Before deploying, validate your workflow definitions to catch errors like missing templates, invalid step references, or circular dependencies. Then push to the Wraps Platform.

GNU Bashterminal.sh
# Validate workflow definitionswraps email workflows validate# Push to Wraps Platformwraps email workflows push

Validation checks:

  • All referenced templates exist in your templates directory
  • Step IDs are unique within each workflow
  • Condition branches reference valid step IDs
  • waitForEmailEngagement references a valid sendEmail step

Example: Re-engagement Campaign

This workflow targets contacts who have been inactive for 30 days. It sends a win-back email, waits for engagement, and branches based on whether the contact opened it.

TypeScriptwraps/workflows/re-engagement.ts
import {  defineWorkflow,  sendEmail,  delay,  condition,  exit,  waitForEmailEngagement,} from '@wraps.dev/client';export default defineWorkflow({  name: 'Re-engagement Campaign',  trigger: {    type: 'segment.entered',    segmentId: 'inactive-30-days',  },  steps: [    sendEmail('win-back', { template: 'we-miss-you' }),    waitForEmailEngagement('check-opened', {      emailStepId: 'win-back',      engagementType: 'opened',      timeout: { days: 3 },    }),    condition('was-opened', {      field: 'steps.check-opened.engaged',      operator: 'equals',      value: true,      branches: {        yes: [          sendEmail('special-offer', { template: 'comeback-offer' }),          exit('re-engaged'),        ],        no: [          delay('wait-week', { days: 7 }),          sendEmail('final-attempt', { template: 'last-chance' }),          exit('campaign-complete'),        ],      },    }),  ],});

How this workflow runs:

  1. Contact enters the inactive-30-days segment, triggering the workflow
  2. A "we miss you" email is sent immediately
  3. The workflow waits up to 3 days for the contact to open the email
  4. If opened: a special offer email is sent and the workflow ends
  5. If not opened: the workflow waits 7 more days, sends a final attempt, then ends

Next Steps

Templates as Code

Write email templates as React components for use in workflows.

Template Guide
Platform SDK

Full reference for the Wraps client SDK and workflow API.

SDK Reference