Send email from ManyContacts without exposing an email API key by using ManyContacts’ Zapier integration as the trigger layer and a small server-side relay as the sending layer. This pattern turns a new ManyContacts contact into a personalized transactional email through Volanea while keeping consent checks, duplicate protection, and deliverability controls in the right places.
ManyContacts does not offer a native Volanea app, marketplace listing, or one-click email-provider connection. It does, however, offer API/webhook capabilities and integrations through Zapier and Make. For this use case, Zapier is the clearest documented route because its ManyContacts connector includes a Contact Created trigger and can pass that contact data to your own HTTPS endpoint.
The architecture is intentionally simple:
- A person becomes a new contact in ManyContacts.
- Zapier detects the Contact Created event from ManyContacts.
- Zapier sends only the fields needed for email to your private relay endpoint.
- Your relay validates the request, applies eligibility rules, and calls Volanea’s
POST /v1/sendendpoint. - Volanea queues the email and records the resulting send activity for delivery investigation.
The relay is not needless complexity. It is the boundary that prevents a Volanea secret key from being visible in a browser, a public form, a client-side automation, or a broadly accessible Zap configuration. It also gives you one place to make consent decisions, validate an address, normalize data, and make retries safe.
What starts the email in ManyContacts
The concrete trigger for this integration is Contact Created in the ManyContacts app on Zapier. Zapier describes the trigger as running when a new contact is created in ManyContacts. It is a polling trigger, meaning Zapier checks ManyContacts for newly created records rather than receiving a direct push for every event.
That distinction matters operationally. A newly created record is not necessarily the same thing as a newly qualified lead, an email opt-in, or a customer who expects a message. In ManyContacts, a contact may be created automatically when somebody starts a WhatsApp conversation, when a team member adds someone manually, or when another connected workflow creates or updates the contact.
For that reason, treat Contact Created as the technical event that begins evaluation—not as automatic permission to send marketing email.
The recommended trigger rule
Use this rule for the first version of the workflow:
When ManyContacts creates a contact, send a transactional acknowledgement only if the record has a valid email address and your business has a documented reason and permission to email that person.
A suitable email might be:
- A requested quote or appointment confirmation.
- A copy of information the person asked for in WhatsApp.
- A welcome or onboarding message after an explicit sign-up.
- A receipt, order update, or support follow-up connected to an existing transaction.
It is not a good fit for automatically adding every new WhatsApp contact to a promotional email sequence. WhatsApp contact creation and email marketing consent are separate facts. Keep that distinction in your relay logic and in your internal operating process.
Why use Zapier and a relay instead of a direct Volanea call
ManyContacts documents API and webhook support, as well as connectors for Zapier and Make. However, a direct integration should not put a Volanea secret key into a front-end workflow, public webhook URL, embedded form, or configuration that non-developers can inspect or copy.
Zapier can trigger the workflow, but it should not be the long-term home for a broad-scope sending secret. The safer arrangement is:
ManyContacts contact created
↓
Zapier trigger and field mapping
↓
HTTPS POST to your relay
↓
Volanea POST /v1/send
The relay can be a small Node.js application, a serverless function, a Cloudflare Worker, an AWS Lambda function, or an endpoint in an existing application. It should have two separate secrets:
INBOUND_WEBHOOK_SECRET: authenticates Zapier to the relay.VOLANEA_API_KEY: authenticates the relay to Volanea.
The Volanea key lives only in the relay’s encrypted server-side environment variables or secret manager. It does not live in ManyContacts. It should also not be inserted into a Zapier request header if your goal is to limit who can view or reuse the credential.
This separation gives you practical security benefits. A staff member can edit the message mapping in Zapier without gaining the ability to send arbitrary email through your Volanea account. If the Zap is copied, exported, or shown in a screen share, the Volanea secret remains outside it. If you rotate your Volanea key, you update one secret in the relay rather than every automation that sends mail.
For Volanea setup, create a secret API key, verify the domain you will use in the from address, and use a sender address on that verified domain. Review the email API reference and setup guides before deploying the relay, especially if you plan to use templates, attachments, scheduling, or delivery webhooks.
The contact data to map from ManyContacts
The ManyContacts Zapier trigger is Contact Created. In Zapier’s test step, inspect the real sample record from your account before publishing the automation. ManyContacts contact data commonly exposes contact attributes such as an identifier, name, email, phone number, and notes through its integration actions and API model, but the exact fields available in a trigger sample can differ based on how the contact was created and which fields your team has populated.
Do not rely on phone number as a substitute for email. ManyContacts is primarily a WhatsApp-oriented contact platform, so new contacts can exist with no email address at all. An email workflow must gracefully skip those records rather than attempt to create an address from a name, phone number, or guessed company domain.
Normalize the Zapier payload yourself
Instead of forwarding the entire trigger output, map a small normalized object in Zapier’s Webhooks by Zapier action. This is the payload your relay should receive:
{
"event": "manycontacts.contact.created",
"contactId": "{{ManyContacts Contact ID}}",
"name": "{{ManyContacts Contact Name}}",
"email": "{{ManyContacts Contact Email}}",
"phone": "{{ManyContacts Phone Number}}",
"notes": "{{ManyContacts Contact Notes}}",
"createdAt": "{{zap_meta_timestamp}}"
}
The values in double braces are Zapier field selections, not literal text to send. In the action editor, select the matching values from the Contact Created test record. The labels in your Zap can vary, so use the test-data picker instead of typing assumed field tokens.
The important part is the stable shape that your relay receives: contactId, name, email, phone, notes, and an event timestamp. This gives your code a small, documented interface even if ManyContacts or Zapier later adds more fields to its raw trigger output.
Field mapping to the email
For a simple contact acknowledgement, map fields as follows:
| ManyContacts/Zapier field | Relay field | Volanea email use |
|---|---|---|
| Contact ID | contactId | Stable idempotency key component and audit correlation |
| Contact Name | name | Greeting and template personalization |
| Contact Email | email | Recipient address in to |
| Phone Number | phone | Optional reference in internal logs; do not expose unnecessarily |
| Contact Notes | notes | Optional context only after reviewing for sensitive data |
| Zap timestamp | createdAt | Event logging and troubleshooting |
Avoid automatically putting contact notes into an email. Notes can contain internal commentary, sales details, unstructured conversation summaries, or sensitive information that should never leave your organization. Use notes as internal context only, and only if your privacy and access controls allow it.
Build the Zapier workflow
Create one Zap with three logical stages: detect, filter, and relay.
Step 1: Choose the ManyContacts trigger
- Create a new Zap.
- Select ManyContacts as the trigger app.
- Select Contact Created as the trigger event.
- Connect the ManyContacts account requested by Zapier.
- Test the trigger with a recently created contact that has a real test email address.
Because this is a polling trigger, test timing can differ from production timing. Zapier notes that its free plan checks polling triggers every 15 minutes. If the acknowledgement must happen immediately—for example, a time-sensitive appointment confirmation—evaluate whether the workflow can instead originate from a system that supports an instant event, or use ManyContacts’ documented webhook/API capabilities with a custom integration after confirming the available event and payload contract for your account.
Step 2: Add eligibility filters
Add a Zapier Filter step before anything reaches your server. At minimum, require:
- The email field exists.
- The email field contains
@. - The contact is not a known test or internal address, if applicable.
These filters reduce useless relay calls, but they do not replace server-side validation. A field containing name@example may pass a simplistic check and still be invalid. Your relay remains the policy enforcement point.
If your team uses tags, stages, or custom fields to record email permission, add a filter for that state as well. Do not infer consent from a WhatsApp conversation alone. If your ManyContacts trigger sample does not include the necessary field, use a separate system of record for consent or have the relay query your own CRM before sending.
Step 3: Send the normalized request to your relay
Use Webhooks by Zapier and choose its custom request action. Configure it as:
Method: POST
URL: https://your-app.example.com/webhooks/manycontacts/contact-created
Data Pass-Through: No
Payload Type: json
Send the normalized JSON object shown earlier. Add a request header that proves the request came from your automation:
X-Integration-Secret: {{your private shared secret}}
Content-Type: application/json
The shared secret is not the Volanea API key. It is a separate random value used only by this Zap and your relay. Store it in the Zapier action’s private configuration as tightly as your team’s permissions allow, rotate it if access changes, and reject every request that does not present the expected value.
A URL path that includes a long unpredictable secret can be an additional layer, but it is not a replacement for checking a header. URLs get copied into logs, browser history, monitoring tools, and support tickets more easily than most teams expect.
Working relay code: ManyContacts data to Volanea email
The following Node.js example accepts the normalized Zapier request and converts it into a Volanea send request. It validates the incoming secret, requires a usable email address, derives a deterministic idempotency key from the ManyContacts contact ID, and sends both HTML and plain-text content.
This is deliberately written as a server-side Express handler. Put VOLANEA_API_KEY and INBOUND_WEBHOOK_SECRET in your hosting provider’s encrypted environment-variable or secret-management system; never commit them to source control.
import crypto from "node:crypto";
import express from "express";
const app = express();
app.use(express.json({ limit: "100kb" }));
const {
INBOUND_WEBHOOK_SECRET,
VOLANEA_API_KEY,
VOLANEA_FROM_EMAIL = "hello@example.com",
VOLANEA_FROM_NAME = "Example Company"
} = process.env;
function sameSecret(received, expected) {
if (!received || !expected) return false;
const receivedBuffer = Buffer.from(received);
const expectedBuffer = Buffer.from(expected);
return receivedBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(receivedBuffer, expectedBuffer);
}
function validEmail(value) {
return typeof value === "string" &&
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
}
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
app.post("/webhooks/manycontacts/contact-created", async (req, res) => {
const inboundSecret = req.get("X-Integration-Secret");
if (!sameSecret(inboundSecret, INBOUND_WEBHOOK_SECRET)) {
return res.status(401).json({ error: "Unauthorized" });
}
const {
event,
contactId,
name,
email,
phone,
notes,
createdAt
} = req.body ?? {};
if (event !== "manycontacts.contact.created") {
return res.status(400).json({ error: "Unexpected event" });
}
if (!contactId || !validEmail(email)) {
// Return 200 for a deliberately skipped contact so the automation
// does not keep retrying an address that cannot be sent to.
return res.status(200).json({
status: "skipped",
reason: "missing_contact_id_or_valid_email"
});
}
// Add your business-specific consent or CRM lookup here before sending.
// Do not use the presence of a WhatsApp contact as email consent.
const firstName = String(name || "there").trim().split(/\s+/)[0] || "there";
const idempotencyKey = `manycontacts-contact-created-${contactId}`;
const emailPayload = {
from: {
email: VOLANEA_FROM_EMAIL,
name: VOLANEA_FROM_NAME
},
to: [{
email: email.trim(),
name: String(name || "").trim() || undefined
}],
subject: `Thanks for contacting ${VOLANEA_FROM_NAME}`,
html: `
<p>Hi ${escapeHtml(firstName)},</p>
<p>Thanks for getting in touch. We received your details and will follow up shortly.</p>
<p>If you did not expect this message, you can reply to let us know.</p>
`,
text: `Hi ${firstName},\n\nThanks for getting in touch. We received your details and will follow up shortly.\n\nIf you did not expect this message, reply to let us know.`,
metadata: {
source: "manycontacts",
event,
manycontactsContactId: String(contactId),
manycontactsPhone: String(phone || ""),
sourceCreatedAt: String(createdAt || "")
}
};
try {
const volaneaResponse = 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(emailPayload)
});
const responseBody = await volaneaResponse.json().catch(() => ({}));
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
contactId,
responseBody
});
return res.status(502).json({
error: "Email provider rejected the request",
providerStatus: volaneaResponse.status
});
}
console.info("Volanea email accepted", {
contactId,
providerResponse: responseBody,
notesPresent: Boolean(notes)
});
return res.status(200).json({
status: "accepted",
contactId,
providerResponse: responseBody
});
} catch (error) {
console.error("Volanea request error", {
contactId,
message: error instanceof Error ? error.message : "Unknown error"
});
return res.status(503).json({ error: "Email send temporarily unavailable" });
}
});
app.listen(process.env.PORT || 3000);
The Volanea call uses POST https://api.volanea.com/v1/send, a JSON request body, a secret key in the Authorization header, and an Idempotency-Key header. Volanea supports idempotency for send requests, which is essential when an upstream tool retries a request after a timeout or temporary failure.
The from.email domain must already be verified in Volanea. Use a real operational mailbox or a monitored reply address where appropriate. If you are building a production workflow with templates, replace the inline subject, html, and text fields with the applicable Volanea stored-template fields from the API reference. That makes copy changes safer and keeps presentation logic out of the relay.
Authentication and secret handling
This integration has three trust boundaries, and each needs different credentials.
ManyContacts authentication
Zapier connects to ManyContacts using the account connection requested by the ManyContacts Zapier integration. Keep access to the Zap limited to people who should be allowed to read contact data and edit automations.
ManyContacts’ own API documentation describes API keys under Settings → Developers, but that key is for calling ManyContacts programmatically. You do not need to put a ManyContacts API key in the Volanea relay for the basic Contact Created Zap flow.
Zapier-to-relay authentication
Use a dedicated X-Integration-Secret header. Your relay compares it in constant time and rejects requests that do not match. Do not use an easy-to-guess phrase, a company name, or the Volanea API key itself.
Generate a random secret, for example with a password manager or a cryptographic command-line tool. Treat it as a credential: restrict access, rotate it after staff or vendor changes, and do not paste it into tickets or code comments.
Relay-to-Volanea authentication
The Volanea secret key belongs only in the relay’s encrypted server-side environment. It must never sit in:
- ManyContacts custom fields or notes.
- A contact record.
- A public JavaScript application.
- An email template.
- A browser-accessible environment variable.
- A Zap field that general collaborators can view.
- A Git repository, deployment manifest, or screenshot.
This is especially important because a sending key can be abused to send mail from your verified domain. Keeping the key at the server boundary also allows you to set policy before every send, rather than giving a third-party workflow unrestricted provider access.
Prevent duplicate emails with idempotency
A workflow can create duplicates even when every individual system is working as designed. Zapier can retry a webhook action after a network problem. Your relay can call Volanea successfully but fail before its response reaches Zapier. A user can create duplicate contacts. An automation can be turned off and back on while historical items are still eligible for processing.
The right defense is a stable idempotency key tied to the business event. In the sample code, this is:
manycontacts-contact-created-{contactId}
That means all attempts to send the acknowledgement for the same ManyContacts contact-created event use the same key. If Zapier makes the same request again, Volanea can recognize it as a safe retry instead of accepting a second independent email.
Do not use the current timestamp or a random UUID as the idempotency key. Those values change on every attempt and therefore guarantee that retries look like new sends.
When one contact can legitimately receive more than one email
A contact ID alone is not always enough. If your workflow will send different event-driven emails to the same person, include an event category and stable event identifier:
manycontacts-{contactId}-quote-request-{quoteId}
manycontacts-{contactId}-appointment-confirmed-{appointmentId}
manycontacts-{contactId}-onboarding-complete-{workflowRunId}
The rule is simple: the same real-world event should always produce the same key; different legitimate events should produce different keys.
When this breaks
Every integration eventually encounters missing fields, delayed events, retries, or external API failures. Design the ManyContacts-to-Zapier-to-relay hop as a failure-prone distributed workflow rather than a single guaranteed transaction.
Zapier retries after the relay has already sent the email
This is the most common duplicate-send scenario. Imagine the relay calls Volanea, Volanea accepts the request, and then the relay response is interrupted by a network timeout. Zapier sees a failed action and retries. Without idempotency, the customer receives the same email twice.
Use the stable Idempotency-Key header on every Volanea send. Also log the ManyContacts contact ID, the calculated key, the Volanea response status, and the returned provider message identifier where available. Those details let support staff distinguish a duplicate trigger from an attempted retry.
The relay times out or returns a non-2xx response
Keep the relay quick. Validate the request, perform only necessary lookups, send the email, and return a response. Do not make the request wait on slow enrichment, CRM synchronization, analytics calls, or unrelated database work.
If an email is truly not accepted by Volanea because of a temporary provider or network error, return a 5xx status from the relay. That tells the upstream automation that the attempt was not completed. If the contact is ineligible—such as missing a valid email—return a successful response with status: "skipped" so an automation retry does not repeatedly process a record that will never qualify.
The contact has no email address
ManyContacts contact creation does not guarantee an email field. A WhatsApp lead may give only a phone number and a display name. Your relay should skip the contact and record a non-sensitive reason rather than attempt a send.
Do not manufacture an address, scrape one from notes, or assume a phone number identifies an email mailbox. If collecting email is important to your workflow, ask for it through an approved conversation or form and record explicit permission alongside it.
Fields are missing or differ by plan, connection, or record source
ManyContacts supports different integration paths, and the fields in a Zapier sample may vary depending on the contact source and account setup. A contact created by a human may contain a full name and email; one created from an inbound WhatsApp conversation may not. Custom fields, tags, stages, and notes may not all appear in the trigger data you expected.
Make the relay defensive:
- Require only fields that are essential to the exact email being sent.
- Use safe defaults for optional personalization, such as
thereinstead of a missing first name. - Skip rather than fail when an email address is absent.
- Fail clearly when the event type or contact identifier is absent.
- Capture a redacted event schema in staging whenever you change your ManyContacts or Zapier configuration.
A workflow that assumes every field exists will fail unpredictably as your team starts creating contacts through more channels.
The ManyContacts Contact Created trigger is delayed
Because the documented Zapier trigger is polling, its execution timing depends on the plan and polling schedule. On Zapier’s free plan, polling can be every 15 minutes. That is fine for a non-urgent acknowledgement, but it is a poor fit for a message that must arrive seconds after an action.
If immediacy is a hard requirement, validate whether your ManyContacts account’s webhook configuration can deliver the specific event you need, confirm the live payload in a test environment, and point that webhook at the same relay. Do not switch to a direct webhook merely because it sounds faster; verify event selection, payload format, authentication options, retry behavior, and any plan limitations first.
Volanea accepts the request but the message is not delivered
A successful send API response means the message was accepted for processing; it is not proof that the recipient saw it. Delivery can still be affected by a suppression, an unsubscribe state, a bounce, a complaint, recipient-server rejection, or mailbox filtering.
Use Volanea’s email activity and delivery event tooling to investigate messages by recipient and provider message data. Configure your sending domain correctly, use a legitimate and recognizable sender identity, include a plain-text alternative, and keep the content aligned with what the recipient expects after the ManyContacts interaction.
Testing before you publish
Test the full path with a controlled address before enabling the Zap for real contacts. Do not begin with a public WhatsApp lead or a large imported audience.
Use this checklist:
- Verify the Volanea sending domain and sender address.
- Deploy the relay with production secrets stored outside source code.
- Call the relay manually with a test payload and an invalid secret; confirm it returns
401. - Call the relay with a valid secret but no email; confirm it returns
200withskipped. - Call it with a valid test email and contact ID; confirm Volanea accepts exactly one message.
- Send the identical request again; confirm the idempotency behavior prevents an additional independent send.
- Create a new test contact in ManyContacts and inspect the Zapier test data.
- Confirm the final email uses the expected name, sender, subject, and content.
- Review logs to ensure phone numbers, notes, and other unnecessary personal data are not being written broadly.
- Document who owns the Zap, the relay deployment, the secrets, and the domain configuration.
A useful final test is to deliberately cause Volanea to reject the request in a staging environment—for example, by using an unverified sender during setup—then confirm the relay logs a clear error and Zapier exposes a failed action that your team can diagnose.
Choosing a template versus inline content
The example uses inline HTML because it shows the field mapping clearly. In production, a stored Volanea template is often easier to manage when non-developers need to update copy, branding, or localization.
Use inline content when:
- The message is small and highly event-specific.
- The developer team owns all copy changes.
- You need to ship a quick, tightly controlled transactional flow.
Use a stored template when:
- Marketing, support, or operations needs to edit content safely.
- The same message is reused across multiple systems.
- You need consistent branding and reusable variables.
- You expect localized versions or multiple customer segments.
Whichever option you choose, keep the decision about whether to send in the relay. Templates make emails easier to maintain; they should not become a bypass around consent checks, address validation, or duplicate prevention.
If you are estimating operational volume before deployment, review transactional email pricing alongside your expected contact-creation rate, retry patterns, and any separate campaign activity. A contact-created acknowledgement is usually a low-volume transactional use case, but cost and throughput planning should still account for growth and accidental automation loops.
Practical privacy and deliverability implications
This integration connects a messaging CRM with email infrastructure, so data minimization matters. Send Volanea only what the email requires. For a basic acknowledgement, that is usually an address, a name, and a reference identifier—not every phone number, note, tag, conversation detail, or custom field stored in ManyContacts.
Set a clear data-retention approach for relay logs. Log event IDs, timestamps, status codes, and provider identifiers. Avoid logging raw message bodies, complete notes, or full contact payloads unless there is a narrowly defined support need and appropriate access control.
Deliverability is also shaped by message relevance. A contact who has just spoken to your team on WhatsApp may expect a requested confirmation by email; that is a coherent cross-channel experience. A person who merely initiated a chat may not expect promotional mail. The difference affects complaints, engagement, brand trust, and long-term mailbox placement.
Keep the first automated email unmistakably connected to the action that caused it. State why the recipient is receiving it, use a recognizable sender, and provide a human support path. For non-transactional or promotional content, use your normal permission and unsubscribe process rather than extending this contact-created event into a marketing trigger.
Conclusion
To send email from ManyContacts with Volanea, use the documented Contact Created ManyContacts trigger in Zapier, normalize the contact fields, and post them to a private server-side relay. The relay should validate the request, require a legitimate email address and your own eligibility rules, create a stable idempotency key from the ManyContacts contact ID, and call Volanea’s POST /v1/send endpoint with a verified sender.
This approach is more reliable than placing a provider key directly in an automation and more maintainable than tying email content to unstructured contact notes. It gives your team a controlled place to handle authentication, retries, privacy, consent, observability, and future changes to ManyContacts fields or workflow logic.
FAQ
Can I connect ManyContacts directly to Volanea?
There is no native ManyContacts-to-Volanea app or marketplace plugin to install. ManyContacts supports API, webhooks, Zapier, and Make integrations, but the safe production design is to use an automation layer and a server-side relay that holds the Volanea secret key.
What ManyContacts event should trigger the email?
Use Contact Created in the ManyContacts Zapier connector for a basic new-contact acknowledgement. Add eligibility checks because a new WhatsApp contact does not automatically mean the person has given permission for promotional email.
Where should I store the Volanea API key?
Store it only in the relay’s encrypted server-side environment variables or secret manager. Do not store it in ManyContacts, a contact field, browser code, an email template, or a broadly visible Zap configuration.
How do I stop Zapier retries from sending duplicate emails?
Create a stable Idempotency-Key from the contact ID and the event type, then pass it on every POST /v1/send request. The same event must always use the same key.
What happens if a ManyContacts contact has no email address?
Skip the email safely and log a minimal reason. Do not guess an address from a phone number, name, or contact notes. Collect an email address and appropriate permission through an approved process before sending.