Send email from Intercom without giving your application another client-side email credential: use an Intercom webhook as the event source, then let secure middleware call Volanea’s email API. This approach works because Intercom can notify an external endpoint about supported workspace events, while your server controls recipient eligibility, templates, authentication, and idempotency.
There is one important constraint upfront: Volanea does not provide a native Intercom Marketplace app or an install-and-connect plugin. The integration is a webhook-based architecture, not a one-click marketplace connection. Intercom emits an event to an endpoint you operate; that endpoint validates the request and sends the resulting email through Volanea.
What this Intercom-to-Volanea integration does
The integration turns an Intercom event into an email send. A practical example is a new customer contact entering Intercom: Intercom publishes a contact.created webhook, your endpoint receives the contact payload, and the endpoint sends a welcome, verification, onboarding, or internal notification email through Volanea.
This is especially useful when you want Intercom to remain the source of customer activity while Volanea handles application email infrastructure. The two systems have different jobs:
- Intercom detects customer events and stores customer context.
- Your middleware makes business decisions: whether a contact is eligible, which template to use, and whether the event has already been processed.
- Volanea delivers the email over its transactional email API and gives your application a dedicated sending path.
The event does not need to be contact.created forever. Once the basic flow works, you can apply the same pattern to other webhook topics that your Intercom workspace and developer app support, such as events related to conversations, tickets, tags, or companies. The crucial design rule is unchanged: model the email as a response to a specific, server-observed event, rather than attempting to put a sending key in a browser, mobile app, or public automation URL.
The concrete Intercom trigger: contact.created
For this guide, the trigger is Intercom’s contact.created webhook topic. Intercom sends this notification when a contact is created in the workspace. It is a useful integration starting point because it has a clear business meaning and typically supplies the contact identifiers your application needs to make a decision.
A webhook is an outbound HTTP request from Intercom to a URL you configure for a developer app. It is not an instruction that Intercom runs inside your codebase, and it is not a direct API call from Intercom to Volanea. That distinction matters because the webhook has to reach an endpoint that can safely hold the Volanea API key.
Why contact.created is a good first event
A contact-created event can support several email journeys:
- Welcome confirmation — acknowledge that a person has signed up or been added.
- Product onboarding — send next-step instructions after your own eligibility checks pass.
- Account linking — prompt the person to finish connecting a product account to the contact record.
- Internal operations alert — notify an account manager when a high-value contact is created.
- Consent-aware follow-up — send only after your middleware confirms that the relevant consent and suppression rules permit it.
Do not equate “Intercom received a contact” with “this person may receive any email.” Contacts can be created by imports, admin actions, inbound support flows, mobile activity, API calls, or identity merges. Some contacts may lack an email address entirely. Others may be leads, users, or records associated with an external identity that is not appropriate for an immediate transactional message.
Your middleware is where those conditions belong. That creates one place to audit and change the policy instead of scattering mail decisions across Intercom configuration, frontend code, and application services.
Configure the webhook endpoint in Intercom
Create or use an Intercom developer app for your workspace, then configure a webhook subscription for the contact.created topic. Point it to a public HTTPS endpoint you control, such as:
POST https://app.example.com/webhooks/intercom
Intercom needs to be able to reach that endpoint from the public internet. A localhost address, private RFC 1918 address, or URL protected only by your company VPN will not work as a production destination. During local development, use a secure tunnel and treat it as temporary infrastructure; production should use a stable HTTPS hostname under your control.
Keep the endpoint narrowly scoped. It should receive Intercom webhook requests and return a prompt success response after durable processing or after safely enqueueing work. It should not double as a generic public endpoint that accepts arbitrary email data from the browser.
The actual payload your endpoint receives
Intercom webhook notifications use an event envelope. For a contact.created event, the payload contains a top-level notification type and topic, along with a data object that represents the contact. The exact fields can vary according to the type of contact, available data, workspace configuration, and the event version Intercom sends, so your code must treat optional fields as optional.
A representative contact.created payload has this shape:
{
"type": "notification_event",
"topic": "contact.created",
"app_id": "abc123",
"data": {
"type": "contact",
"id": "65d4c12e9a8b7f0012345678",
"workspace_id": "wk_123456",
"external_id": "user_48291",
"role": "user",
"email": "alex@example.com",
"phone": "+14155550123",
"name": "Alex Morgan",
"created_at": 1708444800,
"updated_at": 1708444800
},
"created_at": 1708444801
}
Treat this as an event notification, not as a complete customer profile. The data.email value may be absent, blank, malformed, or unsuitable for a particular message. Likewise, a contact name may not be present, may contain only whitespace, or may not be the name your application wants to display.
Before attempting a send, validate at least these facts:
- The webhook topic is exactly the topic your route is designed to process.
- The event is authentic according to Intercom’s webhook-verification guidance.
- The contact has a usable recipient email address.
- The event is not already recorded as successfully handled.
- The contact meets your consent, lifecycle, and suppression requirements.
- The sender identity and template are appropriate for the message category.
If your email needs more context than the webhook provides, use the contact ID or external ID to look up your own application record. Avoid making assumptions such as “a contact’s email is always the product account email” or “the external ID is always present.” Those assumptions are common sources of sends to the wrong recipient.
The architecture: Intercom webhook, middleware, Volanea API
The direct integration path has three hops:
Intercom contact.created webhook
↓
Your serverless function, API route, or worker
↓
Volanea REST API
↓
Recipient inbox
The middleware is not optional ceremony. It is the security and reliability boundary. Intercom sends an HTTP notification to your URL, but it cannot safely hold your Volanea sending credentials as a reusable secret that is exposed to browser users or embedded in a client application. Your server receives the event, verifies it, maps approved fields into an email request, and reads the Volanea key from an environment secret.
A serverless route is often enough for low-to-medium volume. Examples include an API route in a web application, an edge-compatible worker where the cryptographic verification model fits, or a queue-consuming service. At higher volume, a durable queue is usually safer: acknowledge the valid webhook quickly, enqueue a job keyed by the Intercom event or contact ID, then have a worker send the email with controlled retries.
A simple decision model
For every webhook, decide in this order:
- Is it authentic? Reject or ignore anything that does not pass Intercom verification.
- Is it relevant? Ignore topics your endpoint does not support.
- Is it actionable? Skip contacts with no recipient, no consent, or an excluded lifecycle state.
- Has it happened before? Use an idempotency record before sending.
- What should be sent? Select an approved sender, subject, and template.
- Did Volanea accept the request? Record the provider message identifier and response outcome.
This sequence is intentionally conservative. A missing email address should cause a controlled skip with structured logging, not a JavaScript exception. A duplicate Intercom delivery should be acknowledged without producing a second welcome email. A transient Volanea error should be retried according to your job policy, not by blindly rerunning the entire webhook handler.
Working Node.js example: map the webhook to a Volanea email
The following Express example demonstrates the critical field mapping. It uses the contact.created envelope, requires a contact email, derives a safe display name, and makes a server-side Volanea REST request.
The Volanea API key is read from process.env.VOLANEA_API_KEY. The endpoint and payload below use Volanea’s REST email-send pattern: a POST request to /v1/emails with Bearer authentication, a verified from address, a recipient list, and message content. Review the Volanea API setup guides before deploying so your sending domain and environment variables match your account configuration.
import express from "express";
const app = express();
// Preserve raw bytes when implementing Intercom signature verification.
// The exact verification method should follow Intercom's current webhook docs.
app.use("/webhooks/intercom", express.json());
const alreadyProcessed = new Set(); // Replace with Redis or a database in production.
app.post("/webhooks/intercom", async (req, res) => {
const event = req.body;
// 1. Verify the webhook signature before trusting event data.
// verifyIntercomWebhook(req) should use Intercom's documented signing method.
// if (!verifyIntercomWebhook(req)) return res.status(401).send("Invalid signature");
// 2. Accept only the event this route is built to process.
if (event?.type !== "notification_event" || event?.topic !== "contact.created") {
return res.status(204).end();
}
const contact = event.data;
const recipient = contact?.email?.trim().toLowerCase();
// 3. A contact record does not guarantee an email address.
if (!recipient) {
console.info("Skipping Intercom contact without email", {
contactId: contact?.id,
topic: event.topic
});
return res.status(204).end();
}
// Use an event-level identifier if supplied by your Intercom webhook version.
// This fallback is deterministic for this event/contact combination but should
// be replaced with a durable event ID when available.
const idempotencyKey = `${event.topic}:${contact.id}:${event.created_at}`;
if (alreadyProcessed.has(idempotencyKey)) {
return res.status(204).end();
}
const firstName = contact?.name?.trim().split(/\s+/)[0] || "there";
// Field mapping:
// Intercom data.email -> Volanea to[0].email
// Intercom data.name -> personalized HTML/text content
// Intercom data.id -> metadata.intercom_contact_id
// Intercom external_id -> metadata.intercom_external_id
const emailPayload = {
from: {
email: "hello@example.com",
name: "Example Team"
},
to: [
{
email: recipient,
name: contact?.name || undefined
}
],
subject: "Welcome to Example",
html: `<p>Hi ${escapeHtml(firstName)},</p><p>Thanks for joining Example. Your account is ready.</p>`,
text: `Hi ${firstName},\n\nThanks for joining Example. Your account is ready.`,
metadata: {
intercom_contact_id: contact.id,
intercom_external_id: contact.external_id || "",
intercom_topic: event.topic
}
};
const volaneaResponse = await fetch("https://api.volanea.com/v1/emails", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify(emailPayload)
});
if (!volaneaResponse.ok) {
const errorBody = await volaneaResponse.text();
console.error("Volanea email send failed", {
status: volaneaResponse.status,
contactId: contact.id,
errorBody
});
// Return a retryable failure only if your idempotency design is durable.
return res.status(500).send("Email send failed");
}
const result = await volaneaResponse.json();
alreadyProcessed.add(idempotencyKey);
console.info("Volanea email accepted", {
contactId: contact.id,
idempotencyKey,
messageId: result.id
});
return res.status(202).json({ accepted: true });
});
function escapeHtml(value) {
return value.replace(/[&<>'"]/g, (character) => ({
"&": "&",
"<": "<",
">": ">",
"'": "'",
"\"": """
})[character]);
}
The in-memory Set is only a teaching aid. It is not sufficient for production because a server restart, a second server instance, or a deployment can erase it. Use a durable store with a unique constraint on the idempotency key. Record a state such as processing, sent, or failed, plus the Volanea response ID and timestamps.
Also note the escapeHtml call. Customer-controlled values must never be concatenated into HTML without escaping. Even a name field can contain unexpected markup. If you use Volanea templates instead of inline HTML, pass customer data as supported template variables and make sure the template engine escapes values appropriately.
Keep the Volanea API key out of Intercom and out of the client
The Volanea API key belongs in a server-side secret store, not in a client-visible configuration value and not in a public Intercom payload. In this architecture, Intercom does not need the Volanea key at all. It only needs the URL for your webhook receiver.
Store the key in the secret mechanism provided by your hosting platform, such as encrypted environment variables, a cloud secret manager, or a dedicated application configuration service. Your webhook handler reads it at runtime as VOLANEA_API_KEY. Restrict access so only the service that sends email can read it.
Never place the key in any of the following locations:
- Frontend JavaScript, mobile application bundles, browser extension code, or HTML source.
- An Intercom custom attribute, contact note, conversation content, or workflow text field.
- A public Git repository, sample request pasted into a support ticket, or unredacted application log.
- A webhook URL query parameter, where reverse proxies and monitoring tools may record it.
- A no-code client configuration that can be viewed by workspace users without appropriate secret controls.
A leaked sending key can allow unauthorized mail generation, damage sender reputation, expose campaign content, and create avoidable cost. Rotate the key if it is ever exposed, then audit request logs and sending activity around the exposure window.
Authenticate both directions
There are two separate trust relationships:
- Intercom to your endpoint: verify that the incoming webhook really originated from Intercom using its documented webhook-signature process and signing secret.
- Your endpoint to Volanea: authenticate the outgoing API request with your Volanea API key over HTTPS.
Do not substitute a guessable shared URL for signature verification. An endpoint path like /webhooks/intercom/secret-word is not a robust security control by itself. Likewise, do not trust an email value simply because it arrived in JSON; signature validation establishes the origin of the event, while your business rules establish whether a send should occur.
Make the email content transactional and deliberate
A contact.created trigger can be tempting because it is easy to wire up, but it is also broad. The message should match why the contact was created. A true account-verification email is transactional. A generic product newsletter is marketing and usually needs a different consent and preference model.
A good initial message is short, expected, and useful. For example, if your application creates an Intercom contact after a completed signup, send a message confirming that signup and providing the next action. Include an account or support path that the user can recognize.
Recommended sender and content choices
Use a verified domain and a sender identity that matches your product. Keep the subject specific, avoid unnecessary tracking language, and supply both HTML and text versions. The plain-text version is not an afterthought: it improves accessibility and gives recipients a readable fallback where HTML is limited.
Avoid passing every Intercom field into the message. Send only fields needed for the email. That reduces privacy exposure, prevents accidental disclosure of internal metadata, and makes it easier to reason about what is being sent. For many welcome messages, the recipient address, a first name, and an account-specific action URL are enough.
If you need to check an address before a nonessential follow-up, use an address-quality step in your own workflow. For one-off testing and cleanup, Volanea also provides a free email address verification tool. Verification is not a substitute for consent, and it should not be used to justify sending messages that a recipient did not expect.
Prevent duplicate sends and timeout failures
Webhooks are commonly delivered with at-least-once behavior. That means your endpoint must be prepared to receive a notification more than once. Intercom can retry when it does not receive a timely successful response, and network failures can leave your service uncertain whether Volanea accepted a request before the connection dropped.
Without idempotency, the result is familiar and damaging: one new contact receives two or three welcome emails. The failure may not appear in development because local requests are fast and single-threaded, but it emerges under real network conditions, deploys, queue retries, and provider latency.
Use a durable idempotency record
Create a durable unique key before sending. The best key is a stable event identifier supplied by the webhook, when available. If your event format does not provide one, compose a key from immutable fields that describe the exact event, such as topic, contact ID, and event timestamp. Store it in a database table with a unique constraint.
A robust lifecycle looks like this:
- Receive and authenticate the webhook.
- Attempt to insert the idempotency key with a
processingstate. - If the key already exists as
sent, return success without sending again. - Send through Volanea or enqueue a job.
- Store the Volanea message identifier and mark the event
sent. - If the send fails before acceptance, mark a retryable failure and let the job system retry under a bounded policy.
The atomic insert matters. A simple “check whether it exists, then send” pattern can race when two webhook deliveries reach separate application instances at nearly the same moment.
Respond quickly, then do slow work safely
Your endpoint should not spend a long time rendering templates, calling multiple databases, or waiting on unrelated APIs before acknowledging Intercom. If your infrastructure makes this likely, write the authenticated event to a queue or database first, return a success response promptly, and let a worker perform the Volanea request.
The queue worker should still use idempotency. Queues also commonly provide at-least-once delivery. They improve resilience and throughput, but they do not eliminate the need to make sends safe to repeat.
When this breaks
Every integration needs an operational plan for the specific failure modes between Intercom, your webhook receiver, and Volanea. The following issues are the ones most likely to matter in this hop.
Intercom retries and duplicate messages
If Intercom does not receive a timely successful HTTP response, it may retry delivery. A retry can happen even if your code already reached Volanea but the response to Intercom was interrupted. This is why the idempotency record must be created before—or atomically with—the send workflow, and why the Volanea response ID should be stored after acceptance.
Do not solve this by returning success before you have stored the event anywhere. If the process crashes after the acknowledgement and before the send is queued, the contact may never receive the message. Durable acceptance is the balance: persist or enqueue first, acknowledge second, send third.
Webhook timeout or unavailable endpoint
A slow database migration, cold start, overloaded worker, DNS issue, expired TLS certificate, or deployment outage can make your endpoint unavailable. Monitor HTTP error rates, response latency, and webhook authentication failures separately from Volanea delivery outcomes.
Use alerting that tells you which hop failed. “Welcome email did not arrive” is too broad to troubleshoot quickly. Better logs capture the Intercom topic, contact ID, idempotency key, webhook receipt time, Volanea HTTP status, and returned message ID, while redacting recipient addresses and secrets where possible.
Missing payload fields
Do not assume every contact-created event contains the same populated fields. Contacts can differ by role, source, identity state, workspace configuration, and the Intercom capabilities available to the workspace. An email, name, or external_id that appears during your test may be missing in a live event.
Handle this explicitly. If email is absent, skip the transactional send and record a structured reason. If external_id is absent, do not fail a message that only needs the email; leave that metadata empty. If a required business field is not included in the event, fetch or look up the record server-side rather than inventing a default.
Volanea rejects the request
A non-success response from Volanea can indicate an invalid sender identity, malformed recipient, invalid request body, authentication issue, account policy issue, or a temporary service condition. Log the HTTP status and a sanitized error body. Classify validation errors as non-retryable, but treat transient server or network errors according to a bounded retry policy with backoff.
Do not retry an invalid recipient indefinitely. Repeated attempts waste capacity and can conceal an upstream data issue. For operational messages, route failures into an exception workflow that lets a team correct the contact record or investigate the underlying event.
The contact should not have received the message
This is a business-logic failure, not an API failure. It often happens when a contact is created before signup completes, when imported contacts are treated as newly registered users, or when consent is not checked. Fix it by tightening the event choice or adding an application-state gate.
For example, you might require contact.created and a matching application user with signup_completed_at present. If that state is only known later, use a more appropriate Intercom event or have your application initiate the transactional send directly after the completed action. Webhooks should reflect the lifecycle you actually mean, not merely the earliest event that is easy to subscribe to.
Alternatives when a direct webhook is not suitable
A native Intercom webhook plus middleware is the most controllable route, but it is not the only architecture. The right choice depends on how much transformation, ownership, and operational reliability you need.
Direct webhook plus your service
Choose this when email is product-critical, when you need custom authorization or data enrichment, or when you want durable idempotency and structured observability. It gives you the clearest audit trail and avoids putting the Volanea key into a broadly visible configuration surface.
The tradeoff is that you operate a small endpoint or worker. In practice, this is usually modest engineering work, especially if you already have a serverless platform or application backend.
Intercom webhook plus a workflow automation service
A middleware service such as Zapier or Make can receive an Intercom trigger and call an HTTP endpoint. This can be useful for prototypes or internal notifications, but check the service’s secret handling, retry behavior, data retention, task limits, and error visibility before using it for customer-facing transactional mail.
The safest pattern remains: have the automation service call your authenticated endpoint, then have your endpoint call Volanea. If you configure Volanea credentials in a third-party automation tool, restrict access carefully and understand who can view, edit, export, or clone the automation.
Send from your application instead
For account verification, password flows, receipts, and other actions initiated in your own product, sending directly from the application is often better than waiting for a CRM event. Your application already knows the completed action, consent state, recipient, and account context. Intercom can still receive the resulting lifecycle event for customer communication and support.
This is not a failure of the Intercom integration. It is a matter of choosing the system that owns the event as the sender trigger. Use Intercom webhooks when Intercom is the authoritative event source; use your product backend when your product is.
Test the full path before enabling it for all contacts
Testing should include more than confirming that one email appears in your inbox. You need to test event filtering, security, missing data, retries, and duplicate handling.
Use a controlled Intercom contact and send it through a non-production Volanea environment or a clearly labeled test sender where available. Confirm that the receiver gets the expected subject and content, then inspect the stored idempotency record and Volanea response ID.
A practical test checklist is:
- Create a contact with a valid email and confirm one email is accepted.
- Create a contact with no email and confirm the event is skipped cleanly.
- Replay the same webhook payload and confirm no second email is sent.
- Simulate a Volanea temporary failure and confirm the event is retried safely.
- Send a payload with HTML-like characters in the name and confirm content is escaped.
- Verify that logs contain no Volanea API key and do not unnecessarily expose recipient PII.
- Confirm that an unverified or invalid webhook request is rejected before it reaches Volanea.
Keep a test endpoint and a production endpoint separate. This prevents a developer experimenting with a webhook subscription from accidentally triggering real customer mail. It also makes it easier to evolve templates, event policies, and observability without changing a live path in place.
Conclusion
To send email from Intercom with Volanea, use Intercom’s contact.created webhook as the trigger and route it through server-side middleware that you control. The middleware verifies the inbound event, handles optional contact fields, applies your sending rules, prevents duplicate processing, and calls Volanea with a protected API key.
The key design decision is not the HTTP request itself. It is treating the webhook as an at-least-once event source and building a durable boundary between customer-data events and email delivery. With verification, idempotency, explicit consent checks, and useful logs, the connection becomes a dependable part of your customer lifecycle rather than a fragile automation.
FAQ
Can I install Volanea from the Intercom Marketplace?
No. Volanea does not ship a native Intercom Marketplace app or plugin for this workflow. Use an Intercom webhook that calls a secure endpoint you operate, then send through Volanea from that server-side endpoint.
What Intercom event should trigger the email?
This guide uses the contact.created webhook topic. It is appropriate for a welcome or lifecycle message only when creation of the contact truly represents the business event you want. If signup completion happens later in your application, use that later application event or add a server-side eligibility check.
Where do I put the Volanea API key?
Put it in your server or serverless platform’s encrypted environment variables or secret manager. Intercom should only know your webhook destination URL; it should not contain the Volanea key, and the key must never be included in frontend code or client-visible configuration.
How do I stop duplicate welcome emails?
Use a durable idempotency key for every webhook event and store the send state in a database or queue-backed job system. If Intercom retries the same event, detect the existing key and return success without issuing another Volanea send.
What if the Intercom webhook does not include an email address?
Skip the send safely and log the contact ID and reason. Do not construct a recipient from an unrelated field. If the email is required for the workflow, look up your authoritative application record using a stable contact identifier, or choose a later event that guarantees the needed data.