Skip to content
← All templates

Cold Email 3-Step Sequence

Send a personalized cold email, wait 3 days, check if the prospect replied, then follow up or stop. Built-in rate limiting prevents deliverability issues.

http_requestdelayrouterrate_limitloop

What this workflow does

01

Send initial email HTTP POST to your email provider (SendGrid, Resend, Postmark) with personalized content from context. Rate-limited to respect provider quotas and protect deliverability.

02

Wait 3 days Delay step pauses the sequence for 3 business days. The engine sleeps with zero resource consumption — no threads held, no connections open.

03

Check for reply HTTP GET to your email provider or CRM API to check if the prospect replied. Maps reply status to context.

04

Branch on reply Router checks if a reply was received. If yes, the sequence ends — no follow-up needed. If no, continues to follow-up.

05

Send follow-up Second email with a different subject line and angle. Rate-limited. After the follow-up, waits 3 more days and checks again. If still no reply after the third touch, the sequence ends gracefully.

Workflow definition

Copy this JSON and POST it to /sequences.

{
  "id": "cold_email_3_step_v1",
  "context_schema": {
    "prospect_email": "string",
    "prospect_name": "string",
    "prospect_company": "string",
    "sender_name": "string",
    "sender_email": "string",
    "email_provider_url": "string",
    "reply_check_url": "string"
  },
  "blocks": [
    {
      "id": "send_initial",
      "type": "step",
      "handler": "http_request",
      "params": {
        "method": "POST",
        "url": "{{context.data.email_provider_url}}",
        "headers": {
          "Authorization": "Bearer credentials://email-api-key",
          "Content-Type": "application/json"
        },
        "body": {
          "from": "{{context.data.sender_email}}",
          "to": "{{context.data.prospect_email}}",
          "subject": "Quick question for {{context.data.prospect_company}}",
          "html": "<p>Hi {{context.data.prospect_name}},</p><p>I noticed {{context.data.prospect_company}} is scaling — curious if you've looked at automating your internal workflows.</p><p>We built Orch8, a workflow engine that handles the durability, retries, and scheduling so your team doesn't have to.</p><p>Worth a 15-minute call?</p><p>{{context.data.sender_name}}</p>"
        }
      },
      "rate_limit_key": "email:outbound",
      "retry": { "max_attempts": 2, "backoff": "30s" }
    },
    {
      "id": "wait_3_days",
      "type": "step",
      "handler": "builtin.noop",
      "delay": "3d"
    },
    {
      "id": "check_reply_1",
      "type": "step",
      "handler": "http_request",
      "params": {
        "method": "GET",
        "url": "{{context.data.reply_check_url}}?email={{context.data.prospect_email}}",
        "headers": {
          "Authorization": "Bearer credentials://email-api-key"
        }
      }
    },
    {
      "id": "reply_gate_1",
      "type": "router",
      "routes": [
        {
          "condition": "steps.check_reply_1.output.replied == true",
          "blocks": [
            {
              "id": "log_replied",
              "type": "step",
              "handler": "log",
              "params": {
                "level": "info",
                "message": "Prospect {{context.data.prospect_email}} replied — sequence complete"
              }
            }
          ]
        }
      ],
      "default": [
        {
          "id": "send_followup",
          "type": "step",
          "handler": "http_request",
          "params": {
            "method": "POST",
            "url": "{{context.data.email_provider_url}}",
            "headers": {
              "Authorization": "Bearer credentials://email-api-key",
              "Content-Type": "application/json"
            },
            "body": {
              "from": "{{context.data.sender_email}}",
              "to": "{{context.data.prospect_email}}",
              "subject": "Re: Quick question for {{context.data.prospect_company}}",
              "html": "<p>Hi {{context.data.prospect_name}},</p><p>Following up — I know inboxes get busy.</p><p>Teams using Orch8 typically replace 2-3 internal tools (cron jobs, retry scripts, approval queues) with a single engine. Self-hosted, PostgreSQL-backed, runs anywhere.</p><p>Happy to show a quick demo if useful.</p><p>{{context.data.sender_name}}</p>"
            }
          },
          "rate_limit_key": "email:outbound",
          "retry": { "max_attempts": 2, "backoff": "30s" }
        },
        {
          "id": "wait_3_days_2",
          "type": "step",
          "handler": "builtin.noop",
          "delay": "3d"
        },
        {
          "id": "check_reply_2",
          "type": "step",
          "handler": "http_request",
          "params": {
            "method": "GET",
            "url": "{{context.data.reply_check_url}}?email={{context.data.prospect_email}}",
            "headers": {
              "Authorization": "Bearer credentials://email-api-key"
            }
          }
        },
        {
          "id": "reply_gate_2",
          "type": "router",
          "routes": [
            {
              "condition": "steps.check_reply_2.output.replied == true",
              "blocks": [
                {
                  "id": "log_replied_2",
                  "type": "step",
                  "handler": "log",
                  "params": {
                    "level": "info",
                    "message": "Prospect {{context.data.prospect_email}} replied after follow-up"
                  }
                }
              ]
            }
          ],
          "default": [
            {
              "id": "send_final",
              "type": "step",
              "handler": "http_request",
              "params": {
                "method": "POST",
                "url": "{{context.data.email_provider_url}}",
                "headers": {
                  "Authorization": "Bearer credentials://email-api-key",
                  "Content-Type": "application/json"
                },
                "body": {
                  "from": "{{context.data.sender_email}}",
                  "to": "{{context.data.prospect_email}}",
                  "subject": "Last note — {{context.data.prospect_company}}",
                  "html": "<p>Hi {{context.data.prospect_name}},</p><p>Last touch — no hard feelings if the timing's off.</p><p>If workflow automation is ever on the roadmap, here's where to find us: <a href='https://orch8.io'>orch8.io</a></p><p>All the best,<br/>{{context.data.sender_name}}</p>"
                }
              },
              "rate_limit_key": "email:outbound"
            },
            {
              "id": "log_sequence_end",
              "type": "step",
              "handler": "log",
              "params": {
                "level": "info",
                "message": "3-step sequence completed for {{context.data.prospect_email}} — no reply"
              }
            }
          ]
        }
      ]
    }
  ]
}

Credentials to configure

email-api-keyapi_keyAPI key for your email provider (SendGrid, Resend, Postmark)

How to trigger

// POST /sequences/cold_email_3_step_v1/instances
{
  "context": {
    "data": {
      "prospect_email": "jane@example.com",
      "prospect_name": "Jane",
      "prospect_company": "Acme Corp",
      "sender_name": "Alex",
      "sender_email": "alex@yourcompany.com",
      "email_provider_url": "https://api.resend.com/emails",
      "reply_check_url": "https://api.yourapp.com/replies"
    }
  }
}

Start the sequence by creating an instance with prospect and sender details. Works with any email provider that exposes a REST API.

Customize it

Swap email provider — change the HTTP endpoint and body format for SendGrid, Postmark, or your custom SMTP relay.

Add LLM personalization — insert an llm_call step before each email that generates a personalized opening line based on the prospect's LinkedIn or company data.

CRM integration — add steps to update your CRM (HubSpot, Salesforce) with sequence status after each touch.

Business-hour send windows — add send_window to each email step to only send during 9 AM-5 PM in the prospect's timezone.