Skip to main content

What Are Workflows?

Workflows are automated multi-step call sequences that orchestrate outreach to your leads over time. Unlike agents that handle single interactions, workflows manage entire engagement campaigns with multiple call touchpoints, delays, and conditional logic. Think of workflows as your automated outreach campaigns that can:
  • Execute multi-step sequences - Make multiple calls in a defined order
  • Schedule intelligently - Respect business hours, time zones, and TCPA compliance
  • Adapt to outcomes - Branch based on call results (answered, voicemail, no answer, etc.)
  • Persist over time - Continue sequences over days or weeks
  • Scale outreach - Run hundreds of executions simultaneously

Common Use Cases

Sales Sequences

Multi-touch outreach with calls and voicemails to nurture leads through your sales funnel.

Appointment Reminders

Automated reminder call sequences leading up to appointments.

Lead Nurturing

Long-term engagement campaigns that warm up cold leads with multiple call touchpoints over time.

Re-engagement Campaigns

Win back inactive customers with scheduled follow-up calls.

Workflow Architecture

Workflows vs Executions

Feather uses a two-level architecture:
  • Workflow: The template defining the sequence, schedule, and rules
  • Workflow Execution: An instance running for a specific lead
This separation allows you to:
  • Define once, run for thousands of leads
  • Track individual execution progress
  • Pause/resume/cancel specific executions
  • Monitor performance across all executions

Creating a Workflow

Basic Workflow Structure

const workflow = {
  name: "3-Day Sales Sequence",
  description: "Initial call with two follow-up attempts",
  active: true,
  timezone: "America/New_York",
  definition: {
    steps: [
      {
        type: "CALL",
        order: 1,
        delayInSecs: 0,
        agentId: "agent-123",
        leaveVoicemail: true,
        needsTCPACompliance: true,
        finishOn: ["CALENDLY", "NOT_INTERESTED", "DNC"]
      },
      {
        type: "CALL",
        order: 2,
        delayInSecs: 86400, // 24 hours
        agentId: "agent-123",
        leaveVoicemail: true,
        needsTCPACompliance: true,
        finishOn: ["CALENDLY", "NOT_INTERESTED", "DNC"]
      },
      {
        type: "CALL",
        order: 3,
        delayInSecs: 172800, // 48 hours after step 2
        agentId: "agent-123",
        leaveVoicemail: false,
        needsTCPACompliance: true,
        finishOn: ["CALENDLY", "NOT_INTERESTED", "DNC"]
      }
    ]
  }
};

const response = await fetch('https://prod.featherhq.com/api/v1/workflow', {
  method: 'POST',
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(workflow)
});

Workflow Steps

Call Steps

Call steps execute phone calls using your configured agents:
{
  "type": "CALL",
  "order": 1,
  "delayInSecs": 0,
  "agentId": "agent-123",
  "leaveVoicemail": true,
  "needsTCPACompliance": true,
  "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"],
  "conditions": {
    "field": "previousDisposition",
    "operator": "equals",
    "value": "NO_ANSWER"
  }
}
Key Properties:
  • agentId (required): Which agent handles the call
  • leaveVoicemail: Whether to leave voicemail if detected
  • finishOn: Call dispositions that end the workflow
  • conditions: Optional conditional logic for branching

Step Ordering & Delays

Steps execute in order based on the order field (1-indexed). The delayInSecs determines when each step runs:
  • Step 1: Runs immediately when execution starts
  • Step 2+: Runs after delayInSecs from the previous step’s completion
Example timeline:
Step 1 (order: 1, delay: 0)       → Executes at 10:00 AM
Step 2 (order: 2, delay: 3600)    → Executes at 11:00 AM (1 hour after Step 1 completes)
Step 3 (order: 3, delay: 86400)   → Executes at 11:00 AM next day (24 hours after Step 2 completes)

Call Dispositions

Call steps end with dispositions that determine workflow behavior:
DispositionDescription
COULD_NOT_CONNECTCall failed to connect
NO_ANSWERLead didn’t answer
LEFT_VOICEMAILVoicemail was left
VOICEMAIL_DETECTEDVoicemail detected, no message left
SILENCE_TIMEOUTCall answered but silent
BAD_NUMBERInvalid phone number
NOT_INTERESTEDLead expressed disinterest
WARM_TRANSFERCall transferred to human
CALENDLYAppointment booked
DNCDo not call request
ENDEDCall completed normally
FRAUDFraudulent activity detected
LINE_BUSYLine was busy
CALL_AGAINLead requested callback

Workflow Exit Conditions

Use finishOn to end the workflow when specific dispositions occur:
{
  "finishOn": [
    "CALENDLY",      // Success - booked meeting
    "NOT_INTERESTED", // Opted out
    "DNC",           // Do not call
    "BAD_NUMBER"     // Invalid number
  ]
}

Conditional Logic

Create branching workflows based on previous outcomes:
{
  "steps": [
    {
      "type": "CALL",
      "order": 1,
      "agentId": "agent-123",
      "leaveVoicemail": true,
      "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"]
    },
    {
      "type": "CALL",
      "order": 2,
      "delayInSecs": 3600,
      "agentId": "agent-123",
      "leaveVoicemail": true,
      "conditions": {
        "field": "previousDisposition",
        "operator": "equals",
        "value": "NO_ANSWER"
      },
      "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"]
    },
    {
      "type": "CALL",
      "order": 3,
      "delayInSecs": 86400,
      "agentId": "agent-123",
      "leaveVoicemail": false,
      "conditions": {
        "field": "previousDisposition",
        "operator": "in",
        "value": ["NO_ANSWER", "VOICEMAIL_DETECTED"]
      },
      "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"]
    }
  ]
}
Condition Operators:
  • equals: Exact match
  • in: Match any value in array
  • not_equals: Not equal to
  • not_in: Not in array

