Send email from forms.app without exposing an email API key by using forms.app’s native Webhook integration as the trigger and a small server-side receiver as the bridge to Volanea. This approach works for confirmation emails, internal alerts, lead acknowledgements, event registrations, support requests, and any workflow where a completed form response should create one transactional email.
forms.app does not have a native Volanea marketplace app or plugin. The dependable integration is therefore a webhook-based one: a respondent submits a form, forms.app posts that response to an endpoint you control, and that endpoint calls Volanea’s REST API with a secret API key kept out of the browser and out of form configuration.
What triggers an email in forms.app?
The concrete trigger is a form response: when someone completes and submits a published forms.app form, its configured Webhook integration sends the form response to the webhook URL. In forms.app, add that destination from the form’s Connect tab, choose Webhook, and use Add a webhook to enter the receiver URL.
That distinction matters. A webhook is not a client-side action running in the respondent’s browser, and it is not an email rule embedded in a form field. It is a server-to-server handoff after forms.app receives the response. Your receiver gets the response, decides whether an email should be sent, and creates a request to Volanea.
For a practical example, imagine a form with these visible fields:
- Full name
- Email address
- Company
- How can we help?
- Consent to receive a reply
A completed response becomes the event. The recipient can be the respondent for an acknowledgement, an internal inbox for a lead alert, or both as separate messages. Do not automatically turn a form response into a marketing subscription or campaign recipient unless the form includes appropriate consent and your workflow enforces it.
Why the integration needs a server-side bridge
It may be tempting to point forms.app directly at the Volanea send endpoint. Do not do that unless the sending provider explicitly supports the authentication and request shaping options your form platform can safely configure. Volanea’s email endpoint needs Bearer authentication with a secret key, while forms.app’s webhook setup is designed to send response data to a webhook URL.
A bridge endpoint solves several operational problems at once:
- It protects the Volanea API key. The key remains in an environment secret, rather than in a browser bundle, public form embed, query string, or editable third-party configuration.
- It converts form fields into a stable email schema. Forms change over time; your endpoint is the deliberate mapping layer between response labels and email content.
- It creates an idempotency key. If the same webhook delivery is attempted more than once, Volanea can treat the duplicate request as the same logical send rather than delivering two identical emails.
- It validates data before sending. The endpoint can reject blank or malformed email addresses, missing consent, unexpected submissions, and messages that exceed your policy.
- It separates acknowledgement from notification. A customer-facing confirmation and an internal lead notification have different recipients, privacy requirements, and retry behavior.
The bridge can be a Cloudflare Worker, Vercel Function, Netlify Function, AWS Lambda, a small Express service, or any backend that can receive HTTPS POST requests and store environment variables. The example below uses a Cloudflare Worker because it is compact, but the same request and mapping logic applies to any runtime.
The forms.app webhook payload and field mapping
forms.app’s public webhook setup documentation confirms that it sends form response data to the webhook URL and that the webhook panel provides recent deliveries. However, forms.app does not publish a versioned, universal JSON wire-schema reference for webhook bodies that guarantees every key name across every field type and form configuration. The reliable implementation pattern is to submit a real test response, inspect the resulting delivery in forms.app, and map the received keys explicitly.
For a form whose question labels are Full name, Email address, Company, How can we help?, and Consent to receive a reply, the response payload is handled as an object of submitted field values. A representative delivery for that form looks like this:
{
"Full name": "Ada Lovelace",
"Email address": "ada@example.com",
"Company": "Analytical Engines Ltd.",
"How can we help?": "I would like a demo for our support team.",
"Consent to receive a reply": "Yes"
}
Treat those labels as part of your integration contract. If you rename Email address to Work email, the receiver will no longer find payload["Email address"] unless you update the mapping. This is one reason to use simple, stable field labels for values consumed by automation.
The field mapping for a respondent acknowledgement is straightforward:
| forms.app response field | Volanea email field | Purpose |
|---|---|---|
Email address | to | Recipient address for the acknowledgement |
Full name | HTML/text body | Personalized greeting |
Company | HTML/text body | Gives the receiving team context |
How can we help? | HTML/text body | Includes the request safely as escaped text |
| response fingerprint | Idempotency-Key header | Prevents duplicate sends during retries |
The response body is input data, not trusted HTML. Escape it before inserting it into an HTML email. A form field can contain angle brackets, pasted markup, unexpected whitespace, or content designed to make a notification misleading. Escape first, then render.
Working webhook receiver: forms.app to Volanea
Create a Worker with three secrets:
VOLANEA_API_KEY: your Volanea secret key, such as ansk_…orsk_test_…key.FORMAPP_WEBHOOK_TOKEN: a long random value that protects the inbound webhook URL.FROM_EMAIL: a verified sender address, such ashello@updates.example.com.
The route below expects the token as part of the URL, for example:
https://forms-email.example.workers.dev/formsapp/your-long-random-token
Paste that full URL into the forms.app Webhook setup. The secret is intentionally in the inbound URL rather than the outbound Volanea request; forms.app sends to your bridge, and only the bridge receives the Volanea credential from its private environment.
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
// forms.app stores this entire URL as the webhook destination.
if (
!url.pathname.startsWith("/formsapp/") ||
url.pathname.split("/").pop() !== env.FORMAPP_WEBHOOK_TOKEN
) {
return new Response("Not found", { status: 404 });
}
let payload;
try {
payload = await request.json();
} catch {
return new Response("Expected JSON", { status: 400 });
}
// forms.app question labels are the explicit integration contract.
const name = String(payload["Full name"] ?? "").trim();
const email = String(payload["Email address"] ?? "").trim().toLowerCase();
const company = String(payload["Company"] ?? "").trim();
const message = String(payload["How can we help?"] ?? "").trim();
const consent = String(payload["Consent to receive a reply"] ?? "").trim();
if (!email || !email.includes("@")) {
return new Response("Missing or invalid Email address", { status: 422 });
}
if (consent !== "Yes") {
// Return success so a deliberately ineligible response is not retried.
return Response.json({ skipped: "reply consent not granted" }, { status: 200 });
}
const escapeHtml = (value) =>
value.replace(/[&<>'"]/g, (character) => ({
"&": "&",
"<": "<",
">": ">",
"'": "'",
"\"": """
})[character]);
// A deterministic fingerprint makes the same form response safe to retry.
const source = JSON.stringify({ name, email, company, message, consent });
const hashBytes = await crypto.subtle.digest(
"SHA-256",
new TextEncoder().encode(source)
);
const idempotencyKey = [...new Uint8Array(hashBytes)]
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
const safeName = escapeHtml(name || "there");
const safeCompany = escapeHtml(company || "Not provided");
const safeMessage = escapeHtml(message || "Not provided");
// Volanea REST API call: POST https://api.volanea.com/v1/send
const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${env.VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `formsapp-${idempotencyKey}`
},
body: JSON.stringify({
from: env.FROM_EMAIL,
to: email,
subject: "We received your request",
html: `
<h1>Thanks, ${safeName}</h1>
<p>We received your request and will reply soon.</p>
<p><strong>Company:</strong> ${safeCompany}</p>
<p><strong>Your message:</strong></p>
<p>${safeMessage.replace(/\n/g, "<br>")}</p>
`,
text: [
`Thanks, ${name || "there"}.`,
"We received your request and will reply soon.",
`Company: ${company || "Not provided"}`,
`Your message: ${message || "Not provided"}`
].join("\n\n")
})
});
const responseBody = await volaneaResponse.text();
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
responseBody
});
// A non-2xx response tells forms.app that this delivery was not accepted.
return new Response("Email send failed", { status: 502 });
}
return new Response(responseBody, {
status: 200,
headers: { "Content-Type": "application/json" }
});
}
};
This code sends one acknowledgement to the submitting address. To notify an internal team instead, use a separate Volanea request with a fixed recipient such as sales@example.com. Do not put the respondent’s free-form text in the subject line; keeping it in the escaped body reduces the chance that a long or malicious input produces misleading alert messages.
For the complete request schema, sending options, templates, and delivery-event behavior, consult the Volanea email API reference before extending the basic send.
Configure forms.app safely
After you deploy the receiver, configure forms.app itself:
- Open the form that should send the email.
- Open the Connect tab.
- Find Webhook and select it.
- Choose Add a webhook.
- Paste the private receiver URL, including its random token.
- Save or publish the webhook configuration.
- Submit a real test response using the shared form URL.
- Review the webhook’s recent delivery in forms.app and confirm the received fields match the labels used in the receiver.
Do not put VOLANEA_API_KEY into a forms.app hidden field, an embed script, a form URL parameter, a JavaScript snippet, or a webhook URL query parameter. Hidden fields are not a secret store: respondents can inspect page markup, browser network traffic, submission data, or shared form URLs. Similarly, a Bearer key placed in client-visible configuration can be copied and used to send mail from your account.
The Volanea key belongs only in a server-side secret manager. In the Worker example, it is a Worker secret. In another platform, it might be an encrypted function environment variable, an AWS Secrets Manager entry, or a deployment secret injected into the runtime. Rotate it immediately if it is ever committed to a repository, pasted into an issue, or exposed in a public client application.
Design the form for reliable email automation
A form is a user-facing interface; an email automation is a system integration. Designing for both means being intentional about field labels, validation, and conditional paths.
Use stable automation labels
Question labels are convenient mapping keys, but people often rename copy for branding or conversion tests. Every label change can break a direct key lookup. For a high-value flow, establish an editing rule: the labels used by the receiver are integration fields and must be updated in the code and tested whenever the form changes.
A practical convention is to keep automation-oriented labels specific and stable. For example, prefer Email address over frequently changing copy such as Where should we send the exciting details?. The second may be friendlier on a landing page, but the first is clearer in logs, tests, support tickets, and code.
Validate at the right layer
Use an Email field in forms.app where appropriate, but validate again in the receiver. Form-level validation improves user experience; server-side validation protects your mail pipeline from malformed, empty, or unexpected values that may arrive through a changed form, imported record, test delivery, or schema mismatch.
Do not rely on a basic includes("@") check in production if email is business-critical. Use a validation policy appropriate to the risk, and let Volanea’s suppression and delivery controls remain part of your broader sending process. A syntactically plausible address is not proof that a recipient exists or wants mail.
Separate transactional and promotional intent
A form acknowledgement such as “We received your request” is normally transactional and directly related to the respondent’s action. A newsletter, product announcement, or recurring campaign is different. Include explicit consent for marketing, preserve that consent record, and make the automation conditional rather than assuming every form submission is campaign permission.
A useful pattern is to send the immediate acknowledgement regardless of marketing consent when it is necessary to complete the request, then route only opted-in contacts to a separate subscription workflow. This keeps the confirmation useful while preventing a support or contact form from silently becoming a marketing capture mechanism.
Make the email useful, not merely automatic
The strongest forms.app email integrations remove uncertainty for both the person who submitted the form and the team responsible for follow-up. That means the message should answer three questions quickly: did the form arrive, what happens next, and what information did the person provide?
For a lead form, the respondent acknowledgement can include:
- A clear receipt confirmation.
- An expected response window only if your team can meet it.
- A concise copy of the request, excluding sensitive fields.
- A reply-to address monitored by a person or support workflow.
- A link to relevant documentation, scheduling, or account resources when appropriate.
For the internal notification, include the exact response data needed to act, but minimize unnecessary personal data. If the form collects confidential details, medical information, financial details, identity documents, or uploaded files, carefully consider whether email is the right notification channel. An inbox is often less controlled than the system of record.
Use a verified sending domain in Volanea before production traffic. A form automation may begin as a few test submissions and later become a steady source of messages. Domain authentication and consistent sender identity help the mail stream remain recognizable and operationally manageable as it grows.
When this breaks: duplicates, timeouts, and missing fields
The difficult cases in a forms.app-to-email workflow happen in the handoff between systems. A user may submit once while the downstream request happens more than once; a form may evolve while code expects old labels; an email request may succeed even though the receiver loses its response. Plan for these cases before enabling the form publicly.
A webhook retry causes duplicate sends
A webhook sender can retry when it does not receive a successful response, including after a network interruption, receiver crash, or timeout. forms.app also provides recent delivery visibility, which is useful when diagnosing whether a submission reached your endpoint more than once.
The receiver example uses a deterministic Idempotency-Key derived from the mapped response. If forms.app sends the same response again, the same key is supplied to Volanea. Volanea treats repeated requests with the same idempotency key as the same logical operation rather than a new send.
There is an important limitation: hashing only the answer content means two genuinely separate submissions with identical answers produce the same key. For a contact form, that may be acceptable; for registrations, orders, or any form where someone can intentionally submit the same data twice, prefer a unique forms.app delivery or response identifier when it is present in your observed payload. If the webhook does not provide a stable unique identifier, store your own receipt record with a short time window and make an explicit business decision about what counts as a duplicate.
The webhook times out after Volanea accepts the message
This is the classic distributed-systems failure: your receiver sends to Volanea successfully, but the connection closes before forms.app receives your 200 response. forms.app may attempt delivery again because it cannot know the email was accepted. Without idempotency, the customer receives two emails. With a stable idempotency key, the retry repeats the original operation safely.
Keep the receiver small and fast. Do only the validation, mapping, send request, and essential logging in the synchronous webhook path. Do not call several slow APIs, run expensive report generation, or wait for unrelated database tasks before returning a result. If the workflow needs more work, queue it after storing a durable record.
A field is missing or has a different value
Fields may be absent because of conditional logic, an optional answer, a deleted or renamed question, different form versions, or account-level feature differences. A file-upload value may also be a URL or metadata rather than a file attachment you can forward directly.
Use defaults for optional data and fail closed for required data. In the example, missing Company and How can we help? are rendered as “Not provided,” while a missing Email address creates a 422 response and no mail is sent. That behavior is intentional: an email integration cannot safely guess a destination address.
Before editing a live form, test the new form version with every conditional path. Submit one response that shows each branch, then review the received webhook payload and email output. Do not assume the payload contains hidden or skipped fields as blank values; inspect the actual delivery.
The Volanea key is rejected or the sender is not verified
A 401 or 403-style authentication failure usually indicates the wrong key, a key from the wrong environment, a revoked key, or a malformed Authorization header. Sender-related errors usually indicate that FROM_EMAIL is not a verified sender identity or does not match the configured sending domain.
Keep testing and production secrets separate. Use a test key for non-production forms where possible, and ensure the sender address belongs to the environment and verified domain you intend to use. Logging the HTTP status and provider response body privately is useful; logging secrets or entire sensitive form payloads is not.
Testing checklist before publishing
A test should prove more than “an email arrived once.” It should verify that the system sends the right message to the right person, does not leak secrets, and behaves predictably when a downstream dependency fails.
Run this checklist:
- Submit a normal response with a real inbox you control.
- Confirm the forms.app webhook delivery is marked successful.
- Confirm the recipient, sender, subject, plain-text body, and HTML body are correct.
- Submit a response with optional fields empty.
- Submit a response that takes every conditional-logic branch.
- Submit a value containing
<,>,&, quotes, and line breaks to confirm HTML escaping. - Temporarily use an invalid Volanea key and confirm the receiver returns an error rather than reporting a false success.
- Replay the same captured payload to the receiver and confirm the idempotency key prevents another email from being created.
- Verify that deployment logs do not contain the Volanea API key or unnecessary personally identifiable data.
- Test after every change to form labels, requiredness, conditional logic, or sender identity.
For high-value flows, add structured logs containing a request correlation ID, forms.app delivery timestamp if available, a privacy-safe submission identifier, Volanea response status, and the idempotency key. This creates a trail your team can use to answer “Did the form arrive?”, “Was an email created?”, and “Was it retried?” without exposing the full contents of every submission.
Direct webhook, Zapier, or Make?
The direct webhook-plus-receiver route is the best option when you need strong control over secrets, custom email HTML, idempotency behavior, field validation, and observability. It also gives engineering teams a durable integration boundary that is not tied to a visual automation configuration.
Zapier and Make remain valid middleware options when you need a no-code workflow. forms.app supports Zapier with the New Form Submission trigger, and its Make documentation describes creating a Custom webhook, copying the URL, and placing that URL in forms.app’s Webhook integration. In either tool, use a webhook or HTTP module to call your own receiver rather than placing the Volanea secret key into an exposed or broadly shared automation step.
Choose middleware when the workflow is simple, the team needs visual editing, and the operational cost is acceptable. Choose a direct receiver when a duplicate email would be expensive, message content needs careful escaping or personalization, secrets require narrow access, or you need code review and deployment controls.
Conclusion
To send email from forms.app with Volanea, use the real form-response webhook as the trigger, route it to a private server-side endpoint, map stable form labels to an email request, and send through POST /v1/send with a Volanea Bearer key stored as a server secret. This is not a marketplace installation; it is a purposeful integration boundary that gives you control over validation, consent, retries, and delivery behavior.
The key reliability decision is idempotency. Form submissions and webhook requests can be retried even when a person submitted once. By generating and reusing a stable Idempotency-Key, you make the email side effect safe to repeat while preserving a simple experience for the respondent.
FAQ
Does forms.app have a native Volanea integration?
No. forms.app provides a native Webhook integration, but it does not provide a native Volanea app, marketplace listing, or plugin. Use the webhook to reach a receiver you control, then call Volanea from that receiver.
What forms.app event sends the email?
A completed form response triggers the webhook. Configure the webhook from the form’s Connect tab, then forms.app sends the response data to your endpoint after someone submits the form.
Where should I store the Volanea API key?
Store it only in a server-side secret manager or deployment environment variable, such as a Worker secret or function secret. Never place it in a forms.app field, client-side JavaScript, shared webhook URL, or public form configuration.
How do I stop duplicate emails from retries?
Send an Idempotency-Key header with the Volanea request and reuse the same value whenever the same webhook delivery is retried. Prefer a unique submission or delivery ID from your observed forms.app payload when available.
Can I use Zapier or Make instead of writing a webhook receiver?
Yes. forms.app supports Zapier’s New Form Submission trigger and can send webhooks to Make Custom webhooks. For secure Volanea sending, keep the API key in a protected server-side endpoint whenever possible, especially for production forms and sensitive workflows.