How to Send Approved Refund-Policy Replies from Your Own Domain with Resend
Build a Spojit workflow that grounds every refund-policy reply in your current policy document, drafts it with citations, requires a supervisor to approve the money-related response, then sends it from your verified domain through Resend and tags the conversation in Front.
What This Integration Does
Refund questions are sensitive: a wrong promise costs real money and erodes trust. This workflow watches your refunds inbox, finds the relevant passage of your own refund and return policy, and has the intelligent layer draft a reply that quotes that passage. Before anything goes out, a supervisor sees the draft in their Spojit Approvals inbox and either approves or rejects it. Only approved replies are sent, and they leave from your verified domain so the customer sees your brand, not a generic relay address.
The run starts when a new message lands in the connected Gmail or Outlook mailbox for refunds. The Email trigger emits the message fields, a Knowledge query retrieves grounding text from your policy collection, an Agent-mode Connector node produces a structured draft with citations, a Human node pauses for approval, and on approval the resend connector sends the email and the front connector tags the conversation. Each inbound email produces one run; if a supervisor rejects (or the approval times out), the run halts and no email is sent, so re-running is safe and never double-sends.
Prerequisites
- A connected refunds mailbox: Connections -> Add connection -> Gmail (trigger) or Outlook (trigger) (OAuth, read-only is fine).
- A persistent Knowledge collection holding your current refund and return policy. Create it under the Knowledge section in the sidebar and use Upload Document -> Upload & Embed for your policy PDF or Markdown.
- A resend connection whose sending domain is verified. Confirm with the
get-domainorlist-domainstool that the domain status is verified before you go live. - A front connection with permission to read conversations and apply tags. Run
list-tagsonce to capture the tag IDs you want to use. - A supervisor (User, Role, or Team) to staff the approval slot, with access to the Spojit Approvals inbox at
/approvals.
Step 1: Trigger on new refund emails
Add a Trigger node and set its type to Email. Pick the connected Gmail or Outlook mailbox, choose the folder that receives refund requests, and set a poll interval (1 to 60 minutes, default 2). Narrow what fires the workflow with the optional From allowlist and Subject regex (for example a regex matching refund or return). The trigger output gives you fields you will reference downstream, including {{ input.from }}, {{ input.subject }}, {{ input.textBody }}, and {{ input.conversationId }}.
Step 2: Query your refund policy with the Knowledge node
Add a Knowledge node in Query mode. Set Collection to your persistent refund-policy collection, and write a Prompt that combines the customer question with an instruction to return the relevant policy text. Keep Result Count at the default of 5 so you get enough context. A workable prompt:
Customer message:
{{ input.textBody }}
Find and return the exact passages of our refund and return
policy that apply to this customer's situation. Include the
section heading or clause reference for each passage.
Set an Output Variable such as policy so the retrieved passages are available as {{ policy }} in the next step. Use the same embedding model you used when the collection was created.
Step 3: Draft the reply in Agent mode with a Response Schema
Add a Connector node in Agent mode. In the prompt, give it the customer message and the grounding text, and instruct it to answer using only that grounding text and to cite the policy clause it relied on. A solid prompt:
You are drafting a refund reply for a customer.
Customer email:
{{ input.textBody }}
Refund policy passages to use (answer ONLY from these):
{{ policy }}
Write a clear, friendly reply. Quote or reference the specific
policy clause. If the policy does not cover the situation, say
the request needs manual review and do not promise a refund.
Turn on Response Schema so the draft comes back as structured JSON you can map into the email and the approval message. A schema like this keeps the body and citations separate:
{
"type": "object",
"properties": {
"subject": { "type": "string" },
"body": { "type": "string" },
"citations":{ "type": "array", "items": { "type": "string" } },
"needsManualReview": { "type": "boolean" }
},
"required": ["subject", "body", "needsManualReview"]
}
Set an Output Variable such as draft, giving you {{ draft.subject }}, {{ draft.body }}, and {{ draft.citations }}.
Step 4: Require supervisor approval with the Human node
Add a Human node so a person signs off before the money-related reply goes out. Set a clear Label and a Message that shows the draft for review, using upstream variables:
Refund reply ready for {{ input.from }}
Subject: {{ draft.subject }}
{{ draft.body }}
Cited policy: {{ draft.citations }}
Fill the Notification title/body, set Urgency to High, and optionally enable Email approvers. In Approval slots (the only required field), add a slot holding your supervisor as a User, Role, or Team atom. Set a Timeout (minutes) if you want unapproved drafts to expire. The approver acts in the Approvals inbox. On approval the node outputs { approved: true, approvalId, outcome: "APPROVED" } and the run continues; a rejection or timeout halts the run, so no email is sent. Note that branching on "if rejected, do X" is not supported, a rejection simply stops the workflow.
Step 5: Send the approved reply from your domain with Resend
Add a Connector node on the resend connector in Direct mode and pick the send-email tool. Map the fields from the approved draft:
from: an address on your verified domain, for exampleRefunds <refunds@yourdomain.com>(omit it to use the connection default).to:{{ input.from }}.subject:{{ draft.subject }}.text(orhtml):{{ draft.body }}.reply_to: your refunds address so customer replies land back in the right inbox.
Using resend here, rather than the built-in Send Email node, is what lets the reply leave from your own verified domain instead of Spojit's shared mail service.
Step 6: Record the outcome in Front
Add a Connector node on the front connector in Direct mode and pick the add-tag tool to mark the conversation as handled. Map conversationId to the Front conversation for this customer and tag_ids to the array of tag IDs you captured from list-tags (for example a "Refund replied" tag):
conversationId: {{ frontConversation.id }}
tag_ids: ["tag_abc123"]
If your refund conversations live in Front, resolve the conversation first with list-conversations or get-conversation (matching on the customer email) and feed its id into add-tag. This leaves a clean audit trail showing which refund threads got an approved, policy-grounded reply.
Tips
- Keep the policy collection current. When your refund policy changes, re-upload the document so the Knowledge query always grounds replies in the latest terms.
- Use the
needsManualReviewflag from the draft schema. Add a Condition node that routes ambiguous cases to a longer approval message or a different supervisor slot. - Ask Miraxa, the intelligent layer across your automation, to scaffold this for you: "Add a Knowledge query, a Connector node in Agent mode with a response schema, and a Human approval before a Resend send-email node," then fine-tune each node in the properties panel.
- Set the Human node timeout to match your support SLA so stale drafts do not sit pending forever.
Common Pitfalls
- Sending from an unverified domain. Confirm the domain is verified with
get-domainbefore go-live, or Resend will reject thesend-emailcall. - Mismatched embedding models. Query the collection with the same embedding model it was created with, otherwise retrieval quality drops.
- Expecting a reject branch. A rejected or timed-out approval halts the run with no email sent, by design. Do not build downstream "on reject" logic, it will not run.
- Wrong Front tag IDs.
add-tagexpects tag IDs, not tag names. Pull them fromlist-tagsand store them, since names can change.
Testing
Start narrow. Set the Email trigger's Subject regex to match a test phrase and send yourself a refund question from an allowlisted address. Watch the run in execution history: confirm the Knowledge query returns the right policy passage, that {{ draft.body }} cites a clause, and that the run pauses at the Human node. Approve from the Approvals inbox and verify the customer receives the email from your verified domain and that the Front conversation gains the tag. Reject a second test draft to confirm the run halts and nothing sends. Once it behaves, widen the From allowlist and subject filter to your real refunds traffic.