Relay.app previously made it possible to send email from Relay.app through an outbound API call, without a native Volanea app or marketplace plugin. There is an important current-status caveat first: Relay.app shut down in September 2026, and its documentation states that accounts, workflows, and run history were permanently deleted—so nobody can create this integration in Relay.app today.
This page is therefore an archived technical guide for teams documenting an old workflow, rebuilding it elsewhere, or understanding how their former Relay.app automation should have connected to Volanea. The good news is that the architecture is straightforward: an event starts a workflow, Relay.app maps that event into an HTTP request, and Volanea accepts the transactional message at POST /v1/send.
Relay.app did have an outbound HTTP capability called Custom HTTP requests. It also had a Webhook trigger for starting a workflow from an incoming event. It did not ship a native Volanea integration, app listing, or one-click marketplace install. The connection was an explicit REST integration, which is generally the right model for operational email because it makes the recipient, subject, body, sender, and duplicate-prevention behavior visible in the workflow.
Current status: Relay.app cannot be configured now
Before copying an archived setup, distinguish between a historical workflow and a deployable one. Relay.app’s own documentation says it shut down in September 2026 and that all accounts, workflows, and run history were permanently deleted. That means there is no standard plan, paid plan, workspace, Secret Store entry, workflow editor, or HTTP action available to configure now.
If your team still says “send email from Relay.app,” it normally means one of three things:
- You are auditing an automation that existed before the shutdown.
- You are migrating Relay.app logic to another workflow tool or to your own application.
- You need to reproduce the former event-to-email contract so a downstream system does not change behavior unexpectedly.
The rest of this guide preserves the direct pattern Relay.app supported. For a new production implementation, use the same request shape from your current automation platform, serverless function, queue consumer, or backend service. The Volanea endpoint and idempotency design remain useful independently of the workflow product that invokes them.
The historical Relay.app workflow pattern
The historical direct path had two Relay.app components:
- A Webhook trigger to receive an event and start a workflow run.
- A Custom HTTP requests action to call the Volanea REST API.
Relay.app workflows began with a trigger. For this implementation, the concrete trigger was the Webhook trigger: an upstream service sent an HTTPS request to the workflow’s Relay webhook URL, and Relay started one workflow run for that request.
That is deliberately more precise than saying “when a record is created.” Relay.app supported app-specific event triggers too, but a record-created event, form-submitted event, or deal-stage-changed event depended on the connected source application. The portable, direct integration described here begins when Relay.app receives a webhook request.
The following flow shows the responsibility boundary:
- Your source system creates a business event, such as
invoice.paid,request.received, ortrial.started. - That source system posts event data to Relay.app’s Webhook trigger URL.
- Relay.app starts a workflow run and exposes the incoming event fields to later steps.
- The Custom HTTP requests action constructs a Volanea
POST /v1/sendrequest. - Volanea accepts the message for its sending pipeline.
- Your operational system records the event ID and Volanea response for reconciliation.
The fact that this is an API call matters. A successful API response means Volanea accepted the request; it is not proof that the recipient has opened the email, or even that a mailbox provider has accepted final delivery. Treat acceptance, delivery, bounce, complaint, and open/click events as separate states in your monitoring design.
The actual webhook payload Relay.app received
Relay.app’s Webhook trigger did not impose one fixed business-event schema. The payload belonged to the system posting to its webhook URL. In other words, there is no universal “Relay.app email payload” to copy from a marketplace connector.
Instead, the real payload Relay.app received was the JSON sent by your upstream system. For a transactional receipt, an appropriate webhook body would have looked like this:
{
"relayDeduplicationKey": "invoice-paid:inv_1042",
"eventId": "evt_8a4de1",
"eventType": "invoice.paid",
"occurredAt": "2026-08-18T14:21:34.000Z",
"customer": {
"email": "ada@example.com",
"firstName": "Ada"
},
"invoice": {
"id": "inv_1042",
"number": "1042",
"amount": 49,
"currency": "USD",
"receiptUrl": "https://app.example.com/invoices/inv_1042"
}
}
The important Relay-specific field is relayDeduplicationKey. Relay.app documented that adding this property to a Webhook trigger payload caused Relay to start only one run for each unique value. Later requests with the same key did not start a new run; Relay returned a duplicate result instead.
Choose that key from a stable business fact, not from the request timestamp or a random UUID generated for every retry. invoice-paid:inv_1042 is stable. invoice-paid:2026-08-18T14:21:34.000Z is not stable if the sender retries later with a different timestamp. A stable key is the first layer of duplicate prevention, but it should not be the only layer.
For a contact-form workflow, the equivalent payload might use a submission ID. For a CRM workflow, use the immutable record-event ID if the CRM supplies one. For an approval workflow, use the approval ID plus the notification type. The objective is always the same: one business event should lead to one logical email operation.
Mapping Relay event fields to a Volanea email
The Custom HTTP requests action allowed Relay.app to make an outbound request and use data from earlier workflow steps. Historically, you would select the webhook-trigger fields as values while configuring the HTTP request rather than hand-writing a templating language. That is important because Relay.app’s field picker and data typing—not a universal text interpolation syntax—controlled how workflow values were inserted.
The mapping for the receipt event is simple:
| Incoming event field | Volanea send field | Why it belongs there |
|---|---|---|
customer.email | to | The individual recipient address. |
| A verified address you control | from | The authenticated sending identity. |
invoice.number | subject | Makes the notification recognizable in the inbox. |
customer.firstName, invoice.amount, invoice.receiptUrl | html and text | Personalizes the rendered content. |
eventId or invoice.id | Idempotency-Key | Makes an uncertain retry safe. |
customer.email | replyTo only when appropriate | Routes replies to a monitored inbox; it is not normally the customer address. |
The Volanea send endpoint is POST https://api.volanea.com/v1/send. It accepts a JSON message request, uses a Volanea secret key through an Authorization: Bearer header, and supports the Idempotency-Key header for safe retries. A single send can target one recipient or up to 50 recipients, but transactional notifications should usually be modeled as one recipient per logical event unless you intentionally need a small, visible group send.
Here is the resulting Volanea request as a complete curl example. It is also a useful debugging baseline when migrating the integration away from Relay.app:
export VOLANEA_API_KEY="sk_live_replace_me"
curl --request POST "https://api.volanea.com/v1/send" \
--header "Authorization: Bearer ${VOLANEA_API_KEY}" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: invoice-paid:inv_1042" \
--data '{
"from": "Billing <billing@updates.example.com>",
"to": "ada@example.com",
"replyTo": "support@example.com",
"subject": "Your receipt for invoice #1042",
"html": "<p>Hi Ada,</p><p>We received your payment of <strong>$49.00 USD</strong>.</p><p><a href=\"https://app.example.com/invoices/inv_1042\">View your receipt</a></p>",
"text": "Hi Ada,\n\nWe received your payment of $49.00 USD.\n\nView your receipt: https://app.example.com/invoices/inv_1042"
}'
Use a from address on a domain you have verified in Volanea. Do not make the from field equal to an arbitrary customer-supplied email address. That creates authentication and deliverability problems, and it makes replies unpredictable. If a reply is needed, use a controlled replyTo address that a real team or support process monitors.
For deeper endpoint details, payload options, and setup guidance, see the Volanea API reference and setup guides.
A working middleware route for the same event-to-email contract
Because Relay.app no longer exists, a small server-side route is often the cleanest replacement. The route below accepts the archived webhook payload shape, validates the fields that must exist, creates both HTML and plain-text content, and sends the request to Volanea.
This example uses a JavaScript runtime with the standard Request and Response APIs, so it can be adapted for a serverless route, edge handler, or a conventional Node server. Store VOLANEA_API_KEY in the hosting provider’s secret manager or environment configuration—not in browser code, a public client-side config file, or a repository.
function escapeHtml(value) {
return String(value)
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/\"/g, """)
.replace(/'/g, "'");
}
export default async function handleInvoicePaid(request) {
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
const event = await request.json();
const recipient = event?.customer?.email;
const firstName = event?.customer?.firstName || "there";
const invoiceId = event?.invoice?.id;
const invoiceNumber = event?.invoice?.number;
const amount = event?.invoice?.amount;
const currency = event?.invoice?.currency;
const receiptUrl = event?.invoice?.receiptUrl;
if (!recipient || !invoiceId || !invoiceNumber || amount == null || !currency || !receiptUrl) {
return Response.json(
{ error: "Missing required invoice-paid event fields" },
{ status: 400 }
);
}
const idempotencyKey = event.relayDeduplicationKey || `invoice-paid:${invoiceId}`;
const safeName = escapeHtml(firstName);
const safeInvoiceNumber = escapeHtml(invoiceNumber);
const safeAmount = escapeHtml(Number(amount).toFixed(2));
const safeCurrency = escapeHtml(currency);
const safeReceiptUrl = escapeHtml(receiptUrl);
const payload = {
from: "Billing <billing@updates.example.com>",
to: recipient,
replyTo: "support@example.com",
subject: `Your receipt for invoice #${invoiceNumber}`,
html: `<p>Hi ${safeName},</p><p>We received your payment of <strong>${safeAmount} ${safeCurrency}</strong> for invoice #${safeInvoiceNumber}.</p><p><a href="${safeReceiptUrl}">View your receipt</a></p>`,
text: `Hi ${firstName},\n\nWe received your payment of ${Number(amount).toFixed(2)} ${currency} for invoice #${invoiceNumber}.\n\nView your receipt: ${receiptUrl}`
};
const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey
},
body: JSON.stringify(payload)
});
const responseBody = await volaneaResponse.text();
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
eventId: event.eventId,
invoiceId,
responseBody
});
return Response.json(
{ error: "Email request was not accepted", status: volaneaResponse.status },
{ status: 502 }
);
}
return new Response(responseBody, {
status: 200,
headers: { "Content-Type": "application/json" }
});
}
There are two intentional reliability choices in this code. First, it rejects incomplete data before a message can be created with an empty recipient, missing invoice number, or unusable receipt URL. Second, it uses the same stable idempotency value for every retry of the same invoice-paid event.
If you rebuild the workflow in another automation tool, have that tool call this middleware with its own stored connection credential. The middleware keeps the Volanea secret in infrastructure you control, validates the incoming schema in one place, and gives you a stable place to add logging, allowlists, signature verification, rate limits, and observability later.
Historical Relay.app configuration steps
Before the shutdown, the direct configuration would have followed this sequence:
- Create a workflow and choose the Webhook trigger.
- Copy the generated webhook URL into the system that emits the business event.
- Ensure the upstream sender includes a stable
relayDeduplicationKeyin the JSON request body. - Add a Custom HTTP requests action after the trigger.
- Set the request method to
POSTand the request URL tohttps://api.volanea.com/v1/send. - Add
Content-Type: application/json. - Add
Authorization: Bearer …, sourcing the secret portion from Relay.app’s Secret Store. - Add
Idempotency-Key, using the same stable event value used for the notification operation. - Build the JSON body by mapping trigger fields to Volanea fields such as
to,subject,html, andtext. - Test with a non-production recipient, inspect the HTTP response, then verify the send record and downstream delivery events in Volanea.
Do not mistake a manually started test run for a complete integration test. Test the entire chain: the upstream source creates an actual event, the webhook reaches the workflow endpoint, the event maps into the correct recipient and content, Volanea accepts the request, and the resulting email is rendered correctly in a real mailbox.
API key handling: where the secret belonged
Historically, the Volanea API key belonged in Relay.app’s Secret Store, not in the workflow payload, a constant, a prompt, a spreadsheet field, or any data that an end user could inspect. Relay.app’s Custom HTTP request documentation explicitly stated that its Secret Store could hold API secrets.
The practical pattern was:
- Create a Volanea secret key for the integration.
- Put that key in Relay.app’s Secret Store.
- Reference the secret only when constructing the
Authorization: BearerHTTP header. - Keep the webhook event free of Volanea credentials.
- Limit who can edit the workflow and who can view or change the secret.
A Volanea secret key is server-side infrastructure credentials. Anyone who obtains it may be able to submit email through your project, consume sending capacity, damage your sender reputation, or impersonate operational messages from your verified domain. A key must never be shipped to a browser, embedded in a public page, passed into a client-visible JavaScript variable, or inserted into an untrusted form submission.
For a replacement implementation, the equivalent secret location is your automation platform’s protected connection/secret feature or your serverless provider’s encrypted environment-variable store. The principle is more important than the brand name: the secret is only available to the trusted process that makes the Volanea request.
Rotate the key if a former Relay workflow exported it into documentation, copied it into a ticket, or used it in a test that was shared widely. Update the replacement integration first, verify sends, then revoke the old credential. Avoid a rotation plan that revokes the current key before the new path has been tested.
Deliverability choices that belong in the workflow design
An automation can successfully call an email API and still produce a poor recipient experience. The workflow must be designed around the type of message it sends.
Transactional email is appropriate when the recipient reasonably expects a message because they triggered or are directly affected by an action: a receipt, a password reset, an invitation, a workflow approval result, a shipment status, or a requested report. Promotional messages, broad announcements, and recurring marketing campaigns have different consent and unsubscribe requirements and should not be disguised as a webhook-triggered receipt.
For operational notifications, apply these rules:
- Use a verified domain and a recognizable sender name.
- Send to the address associated with the actual event, not a free-form address supplied in an unrelated field.
- Include plain text as well as HTML so the message remains useful in restrictive clients.
- Escape or sanitize event-derived values before inserting them into HTML.
- Keep subject lines descriptive rather than urgent-looking or misleading.
- Use a monitored reply address when a recipient may reasonably reply.
- Do not put sensitive personal or financial data in a subject line.
- Treat a successful HTTP response as acceptance, then observe later delivery or suppression outcomes separately.
For high-volume or high-value messages, consider validating an address before placing it into a workflow branch. Volanea’s email address verification tool can help catch malformed or risky addresses before they create avoidable bounces. Verification is an input-quality control, not a substitute for consent, good content, or domain authentication.
When this breaks
The fragile point in this architecture was not simply “email sending.” It was the hop from an upstream event into a workflow run and then from the workflow’s outbound HTTP action into Volanea. Troubleshoot that chain in order.
Relay-side retries can cause duplicate sends
A retry is not evidence that the first request failed. The original Volanea request may have succeeded, while the caller timed out before seeing the response. If Relay.app retried the Custom HTTP request or an operator replayed a failed run, a new POST without duplicate protection could create a second email.
Use two layers of protection. First, supply relayDeduplicationKey in the payload sent to the Relay Webhook trigger so duplicate inbound events do not start duplicate workflow runs. Second, use the same stable business-event value in Volanea’s Idempotency-Key header. Volanea supports idempotency on the single-send endpoint, allowing a safe retry of the same logical send instead of treating each POST as a new message.
Do not generate the idempotency key from the whole email body. A content correction can then accidentally become a second send, while identical bodies for two different events can collide. Scope the key to the event and the email purpose, such as invoice-paid:inv_1042:receipt or case-approved:case_981:customer-notice.
The HTTP action can time out
Relay.app documented a standard three-minute timeout for outbound Custom HTTP requests and did not expose user configuration for that timeout. Volanea’s send endpoint should respond much faster in normal operation, so a timeout usually points to a connectivity issue, an intermediary problem, a stalled route, or an unhealthy downstream dependency rather than ordinary email delivery delay.
A timeout creates an ambiguous state: the message might not have reached Volanea, it might be in progress, or it might have been accepted just before the connection ended. Never solve that ambiguity by immediately disabling idempotency and sending again. Retry with the same Idempotency-Key, log the source event ID, and inspect the Volanea send history before attempting a manual resend.
A field can be absent or have the wrong type
The Webhook trigger made the incoming event schema your responsibility. One source event may include customer.email, while another event type may use email, contact.email, or no email address at all. A field can also be blank, an array instead of a string, or present only when the source integration has sufficient permissions or a qualifying source-product plan.
Do not assume this is a Relay.app plan limitation. Relay.app did not define your source system’s business payload. If values are missing, inspect the raw source event first, then confirm the source connector’s permissions, trigger configuration, and plan-specific data availability. In a replacement system, preserve a sample event for every event type and validate all required fields before calling Volanea.
At minimum, reject and alert on a missing recipient, missing event ID, missing template variables, or a missing business object ID. Sending a generic email to the wrong person is worse than pausing a run for review.
The sender domain is not verified
If the from domain is not verified in Volanea, the send request can be rejected. This is not something a Relay workflow can fix by changing the body mapping. Configure the domain in Volanea, publish the requested DNS records, and verify the domain before testing the live workflow.
Do not work around a verification failure by switching to a customer’s domain or using an arbitrary free-mail address. Use a domain your organization owns and controls. That keeps authentication aligned with the sending identity and protects long-term deliverability.
A 2xx acceptance is not final inbox delivery
Volanea’s acceptance response tells you the platform received and processed the API request; it is not a receipt from Gmail, Outlook, or the recipient’s server. A later suppression decision, unsubscribe state, bounce, or receiving-server outcome can still affect delivery.
For important notices, save the source event ID, idempotency key, Volanea response identifier, recipient, and workflow run identifier in your own audit system. Those five values make it possible to answer practical questions later: Did the source event occur? Did the workflow run? Was the API request accepted? Was it replayed? Which recipient was targeted?
Rebuilding the flow after Relay.app
The right Relay.app replacement depends on where the event originates and how much control you need. The email-send contract should remain the same even if the automation tool changes.
A lightweight replacement can call Volanea directly if the new platform provides all of the following:
- An outbound HTTP action with custom headers and JSON body support.
- A protected secret store for the Volanea API key.
- Access to the actual trigger payload fields.
- A way to retain or compute a stable event identifier for
Idempotency-Key. - Error handling and a run history that lets you inspect failed requests.
Use middleware instead when the workflow needs validation, complex branching, signature verification, HTML rendering, data lookups, audit logging, or strict control over retry behavior. Middleware is also the safer option if your automation vendor makes it difficult to keep the API key hidden or cannot reliably reuse a stable idempotency key on retries.
A queue-backed implementation is worth considering for high-value workflows such as invoices, account access, incident alerts, and regulated communications. In that model, the webhook handler verifies and stores the business event first, a worker sends the Volanea request with idempotency, and a reconciliation process tracks send and delivery outcomes. It adds infrastructure, but it separates event receipt from email dispatch and makes recovery much easier.
Conclusion
The historical way to send email from Relay.app with Volanea was a direct REST integration: a Webhook trigger received a source event, a Custom HTTP requests action issued POST /v1/send, and Relay.app’s Secret Store protected the Volanea API key. There was no native Volanea marketplace app to install.
That exact setup cannot be newly deployed because Relay.app shut down in September 2026. But the underlying design remains a sound migration target: validate an event, map only the fields you need, keep the API key server-side, send from a verified domain, and use a stable idempotency key at every retry boundary. Rebuild those controls in your next automation platform or middleware layer, and the email behavior will be more reliable than a one-click connector ever could be.
FAQ
Can I still create a Relay.app workflow to send through Volanea?
No. Relay.app shut down in September 2026, and its accounts, workflows, and run history were permanently deleted. Use this guide to audit or migrate an older workflow, not as a current Relay.app signup tutorial.
Did Relay.app have a native Volanea integration?
No. The historical connection used Relay.app’s Custom HTTP requests action to call Volanea’s REST API. There was no native Relay.app app, marketplace listing, or plugin installation flow for Volanea.
What started the former Relay.app email workflow?
This archived pattern used Relay.app’s Webhook trigger. An upstream system posted a JSON business event to the workflow webhook URL, and Relay.app started a run from that event.
How do I prevent duplicate transactional emails?
Use a stable business-event identifier twice: include it as relayDeduplicationKey when posting to the Relay Webhook trigger, and send the same logical value in Volanea’s Idempotency-Key header. Keep the key constant when retrying the same event.
Where should the Volanea API key live now?
Store it in a protected server-side secret manager, encrypted environment variable, or automation-platform secret store. Never put the key in browser code, client-visible configuration, an inbound webhook body, or a public workflow variable.