Send email from Missive with Volanea by using a Missive Rule with the Webhook action, then translating the webhook payload in a small server-side relay. This is a direct webhook-to-your-server integration: Volanea does not provide a native Missive app, marketplace listing, or one-click plugin.
The distinction matters. Missive can notify an external HTTP endpoint when a rule fires, but it is not a place to store or expose a transactional-email provider secret. Your relay receives Missive’s event, applies your business rules, and calls Volanea’s REST API with a verified sender, a controlled recipient, and an idempotency key that makes retries safe.
This guide uses a practical workflow: a teammate applies a Send with Volanea label to a conversation in Missive. That label-change rule fires a webhook. The relay then sends an email notification through Volanea. You can adapt the same pattern for incoming messages, outgoing messages, or other rule types, but label changes are a strong starting point because a human or an earlier rule has made an explicit decision to send.
What the Missive-to-Volanea integration actually is
Missive has developer webhooks and a Rules system. A rule can run when a message arrives, gets sent, or a user takes an action; its actions include Webhook. Missive sends the webhook as an HTTP POST request to a URL you configure. Webhook rules are available to organization admins and owners on Missive Productive or Business plans.
That gives you the first half of the integration:
- A conversation event occurs in Missive.
- A Missive Rule matches it.
- Missive posts JSON about the rule and conversation to your relay.
- Your relay validates, maps, queues, and records the event.
- Your relay sends an authenticated
POST /v1/sendrequest to Volanea.
There is no safe version of a browser-side implementation here. A Volanea secret key authorizes email sends, so it belongs in server-side secret storage, such as a deployment platform secret, environment variable, or managed secrets service. Missive should only know the URL of your relay endpoint; it should not hold the Volanea API key.
This architecture is also easier to operate. It gives you one place to prevent accidental sends, enforce consent rules, normalize recipients, add message templates, keep an audit trail, and troubleshoot a failed hop.
Choose a concrete Missive trigger: a label-change rule
For this implementation, the trigger is: a conversation gets the Send with Volanea label.
In Missive, create an organization rule for the relevant channel and choose the rule type that reacts to the label change. Add a condition that limits it to the specific label, then add Webhook as the action. Missive’s webhook documentation shows a rule.type value such as label_change, and its webhook payload includes the conversation and rule that caused the action.
A label-triggered send is usually safer than sending on every incoming message. It prevents a support mailbox, shared inbox, or automatically forwarded account from turning every conversation into an outbound email. A label represents an explicit operational decision: notify an account manager, send a follow-up, create an escalation notice, or initiate a carefully defined transactional message.
Suggested rule design
Use a clear label name and a narrow rule condition:
- Label:
Send with Volanea - Trigger: Label change / label added
- Condition: Conversation has the
Send with Volanealabel - Action: Webhook
- Webhook URL:
https://your-service.example.com/webhooks/missive - Rule scope: Organization, if the conversation is shared with your organization
Name the rule with a sortable prefix, such as 20. Send labeled conversations to Volanea. Missive runs rules alphabetically by description, so prefixes help when your workflow has prior rules that categorize, assign, or label a conversation.
Do not use this label both as the signal to send and as a generic organizational tag. If somebody removes and re-adds it later, that may create another event. Make the label purpose-specific, and let the relay enforce one logical send per conversation-event combination.
Other valid trigger patterns
After the basic workflow is proven, you might use:
- Incoming message rule: Send an internal alert when a message from a VIP address arrives.
- Outgoing message rule: Notify another system after a shared mailbox sends a response.
- User action rule: Have a teammate type a defined comment or take a defined action to initiate a workflow.
- AI-assisted labeling followed by a webhook: Route only conversations classified into an approved category, while retaining explicit safeguards before sending.
The label-change pattern remains preferable when an email carries customer-impacting consequences. It makes the triggering state visible in the Missive timeline and easier for a teammate to understand later.
Understand the Missive webhook payload before mapping it
Missive sends a JSON object. Its documented general shape contains a rule object and a conversation object. The conversation includes identifiers and summary data such as the conversation subject, organization, team, assignees, authors, counts, labels, and a Missive app URL.
A simplified payload for the label-change workflow looks like this:
{
"rule": {
"id": "45408b30-aa3a-45n1-bh67-0a0cb8da9080",
"description": "20. Send labeled conversations to Volanea",
"type": "label_change"
},
"conversation": {
"id": "47a57b76-df42-4d8k-927x-80dbe5d87191",
"subject": "Mordor GPS coordinates",
"latest_message_subject": "Fwd: Mordor GPS coordinates",
"organization": {
"id": "93e5e5d5-11a2-4c9b-80b8-94f3c08068cf",
"name": "Fellowship"
},
"team": {
"id": "2f618f9e-d3d4-4a01-b7d5-57124ab366b8",
"name": "Hobbits"
},
"authors": [
{
"name": "Samwise Gamgee",
"address": "sam@fellowship.org"
}
],
"shared_labels": [
{
"id": "146ff5c4-d5la-3b63-b994-76711fn790lq",
"name": "Send with Volanea"
}
],
"app_url": "missive://mail.missiveapp.com/#inbox/conversations/47a57b76-df42-4d8k-927x-80dbe5d87191"
}
}
Treat that payload as event context, not as a ready-made email object. In particular, a conversation subject is not necessarily an appropriate subject line, authors[0] is not automatically a consented marketing recipient, and a conversation-level payload may not contain the exact message body you expect for every rule type or channel.
The relay should build a message from known-safe fields. For an internal notification, use a fixed internal recipient. For a customer message, look up the recipient in your application or CRM, confirm the event is eligible to send, and use a template designed for that purpose.
Field mapping used in this guide
The example below deliberately sends an internal escalation email. It maps:
| Missive webhook field | Volanea field or use | Why |
|---|---|---|
conversation.id | Idempotency-Key component | Provides a stable conversation identifier for duplicate protection. |
rule.id | Idempotency-Key component | Separates sends initiated by different rules. |
conversation.latest_message_subject | subject | Gives the internal alert useful context, with a fallback. |
conversation.subject | Subject fallback and message content | Keeps the email useful when there is no latest-message subject. |
conversation.authors[0].name | HTML and text message content | Identifies the visible author when present. |
conversation.authors[0].address | HTML and text message content | Shows the source address without treating it as the email recipient. |
conversation.team.name | HTML and text message content | Helps recipients route the alert. |
conversation.app_url | HTML and text message content | Lets a recipient open the conversation from a supported Missive client. |
The recipient and sender do not come from the Missive payload in this example. They are controlled environment variables. That avoids accidentally routing a message to an untrusted address or attempting to send from an unverified domain.
Build the secure relay that calls Volanea
Your relay can run in Express, Fastify, Cloudflare Workers, AWS Lambda, a queue worker, or another server-side runtime. The core requirements are the same:
- Accept Missive’s JSON
POSTrequest. - Return quickly enough for Missive’s webhook deadline.
- Validate the event shape and apply authorization rules.
- Use a durable idempotency strategy.
- Send the Volanea API request from server-side code.
- Record enough data to investigate failures without logging sensitive content unnecessarily.
Missive requires webhook endpoints to respond within 15 seconds. Therefore, do not make a long chain of external calls before replying. For a low-volume internal notification, the Volanea call may fit comfortably within that window. For anything important or high-volume, persist the event and hand it to a background worker, then return a successful response immediately.
Working Node.js example
This Express route accepts the documented Missive shape, requires the expected rule ID, builds plain-text and HTML content, and calls Volanea’s single-message send endpoint. It uses a stable Idempotency-Key so a repeated delivery for the same conversation and rule does not create a second email.
import express from "express";
const app = express();
app.use(express.json({ limit: "256kb" }));
const {
VOLANEA_API_KEY,
VOLANEA_FROM_EMAIL,
VOLANEA_FROM_NAME = "Missive notifications",
VOLANEA_ALERT_TO,
MISSIVE_RULE_ID
} = process.env;
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
app.post("/webhooks/missive", async (req, res) => {
const payload = req.body;
const rule = payload?.rule;
const conversation = payload?.conversation;
// Missive sends a validation POST when a webhook rule is saved.
// A validation request may not carry a usable conversation payload.
if (!conversation?.id || !rule?.id) {
return res.sendStatus(204);
}
// Accept only the one Missive Rule intended to send this email.
if (rule.id !== MISSIVE_RULE_ID || rule.type !== "label_change") {
return res.sendStatus(204);
}
const labels = conversation.shared_labels ?? [];
const hasSendLabel = labels.some((label) => label?.name === "Send with Volanea");
if (!hasSendLabel) {
return res.sendStatus(204);
}
if (!VOLANEA_API_KEY || !VOLANEA_FROM_EMAIL || !VOLANEA_ALERT_TO) {
console.error("Missing required Volanea relay configuration");
return res.sendStatus(500);
}
const author = conversation.authors?.[0] ?? {};
const subjectSource =
conversation.latest_message_subject ||
conversation.subject ||
"Untitled Missive conversation";
const emailSubject = `[Missive] ${subjectSource}`;
const plainText = [
"A Missive conversation was labeled for notification.",
"",
`Conversation: ${conversation.subject || "Untitled"}`,
`Latest subject: ${conversation.latest_message_subject || "Not provided"}`,
`Author: ${author.name || "Not provided"} <${author.address || "not provided"}>`,
`Team: ${conversation.team?.name || "Not assigned"}`,
`Conversation ID: ${conversation.id}`,
`Open in Missive: ${conversation.app_url || "Not provided"}`
].join("\n");
const html = `
<p>A Missive conversation was labeled for notification.</p>
<ul>
<li><strong>Conversation:</strong> ${escapeHtml(conversation.subject || "Untitled")}</li>
<li><strong>Latest subject:</strong> ${escapeHtml(conversation.latest_message_subject || "Not provided")}</li>
<li><strong>Author:</strong> ${escapeHtml(author.name || "Not provided")} <${escapeHtml(author.address || "not provided")}></li>
<li><strong>Team:</strong> ${escapeHtml(conversation.team?.name || "Not assigned")}</li>
<li><strong>Conversation ID:</strong> ${escapeHtml(conversation.id)}</li>
</ul>
${conversation.app_url ? `<p><a href="${escapeHtml(conversation.app_url)}">Open the conversation in Missive</a></p>` : ""}
`;
const idempotencyKey = `missive:${rule.id}:${conversation.id}:label-change`;
const response = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey
},
body: JSON.stringify({
fromEmail: VOLANEA_FROM_EMAIL,
fromName: VOLANEA_FROM_NAME,
to: [VOLANEA_ALERT_TO],
subject: emailSubject,
text: plainText,
html,
tags: ["missive", "internal-notification"]
})
});
if (!response.ok) {
const responseBody = await response.text();
console.error("Volanea send failed", {
status: response.status,
conversationId: conversation.id,
responseBody
});
// Return a non-2xx response only if you want Missive to retry.
return res.sendStatus(502);
}
return res.sendStatus(202);
});
app.listen(process.env.PORT || 3000);
The Volanea request uses POST /v1/send, a Bearer secret key, JSON content, and the Idempotency-Key header. The fromEmail must be an address on a verified sending domain, except when you are explicitly using test mode. Review the email API reference and setup guides before adding templates, attachments, recipient variables, or event handling.
Keep the Volanea API key out of Missive
The correct answer to “where does the Volanea API key live on the Missive side?” is: it does not live on the Missive side at all.
Missive is the webhook sender. It points at your endpoint. Your relay is the API client that authenticates to Volanea. Store VOLANEA_API_KEY as a server-side environment secret or in a managed secrets product, then read it only at runtime in your server or worker.
Never put the key in any of these places:
- A Missive comment, note, canned response, or rule description.
- A frontend JavaScript bundle or browser-accessible configuration file.
- A public Git repository, example payload, screenshot, or ticket.
- The webhook URL query string.
- A client-side automation that a teammate can inspect or export.
A URL containing a secret can leak through logs, browser history, reverse proxies, incident reports, and monitoring tools. Use an unguessable endpoint path, restrict access at the network edge when possible, and keep the actual Volanea credential in the relay’s secret store.
Separate inbound webhook trust from outbound API authentication
There are two independent security problems:
- Can your endpoint trust this request as a permitted Missive-triggered action?
- Can your server authenticate to Volanea to send the email?
The Volanea API key solves only the second problem. It does not prove that an inbound request came from Missive. Your relay should therefore accept only the expected rule ID, rule type, organization or team identifiers where relevant, and required label. You can also place the endpoint behind a gateway that enforces additional access controls.
Most importantly, do not send merely because any JSON payload contains an email-looking field. Build explicit allowlists: accepted rule IDs, eligible organization IDs, known recipient sources, and message categories your workflow is allowed to create.
Configure and test the Missive Rule
Create the relay before you create the final rule. Missive sends a validation request when you save a webhook rule, so an endpoint that does not respond successfully will prevent a smooth setup.
Setup sequence
- Verify a Volanea sending domain and select a static sender, such as
notifications@updates.example.com. - Deploy the relay with
VOLANEA_API_KEY,VOLANEA_FROM_EMAIL,VOLANEA_ALERT_TO, and a temporaryMISSIVE_RULE_IDsecret configuration plan. - In Missive, open Settings > Rules or the Rules area from the account menu.
- Create an organization rule for the correct shared inbox or channel.
- Configure the label-change trigger and condition for
Send with Volanea. - Add the Webhook action and provide your relay URL.
- Save the rule and confirm the endpoint accepts Missive’s validation request.
- Copy the created Missive rule ID from the webhook data observed by your relay or your controlled logging, then set it as
MISSIVE_RULE_ID. - Apply the label to a test conversation with a safe internal alert recipient.
- Check the Missive conversation timeline, relay logs, and Volanea send result.
Missive shows webhook activity in the conversation timeline after a rule fires. That is useful for determining whether the failure occurred before delivery left Missive or after your service received the request.
Test with a controlled conversation
Start with an internal recipient rather than the conversation author. Use a subject that makes it obvious this is a test, such as TEST — Missive label webhook. Apply the label once, verify exactly one email arrives, then remove and reapply it intentionally to confirm how your idempotency policy behaves.
The example’s idempotency key intentionally treats the same rule and conversation as one send. If the real business event should permit multiple distinct messages for one conversation, include a durable event identifier from your own database or a state/version value you control. Do not simply append Date.now() or a random UUID during each HTTP attempt; that defeats duplicate protection.
When this breaks: diagnose the specific webhook hop
A Missive-to-Volanea flow has at least three separate failure boundaries: Missive to your endpoint, your endpoint to Volanea, and Volanea to the recipient mailbox. A reliable integration distinguishes them instead of calling every failure an “email issue.”
Missive retries and duplicate sends
A network failure can be ambiguous. Your relay may successfully send an email to Volanea but fail before it returns a response to Missive. Missive may then retry its webhook delivery. Without idempotency, the retry can generate a second email.
Use a stable Idempotency-Key constructed from the event’s logical identity, not the current HTTP request. For the label-change example, missive:<rule-id>:<conversation-id>:label-change is stable across retry attempts. Volanea supports idempotency on POST /v1/send, allowing safe retries of a logical send.
Also keep a local event ledger for important workflows. Store the idempotency key, Missive conversation ID, rule ID, recipient, Volanea response status, and send timestamp. That ledger is valuable if a label is removed and re-added, if a rule is edited, or if operators need to determine whether a person got a notice.
Webhook timeouts
Missive requires your endpoint to respond within 15 seconds. A relay that fetches multiple APIs, renders a large document, waits for a slow database transaction, and then calls Volanea may exceed that limit.
The safer pattern is:
- Validate the shape and rule identity.
- Write a minimal event record to durable storage or enqueue a job.
- Return a
2xxresponse quickly. - Have a worker perform the Volanea call.
- Retry the job with the same idempotency key when appropriate.
If you choose synchronous sending, set conservative request timeouts and log whether the Volanea request completed before your endpoint responded. Never blindly retry after an ambiguous timeout with a new key.
Payload fields are missing or empty
Do not assume every event, channel, or conversation has an author, team, subject, app URL, or populated labels array. The documented webhook payload is conversation-oriented, and optional details can be absent in a real event. Your code should use optional access and sensible fallbacks, as the example does with conversation.authors?.[0] and subject fallbacks.
Plan eligibility also matters. Missive documents that creating Rules requires Productive or Business, and organization-level Rules have role requirements. Treat that as a configuration prerequisite, not as a reason to hard-code a different payload shape. If your organization changes plan, scope, channel, or rule type, retest the actual webhook payload before relying on fields that were only present in a previous test.
When a customer-facing email needs data that Missive does not reliably include, fetch it from your system of record using conversation.id or another controlled reference. Do not invent missing fields, and do not turn a blank author address into a recipient.
Volanea rejects the request
A failed Volanea request is usually actionable. Common categories include an absent or invalid secret key, an unverified fromEmail domain, malformed recipient data, an unsupported field, or a suppressed recipient. Log the response status and structured error detail safely, but avoid logging full bodies or personal data unless your retention and access policies justify it.
Keep the sender static. Do not map a customer’s email address into fromEmail; that can create spoofing risk and conflict with sender authentication. If replies should go to a monitored mailbox, configure a verified business address as replyTo after confirming the needed behavior in the API reference.
The email sends but does not arrive
A successful API response means the send was accepted, not necessarily that a recipient saw it in the inbox. Check Volanea’s email events and delivery records, then inspect address quality, suppression status, message content, and domain authentication. For one-off external addresses, you can use the free address verification tool before adding them to a workflow.
Keep transactional notifications distinct from marketing campaigns. A Missive-triggered operational message should be expected by the recipient, tied to a real workflow, and sent only when the event merits it. That protects recipient trust and makes deliverability issues easier to diagnose.
Improve the workflow after the first successful send
The first version should be intentionally narrow: one rule, one static internal recipient, one verified sender, and one message type. Once it is stable, expand with controls rather than simply adding more payload fields.
Add a durable queue
A queue protects you from temporary downtime and lets the webhook receiver respond fast. The receiver writes an event row using a unique key, and a worker sends the Volanea request. If the worker crashes after the API call, the stable idempotency key protects the retry.
This is particularly important if one label can be applied to many conversations at once or if several rules can fire in quick succession. A queue gives you concurrency control, retry backoff, dead-letter handling, and an operator-friendly place to inspect failed jobs.
Use templates for repeatable customer messages
Inline html and text are useful for an internal alert. For customer-facing communication, a stored template can keep wording, branding, localization, and variables consistent. Let the relay supply narrowly defined variables from your application, not arbitrary unescaped email content from a conversation.
If you include user-entered content in HTML, escape it. The example does that for conversation text. Escaping is not an optional polish item: it prevents markup in a subject, name, or conversation title from becoming unintended HTML in the outbound email.
Add recipient policy checks
Before a customer-facing send, verify all of the following:
- The recipient was selected by a defined business rule.
- The email is transactional or otherwise has appropriate permission.
- The event has not already generated the same logical notification.
- The recipient is not suppressed.
- The sender is a verified, controlled address.
- The content does not disclose information to an unintended party.
For example, an author address in Missive can identify the person who started a conversation, but it may be inappropriate to send them an automated message when a teammate applies an internal label. The recipient policy belongs in your relay because it understands the workflow, not merely the field shape.
Alternatives when a custom relay is not the right fit
A direct Missive webhook plus a small relay is the most controllable route for developers. It keeps the Volanea key private, allows real idempotency handling, and does not depend on a client-side browser session.
Missive also documents a native Zapier integration for triggers such as new contacts, comments, and messages. Zapier or Make can be useful when your workflow is simpler and an operations team needs to own it. Even then, avoid placing the Volanea secret in a browser-visible step or copying it into a shared document. Use the automation platform’s secure connection or secret facility if available, and preserve a stable idempotency key where the platform supports custom headers.
Middleware remains the better option when the send decision needs policy checks, database lookups, secure logging, template rendering, or a durable queue. It is not needless complexity when the workflow can affect customers; it is the layer that turns a webhook notification into a safe email operation.
Conclusion
To send email from Missive with Volanea, start with a Missive label-change Rule and its Webhook action, not a nonexistent marketplace plugin. Send the webhook to a server-side relay, validate the expected rule and conversation state, map only safe fields, and call Volanea’s POST /v1/send endpoint with a verified sender and a stable Idempotency-Key.
Keep the Volanea secret entirely outside Missive and outside client-visible configuration. Respond to Missive quickly, queue work when reliability matters, and treat webhook retries as normal rather than exceptional. With those safeguards in place, Missive becomes a useful operational trigger while Volanea remains the dedicated sending layer.
FAQ
Does Volanea have a native Missive integration?
No. This setup uses Missive’s documented Webhook Rule action and a server-side relay that calls the Volanea REST API. There is no native Missive marketplace installation flow to use.
What triggers the Volanea email in this example?
A Missive conversation receives the Send with Volanea label. A label-change rule matches that event and runs the Webhook action, which posts the conversation context to your relay.
Where should I store the Volanea API key?
Store it only in server-side secret storage, such as an environment variable or managed secrets service used by the relay. Do not place it in Missive, browser code, a webhook URL, or shared automation documentation.
How do I prevent duplicate emails when Missive retries a webhook?
Send a stable Idempotency-Key on the Volanea request. Build it from the logical event, such as the Missive rule ID and conversation ID, and reuse that exact key for retry attempts.
What if the webhook payload does not include the recipient or message body I need?
Do not guess. Use the payload only as context, then fetch the needed data from your system of record or redesign the workflow around a controlled template and recipient policy.