Send transactional email from WPForms without relying on a native plugin integration: configure WPForms to send a webhook when a form is submitted, receive that request in a small server-side endpoint, and have that endpoint call Volanea’s REST API. This pattern keeps your Volanea secret key out of form fields and gives you control over validation, duplicate prevention, and the final email content.
There is no native Volanea app or one-click WPForms integration to install. That is not a limitation you need to work around with an unofficial connector, though. WPForms includes a Webhooks addon designed for exactly this kind of custom connection: a submission can trigger an HTTP request to an endpoint you control. Your endpoint decides whether the submission should generate an email and, if it should, sends a properly authenticated request to Volanea.
This guide uses a contact-form confirmation as the working example. A visitor submits their name, email address, and message; WPForms posts those values to your webhook receiver; the receiver validates the data and sends the visitor a confirmation email through Volanea. The same architecture works for application forms, quote requests, downloads, support tickets, appointment requests, and form-driven receipts.
The honest WPForms-to-Volanea architecture
The integration has three pieces:
- WPForms collects and validates the visitor’s form submission.
- A webhook receiver you control accepts the POST request, verifies that it is expected, validates the payload, and builds safe email content.
- Volanea’s REST API accepts the email request and queues the transactional message for delivery.
The request flow looks like this:
Visitor submits WPForms form
↓
WPForms Webhooks addon sends HTTPS POST
↓
Your /webhooks/wpforms endpoint validates and maps data
↓
POST https://api.volanea.com/v1/send
↓
Volanea accepts the transactional email
It can be tempting to post directly from WPForms to Volanea’s send endpoint. WPForms can create custom outbound requests, but a direct setup requires placing a long-lived Volanea secret key in WordPress webhook configuration. That may be acceptable for a tightly controlled site, but it gives every administrator who can inspect that configuration access to a sending credential. It also leaves little room to validate a recipient, sanitize user-supplied content, record an audit trail, or safely handle retries.
A lightweight receiver is the more durable choice. It can run as a small Node.js service, a serverless function, a WordPress plugin endpoint, or an endpoint in an existing application. The receiver’s only job is to translate a trusted form event into a narrowly scoped transactional email request.
What you need before sending email
Prepare the form, sending domain, and server-side credentials before configuring the webhook.
WPForms requirements
WPForms documents the Webhooks addon as an Elite feature. In the form builder, webhook settings are available under Settings » Webhooks after the addon is installed and activated. The addon lets you choose an outbound request URL, request method, request format, body mappings, optional conditions, and more than one webhook configuration for a form.
If you do not have the Webhooks addon, WPForms also supports automation routes through services such as Zapier and Make. Those routes can work, but the native webhook route is generally the cleanest fit when you already have a backend endpoint and want to avoid routing form data and email credentials through an additional automation account.
Volanea requirements
You need a Volanea project, a secret API key, and a sending address on a verified sending domain. Keep the API key in a server-side environment variable, not in browser code, a form confirmation, a page builder, or a public repository.
Volanea’s single-message endpoint is:
POST https://api.volanea.com/v1/send
The request uses Authorization: Bearer <secret-key>, JSON content, and can include an Idempotency-Key header so an upstream retry does not generate another logical email. The send request includes a verified from address, recipient, subject, plain-text body, and HTML body. For endpoint details and current request options, consult the email API reference and setup guides.
Your webhook receiver requirements
Use an HTTPS endpoint that WPForms can reach publicly, such as:
https://api.example.com/webhooks/wpforms
The endpoint needs two secrets:
WPFORMS_WEBHOOK_SECRET: a high-entropy shared value used to authenticate the request from your WordPress site.VOLANEA_API_KEY: your Volanea secret key, stored only in the receiver environment.
You also need a verified sender address, such as hello@updates.example.com. Use an address on your own authenticated domain rather than a visitor’s submitted email address. Put the visitor’s address in the to field for an acknowledgement, or in replyTo only if your chosen send configuration supports the behavior you need and you have tested it.
Build the WPForms form for a transactional event
Start with a focused form. This example uses four fields:
| Form field | Suggested key in webhook body | Purpose |
|---|---|---|
| Name | name | Personalizes the response |
email | Recipient of the confirmation | |
| Paragraph Text / Message | message | Gives the visitor useful context |
| Hidden field or entry identifier | entry_id | Prevents duplicate confirmation emails |
Keep the content of your confirmation predictable. A contact form confirmation should confirm that the request was received, set an expectation for response time if appropriate, and optionally repeat a short, safely escaped version of the submitted message. It should not turn every free-form field into raw HTML or expose internal routing data.
Add a stable submission identifier
A stable event identifier matters because webhooks can be retried. A timeout can occur after WPForms has already submitted the request but before it receives a response. Without idempotency, a retry can lead to two confirmation emails.
WPForms assigns an Entry ID to stored form entries. WPForms’ developer documentation also provides a specific example for passing the entry ID through the Webhooks addon, because entry metadata is not necessarily included in a normal field mapping by default. Use that documented approach if you want the receiver to use the actual WPForms entry ID as the message event ID.
For this guide, the incoming body includes entry_id. The result is a deterministic Volanea idempotency key such as:
wpforms-contact-4821
The important property is stability: a retry for WPForms entry 4821 must reuse exactly the same idempotency key. Do not generate a fresh UUID inside the receiver for every request, because that turns a retry into a new send.
Configure the WPForms webhook
Open the form in the WPForms builder, then go to Settings » Webhooks. Enable webhooks and add a webhook configuration for the confirmation flow.
Use the following configuration as the baseline:
| Webhook setting | Value |
|---|---|
| Request URL | https://api.example.com/webhooks/wpforms |
| Request Method | POST |
| Request Format | JSON |
| Conditional Logic | Optional; use it to send only for forms that should create an email |
If your WPForms webhook settings include request headers, add a shared authentication header:
X-WPForms-Webhook-Secret: replace-with-a-long-random-secret
Use a random secret generated by a password manager or secret-management tool. This value is not a replacement for HTTPS, but it prevents arbitrary internet clients from successfully calling your receiver if they discover the endpoint URL.
The actual WPForms webhook payload shape
WPForms Webhooks does not impose one universal submission-event JSON envelope. Its outbound request body is the body you create by mapping parameter keys to fields in the form builder. In other words, the actual shape sent by WPForms is determined by the Request Body rows you configure.
For this guide, create these Request Body mappings:
| Parameter key | Map to |
|---|---|
form_id | A static value such as contact-form or your form identifier |
entry_id | Your configured entry ID value |
name | The Name field |
email | The Email field |
message | The Paragraph Text field |
With example visitor input, WPForms sends this JSON body to your receiver:
{
"form_id": "contact-form",
"entry_id": "4821",
"name": "Avery Jordan",
"email": "avery@example.net",
"message": "Could you send pricing for a 20-person team?"
}
That is the payload shape your endpoint should expect for this configuration. If you rename message to question, add a phone field, or remove form_id, the JSON changes accordingly. This is useful: you should map only the fields your email workflow actually needs instead of forwarding every field and piece of visitor metadata by default.
Before going live, submit a test form to a temporary inspection endpoint or use request logs from your receiver. Confirm the exact keys, data types, and values sent by your installed WPForms version and form configuration. Field labels and values are not interchangeable in every form setup, particularly for choice fields, so inspect a real test submission before assuming how a checkbox, dropdown, or address subfield will arrive.
Create the secure webhook receiver
The following Node.js example uses Express. It accepts the JSON payload configured above, checks the shared secret, validates the basic fields, escapes user-controlled values before placing them into HTML, and sends a confirmation email through Volanea.
Install Express:
npm install express
Set environment variables in your server or deployment platform:
export WPFORMS_WEBHOOK_SECRET="use-a-long-random-value"
export VOLANEA_API_KEY="sk_replace_with_your_secret_key"
export VOLANEA_FROM="Example Team <hello@updates.example.com>"
Create server.mjs:
import crypto from "node:crypto";
import express from "express";
const app = express();
app.use(express.json({ limit: "100kb" }));
const {
WPFORMS_WEBHOOK_SECRET,
VOLANEA_API_KEY,
VOLANEA_FROM,
} = process.env;
if (!WPFORMS_WEBHOOK_SECRET || !VOLANEA_API_KEY || !VOLANEA_FROM) {
throw new Error("Missing required environment variables");
}
function safeEqual(left, right) {
const leftBuffer = Buffer.from(left || "");
const rightBuffer = Buffer.from(right || "");
return (
leftBuffer.length === rightBuffer.length &&
crypto.timingSafeEqual(leftBuffer, rightBuffer)
);
}
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function isEmail(value) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value || ""));
}
app.post("/webhooks/wpforms", async (req, res) => {
const suppliedSecret = req.get("X-WPForms-Webhook-Secret");
if (!safeEqual(suppliedSecret, WPFORMS_WEBHOOK_SECRET)) {
return res.status(401).json({ error: "Unauthorized" });
}
const { form_id, entry_id, name, email, message } = req.body || {};
if (form_id !== "contact-form") {
return res.status(400).json({ error: "Unexpected form" });
}
if (!entry_id || !isEmail(email)) {
return res.status(400).json({ error: "Invalid submission" });
}
const safeName = escapeHtml(name || "there");
const safeMessage = escapeHtml(message || "");
const plainName = String(name || "there").trim();
const plainMessage = String(message || "").trim();
const payload = {
from: VOLANEA_FROM,
to: email,
subject: "We received your message",
text: `Hi ${plainName},\n\nThanks for contacting Example Team. We received your message and will reply soon.\n\nYour message:\n${plainMessage}`,
html: `
<p>Hi ${safeName},</p>
<p>Thanks for contacting Example Team. We received your message and will reply soon.</p>
<p><strong>Your message</strong></p>
<blockquote>${safeMessage.replaceAll("\n", "<br>")}</blockquote>
`,
};
const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
Authorization: `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `wpforms-contact-${entry_id}`,
},
body: JSON.stringify(payload),
});
const result = await volaneaResponse.json().catch(() => ({}));
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
entryId: entry_id,
result,
});
return res.status(502).json({ error: "Email was not accepted" });
}
console.info("WPForms confirmation accepted", {
entryId: entry_id,
email,
});
return res.status(202).json({ accepted: true });
});
app.listen(3000, () => {
console.log("Listening on http://localhost:3000");
});
Run it locally:
node server.mjs
For local testing, expose port 3000 through a secure development tunnel and use the resulting HTTPS URL as the temporary WPForms Request URL. For production, deploy the endpoint behind HTTPS on infrastructure you operate and monitor.
Understand the Volanea send request
The critical part of the receiver is the request to Volanea:
const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
Authorization: `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `wpforms-contact-${entry_id}`,
},
body: JSON.stringify({
from: VOLANEA_FROM,
to: email,
subject: "We received your message",
text: "Plain-text version of the confirmation.",
html: "<p>HTML version of the confirmation.</p>",
}),
});
Each field has an operational purpose:
frommust be a sender address you control and have verified for sending.tois the visitor who should receive the transactional confirmation.subjectshould describe the completed action rather than make a promotional claim.textgives recipients who do not render HTML a readable version of the message.htmlprovides the designed email version.Idempotency-Keyties repeated delivery attempts to one WPForms entry.
The API accepting the request is not the same as an inbox provider accepting or displaying the email. Treat the API response as confirmation that Volanea accepted the send request, then use your normal message events and logs to investigate later delivery, bounce, complaint, or suppression outcomes.
Protect recipient data and avoid unsafe email content
A form submission is user input. Even when WPForms validates required fields, do not assume the data is suitable to insert directly into an email API request or HTML document.
Validate the event before calling Volanea
Your receiver should reject requests that fail basic expectations:
- The shared webhook secret is absent or incorrect.
- The form identifier does not match an expected form.
- The entry identifier is missing.
- The email does not pass basic structural validation.
- The payload is too large or has unexpected field types.
This validation makes the endpoint narrow by design. A public URL should not become a general-purpose relay that anyone can use to send arbitrary email through your account.
Escape HTML, even in transactional messages
The example uses escapeHtml() before placing the visitor name or message into the HTML body. This is necessary because a visitor may submit characters such as <, >, &, or quotes. Without escaping, a submitted value could alter the markup of your email.
Do not solve this by stripping every character or refusing all punctuation. Preserve useful customer text in the plain-text body, escape it in HTML, and limit the number of characters you echo back. For a lengthy support form, it may be better to confirm receipt without quoting the entire message at all.
Do not use the visitor address as the sender
A common email mistake is setting from to the email a visitor enters into a form. That can break domain alignment and makes it look as if your system is sending mail on behalf of domains you do not control. Use your verified domain for from; keep the visitor as the recipient for confirmations and configure a deliberate reply workflow for internal notifications.
Make webhook retries safe with idempotency
Transactional email is a real-world side effect. If a user submits a contact form once but receives two confirmations, the system has created a trust problem even though both API calls technically succeeded.
The failure sequence is easy to miss:
- WPForms posts the form body to your receiver.
- The receiver calls Volanea.
- Volanea accepts the send.
- The receiver’s response is delayed or interrupted before WPForms receives it.
- WPForms or an intermediary retries the original webhook.
Without an idempotency key, step five can produce a duplicate message. With the same Idempotency-Key derived from entry_id, the repeated Volanea request represents the same logical operation.
Use a prefix that names the business action. For example:
wpforms-contact-4821
wpforms-download-4821
wpforms-quote-confirmation-4821
Do not reuse one entry ID for different email purposes without differentiating the action. A receipt and a support confirmation triggered from the same entry should receive different keys because they are different messages.
For higher-volume forms, also keep a small database table or durable log keyed by form_id plus entry_id. Store the first accepted API result and timestamp. That provides an audit trail when a customer asks whether a form was received, while the Volanea idempotency key remains the protection at the sending boundary.
Test the complete flow before publishing it
Test the system as a user would, not only by calling Volanea from a terminal.
A practical test checklist
- Submit the WPForms form with an inbox you can access.
- Confirm the receiver logs the expected
form_idandentry_idbut does not log your API key. - Confirm Volanea accepts the email request.
- Check that the recipient sees the expected sender, subject, text content, and HTML rendering.
- Submit a message containing
<script>, ampersands, line breaks, and quotes to verify escaping. - Replay the exact same webhook body with the same entry ID and confirm it does not create another logical confirmation.
- Submit the form a second time to create a new entry ID and confirm it does create a new email.
- Test an invalid shared secret and make sure the receiver returns
401without calling Volanea.
Test with a real mailbox at more than one provider if the form will be important to your customer journey. A message that looks good in one webmail interface can wrap, truncate, or display differently in another client. Include both HTML and plain text, use a recognizable sender name, and keep the subject direct.
When Zapier or Make is a better fit
A direct WPForms webhook receiver is not the only valid architecture. It is usually the best choice when you want to own the sending logic, avoid exposing an email API key outside infrastructure you control, and need reliable duplicate handling.
Use an automation service when the flow needs nontechnical editing or several business systems. For example, a team may want to create a CRM record, add a help-desk ticket, notify a sales channel, and then trigger a confirmation. WPForms supports both Zapier and Make integrations, and its Make addon maps selected form fields to parameter keys sent through a webhook-driven scenario.
Even then, be careful about where the Volanea secret lives. A workflow platform may provide secure connection storage, but sending directly from a generic HTTP step still means that platform becomes part of your credential and customer-data boundary. A thin receiver remains valuable when you need custom validation, an internal data lookup, HTML escaping, queueing, or uniform idempotency across many inbound systems.
A useful rule is simple:
- Use native WPForms Webhooks plus a receiver when engineering control, credential isolation, and predictable behavior matter most.
- Use Make or Zapier when the workflow is mostly SaaS-to-SaaS automation and nondevelopers must maintain mappings.
- Use a WordPress-side custom hook when all business logic belongs in the WordPress application and your team can safely maintain PHP code there.
Operate the integration as production email infrastructure
A form confirmation is often the first message a prospective customer receives from your business. Treat it as part of your production email system, not as an afterthought attached to a form.
Monitor these signals:
- Form submissions recorded by WPForms.
- Requests received and rejected by your webhook endpoint.
- Volanea API acceptance and error responses.
- Delivery, bounce, and suppression events for the sending domain.
- Duplicate attempts identified by entry ID and idempotency key.
Keep logs useful but restrained. Record the entry ID, form identifier, recipient domain, status code, and provider message identifier where available. Avoid logging full message bodies, complete form submissions, API keys, or sensitive fields such as medical information, passwords, payment details, and uploaded documents.
If a secret appears in logs, a screenshot, browser code, or a repository, revoke and rotate it. Update the receiver environment variable, redeploy, and then update the WPForms shared webhook secret separately if that secret was exposed too. Credentials are not merely configuration values; they are the authority to send email from your infrastructure.
As sending volume grows, review transactional email pricing alongside your expected form volume, retry behavior, and other application-generated messages. A contact form may start with a few confirmations each week, then become a meaningful part of sending volume after a campaign, product launch, or viral post.
Conclusion
To send transactional email from WPForms using Volanea, do not look for a native app that does not exist. Use WPForms’ Webhooks addon to post a deliberately mapped JSON body to a small server-side receiver. Authenticate that request, validate and escape its values, use the WPForms entry ID to build an idempotency key, and send the resulting message through Volanea’s POST /v1/send endpoint.
This approach is honest about the integration boundary and stronger in practice than a one-click connection. It keeps Volanea credentials server-side, makes your email content safer, gives you a place to handle business rules, and prevents a transient webhook failure from becoming a duplicate email in a visitor’s inbox.
FAQ
Does Volanea have a native WPForms integration?
No. Volanea does not currently provide a native WPForms app or installable one-click integration. The supported practical pattern is WPForms Webhooks posting to a server-side endpoint that calls Volanea’s REST API.
What does WPForms send in its webhook payload?
WPForms Webhooks sends the Request Body you configure through field mappings. It does not force one universal JSON event format. In this guide, the configured payload contains form_id, entry_id, name, email, and message.
Can WPForms post directly to Volanea’s API?
A custom outbound request can be configured, but a server-side receiver is usually safer because it keeps the Volanea secret key out of WordPress webhook settings and lets you validate data, sanitize HTML, and control retries.
Why do I need an Idempotency-Key for a form confirmation?
A webhook can be retried after a network interruption. Reusing a stable key based on the WPForms entry ID tells Volanea that repeated requests represent one logical email send rather than multiple confirmations.
Should I include the customer’s form message in the email?
Only if it is useful. Escape it before including it in HTML, keep a plain-text alternative, and consider truncating long text. For sensitive forms, acknowledge receipt without echoing submitted content back to the recipient.