How to Send a Branded Multi-Step Welcome Sequence with Resend
When a signup webhook fires, add the new contact to Resend, send a branded three-email welcome sequence from your own domain, and track each step in MongoDB so the run is resumable and auditable.
What This Integration Does
A great first impression sets the tone for every customer relationship, but stitching a welcome sequence together by hand is slow and easy to get wrong. This Spojit workflow listens for new signups, adds each person to a Resend audience, and then sends three branded emails from your own verified domain: an instant welcome, a getting-started email a few days later, and a check-in near the end of the first week. Because every email goes out through the Resend connector rather than Spojit's shared mail service, your sender address, reply-to, and HTML branding are entirely yours.
The run starts on a Webhook trigger that your signup system posts to. Each run handles exactly one new contact: it inserts a tracking document in MongoDB, queues all three emails in Resend (using Resend's scheduled_at field so later emails go out on their own schedule), then updates the same MongoDB document so you have a record of what was sent. If your signup system retries a delivery, opt-in dedup on the webhook trigger keeps you from welcoming the same person twice, and the MongoDB lookup gives you a second safety net before any email is queued.
Prerequisites
- A Resend connection (API key) with a verified sending domain. You can confirm the domain status with the
get-domainorverify-domaintools before going live. - A Resend audience to hold contacts. Copy its
audience_idfrom the Resend dashboard. - Three branded HTML email templates (welcome, getting-started, check-in) ready to paste into the workflow.
- A MongoDB connection pointing at the database where you want the tracking collection (for example
welcome_sequences). - A Webhook signing connection so Spojit can verify incoming signup posts. See Setting Up a Webhook Connection.
- Your signup system configured to POST new-user JSON (email, first name) to the workflow URL.
Step 1: Start on a Webhook trigger
Create a new workflow and set the Trigger node type to Webhook. Choose your signing connection so each incoming request is verified by HMAC, and turn on dedup using your signup system's event-id header to ignore retried deliveries. Save the workflow to reveal the trigger URL, then point your signup system at it. The trigger output is the parsed JSON body, available downstream as {{ input }}. For this tutorial assume the body looks like:
{
"email": "jordan@example.com",
"firstName": "Jordan"
}
The webhook returns 202 with an executionId immediately, so your signup flow is never blocked waiting on the sequence.
Step 2: Check MongoDB for an existing welcome record
Add a Connector node in Direct mode using the MongoDB connector and the find-documents tool. Point it at your database and a collection such as welcome_sequences, and filter on the signup email:
{
"email": "{{ input.email }}"
}
Set the result limit to 1 and store the output in a variable like existing. Next, add a Condition node that branches on whether a record already exists, for example checking that {{ existing.documents.length }} equals 0. Route the true branch (no record yet) into the rest of the sequence, and let the false branch end the run so an already-welcomed contact is never enrolled twice.
Step 3: Insert a tracking document
On the true branch, add a Connector node in Direct mode using MongoDB and the insert-documents tool to create the tracking record before any email goes out. Insert a single document into welcome_sequences:
{
"email": "{{ input.email }}",
"firstName": "{{ input.firstName }}",
"status": "started",
"emailsQueued": [],
"enrolledAt": "{{ now }}"
}
Store the result in a variable such as tracking. Writing the row first means that even if a later step fails, you can see exactly who started the sequence and where it stopped.
Step 4: Add the contact to your Resend audience
Add a Connector node in Direct mode using the Resend connector and the create-contact tool. Map the fields from the trigger:
audience_id: your audience id from the Resend dashboard.email:{{ input.email }}first_name:{{ input.firstName }}unsubscribed:false
This keeps your Resend audience in sync with your signups so you can also reach these contacts through Resend broadcasts later. Adding the contact here, before sending, means anyone who unsubscribes from the welcome emails is recorded in the same audience.
Step 5: Queue the three branded emails
Add a Connector node in Direct mode using Resend and the send-batch-emails tool to queue all three messages in one call. Each entry uses the same fields as a single send. Set from to an address on your verified domain (for example Acme Team <hello@yourdomain.com>), put your branded markup in html, and use Resend's scheduled_at field (an ISO 8601 timestamp) to space the later emails out. To compute the future timestamps, add a Connector node in Direct mode using the date utility connector and its add tool, or generate them with Miraxa, the intelligent layer across your automation, and fine-tune in the properties panel. A batch payload looks like:
{
"emails": [
{
"from": "Acme Team ",
"to": "{{ input.email }}",
"subject": "Welcome to Acme, {{ input.firstName }}!",
"html": "Welcome aboard, {{ input.firstName }}
...",
"reply_to": "support@yourdomain.com"
},
{
"from": "Acme Team ",
"to": "{{ input.email }}",
"subject": "Getting started with Acme",
"html": "Here is how to set up your first project
...",
"scheduled_at": "{{ day3.result }}"
},
{
"from": "Acme Team ",
"to": "{{ input.email }}",
"subject": "How is it going, {{ input.firstName }}?",
"html": "A quick check-in
...",
"scheduled_at": "{{ day7.result }}"
}
]
}
Store the result in a variable such as batch. Each queued email returns its own id in the same order as the request, so you can record those ids for later lookups.
Step 6: Update the tracking document
Add a final Connector node in Direct mode using MongoDB and the update-documents tool to mark the sequence as queued. Filter on the same email and set the new state, capturing the Resend email ids from the batch result:
{
"filter": { "email": "{{ input.email }}" },
"update": {
"$set": {
"status": "queued",
"emailsQueued": "{{ batch.data }}",
"queuedAt": "{{ now }}"
}
}
}
With this in place, your welcome_sequences collection is a complete, queryable record of who was enrolled and which emails were scheduled. You can later look up an individual send with the Resend get-email tool if you need delivery detail.
Step 7: Reuse the sequence as a Subworkflow (optional)
If you run signups from more than one source (a website form and a partner feed, say), wrap this logic so other workflows can call it. Save the welcome workflow with a Manual trigger version that accepts the same shape as the webhook body, then in your other workflows add a Subworkflow node, pick this workflow under Workflow, and pass the new contact as Input:
{
"email": "{{ contact.email }}",
"firstName": "{{ contact.firstName }}"
}
The parent run pauses while the welcome sequence runs through its own nodes, then continues once it returns. Because changes to a child take effect immediately for every parent, you update your branding in one place. For more on this pattern, see How to Build a Reusable Subworkflow Library.
Tips
- Keep all three emails in a single
send-batch-emailscall rather than three separatesend-emailnodes. It is fewer steps to maintain and the orderedidarray maps cleanly to your tracking document. - Confirm your domain is ready before launch with the Resend
get-domaintool. Sending from an unverified domain lands in spam. - Generate
scheduled_atvalues with the date utility connector'saddtool so the day-3 and day-7 timestamps are consistent and timezone-aware. - Ask Miraxa, the intelligent layer across your automation, to scaffold the Condition and MongoDB branch for you, for example: "Add a Condition node that checks if
{{ existing.documents.length }}equals 0 and connect the true branch to the insert-documents node."
Common Pitfalls
- Skipping the dedup check. Signup systems often retry. Without webhook dedup and the MongoDB
find-documentslookup, a retried post enrolls the same person twice. - Forgetting the from address. If
fromis omitted on any batch entry and no default sender is set on the Resend connection, that email fails to queue. Always set a verifiedfrom. - Bad
scheduled_atformat. Resend expects an ISO 8601 timestamp. A loose date string will be rejected, so compute it with the date connector rather than hand-typing. - Using the wrong audience id.
create-contactrequires a validaudience_id. Copy it directly from the Resend dashboard rather than guessing.
Testing
Before pointing live traffic at the workflow, post a test payload with your own email address to the webhook URL and watch the run in the execution history. Confirm the find-documents step returns nothing on the first run, that the contact appears in your Resend audience, and that the welcome_sequences document is created and then updated to queued. Temporarily set the day-3 and day-7 scheduled_at values a few minutes out so you can verify all three branded emails actually arrive from your domain. Run the same payload a second time to confirm the Condition branch stops the duplicate before any email is queued. Once it behaves, restore the real intervals and enable the workflow.