Scheduling

Business Hours

Define when the workflow can execute:
{
  "startHour": 9,    // 9 AM
  "endHour": 17,     // 5 PM
  "timezone": "America/New_York"
}
Steps scheduled outside these hours will wait until the next available time window.

Day-Specific Schedules

Control execution by day of week:
{
  "workflowSchedule": {
    "monday": [
      { "startHour": 9, "endHour": 12 },
      { "startHour": 13, "endHour": 17 }
    ],
    "tuesday": [
      { "startHour": 9, "endHour": 17 }
    ],
    "wednesday": [],  // No execution on Wednesdays
    "thursday": [
      { "startHour": 9, "endHour": 17 }
    ],
    "friday": [
      { "startHour": 9, "endHour": 15 }
    ],
    "saturday": [],
    "sunday": []
  }
}

TCPA Compliance

Feather includes built-in TCPA compliance scheduling:
{
  "tcpaSchedule": {
    "defaultSchedule": {
      "startHour": 8,
      "endHour": 21,
      "timezone": "LOCAL"  // Uses lead's timezone
    },
    "stateOverrides": {
      "CA": {
        "startHour": 8,
        "endHour": 20
      },
      "NY": {
        "startHour": 8,
        "endHour": 21
      }
    }
  }
}
TCPA Features:
  • State-specific calling hours
  • Automatic timezone detection
  • Holiday exceptions
  • DNC list integration

Workflow Executions

Creating an Execution

Start a workflow for a specific lead:
const execution = {
  workflowId: "workflow-123",
  customerLeadId: "lead-456",
  variables: {
    firstName: "John",
    companyName: "Acme Corp",
    productName: "Enterprise Plan"
  }
};

const response = await fetch('https://prod.featherhq.com/api/v1/workflow-execution', {
  method: 'POST',
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(execution)
});

Execution States

Executions progress through these states:
CREATED → RUNNING → COMPLETED

          PAUSED → RESUMED → RUNNING

          CANCELLED

          FAILED

Managing Executions

Pause an execution:
await fetch(
  `https://prod.featherhq.com/api/v1/workflow-execution/${executionId}/pause`,
  {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY }
  }
);
Resume an execution:
await fetch(
  `https://prod.featherhq.com/api/v1/workflow-execution/${executionId}/resume`,
  {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY }
  }
);
Cancel an execution:
await fetch(
  `https://prod.featherhq.com/api/v1/workflow-execution/${executionId}/cancel`,
  {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY }
  }
);

Variables in Workflows

Use variables to personalize agent conversations and pass data: Variables are provided when creating the execution and can reference:
  • Lead data: {{firstName}}, {{lastName}}, {{email}}
  • Custom data: Any variables passed in execution creation
  • System data: Timestamps, execution IDs, etc.
Agents can access these variables during calls to personalize conversations based on lead information and workflow context.

Best Practices

Workflow Design

  1. Start simple - Begin with 2-3 steps and expand based on results
  2. Set clear exit conditions - Define when the workflow should stop
  3. Respect recipient preferences - Honor DNC requests immediately
  4. Test thoroughly - Run executions with test leads before production

Timing and Delays

  1. Space out touchpoints - Don’t overwhelm leads with rapid contacts
  2. Consider time zones - Use TCPA schedule with LOCAL timezone
  3. Allow response time - Give leads time to respond between steps
  4. Respect business hours - Configure appropriate start/end hours

TCPA Compliance

  1. Always enable TCPA checks - Set needsTCPACompliance: true
  2. Configure state overrides - Different states have different rules
  3. Handle DNC immediately - Include DNC in finishOn conditions
  4. Document consent - Track when and how consent was obtained

Performance Monitoring

  1. Track disposition rates - Identify patterns in call outcomes
  2. Measure completion rates - How many executions complete successfully
  3. Monitor execution times - Ensure steps execute on schedule
  4. A/B test sequences - Try different messaging and timing

Common Patterns

The Follow-Up Sequence

{
  "name": "Standard Follow-Up",
  "definition": {
    "steps": [
      {
        "type": "CALL",
        "order": 1,
        "delayInSecs": 0,
        "agentId": "sales-agent",
        "leaveVoicemail": true,
        "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"]
      },
      {
        "type": "CALL",
        "order": 2,
        "delayInSecs": 7200,
        "agentId": "sales-agent",
        "leaveVoicemail": true,
        "conditions": {
          "field": "previousDisposition",
          "operator": "in",
          "value": ["NO_ANSWER", "VOICEMAIL_DETECTED"]
        },
        "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"]
      },
      {
        "type": "CALL",
        "order": 3,
        "delayInSecs": 86400,
        "agentId": "sales-agent",
        "leaveVoicemail": false,
        "finishOn": ["CALENDLY", "NOT_INTERESTED", "DNC"],
        "conditions": {
          "field": "previousDisposition",
          "operator": "equals",
          "value": "NO_ANSWER"
        }
      }
    ]
  }
}

The Appointment Reminder

{
  "name": "Appointment Reminder Series",
  "definition": {
    "steps": [
      {
        "type": "CALL",
        "order": 1,
        "delayInSecs": 0,
        "agentId": "reminder-agent",
        "leaveVoicemail": true
      },
      {
        "type": "CALL",
        "order": 2,
        "delayInSecs": 86400,
        "agentId": "reminder-agent",
        "leaveVoicemail": true
      },
      {
        "type": "CALL",
        "order": 3,
        "delayInSecs": 3600,
        "agentId": "reminder-agent",
        "leaveVoicemail": true
      }
    ]
  }
}

Next Steps

I