If you need to send email from Paperform, the dependable pattern is a Paperform submission webhook that calls your server, followed by a server-side Volanea API request. That approach keeps credentials private, gives you control over field mapping, and prevents a form tool from becoming the place where email-delivery logic lives.
Paperform does not need a native Volanea app for this workflow. Its webhook capability can notify an HTTPS endpoint when a respondent submits a form; your endpoint then validates the request, normalizes the submission data, and sends the appropriate email through Volanea’s REST API.
This guide uses a practical example: a customer submits a “request a demo” form, receives a confirmation email, and your sales inbox receives an internal notification. The same design works for registration confirmations, quote requests, onboarding forms, order enquiries, waitlists, lead routing, and document-upload workflows.
What the Paperform-to-Volanea flow looks like
The trigger is a form submission in Paperform. After a respondent completes and submits the form, Paperform posts submission data to the webhook URL you configure. That webhook delivery—not a browser-side script—is what starts the email workflow.
The complete path has four parts:
- A respondent submits a published Paperform form.
- Paperform sends a JSON webhook request to an HTTPS endpoint you control.
- Your relay extracts the submitted email address and other answers, then applies your business rules.
- The relay sends a server-to-server request to Volanea’s email API and returns a successful response quickly to Paperform.
There are two important boundaries in that model. Paperform owns collection of the response and delivery of the webhook. Your application owns authentication, recipient decisions, templates, idempotency, and the decision to send. Volanea owns the actual email submission and delivery infrastructure after your relay makes the API request.
That separation is useful even for a simple one-email form. A form can be changed by a marketer, duplicated for a campaign, translated, or extended with questions. Your email sender should be resilient to those changes rather than assuming every field will always be present and correctly formatted.
Why use a webhook relay instead of putting an API key in a form
A Paperform webhook is an outbound HTTP notification, not a safe place to expose a sending credential to a visitor’s browser. The Volanea API key must remain in a server-side secret store, such as your hosting provider’s encrypted environment variables, a cloud secret manager, or a dedicated configuration system.
Do not put the key in any of these places:
- Custom JavaScript delivered with the form page.
- A client-side environment variable whose value is bundled into browser code.
- A query string on the webhook URL.
- A hidden Paperform field.
- A webhook body or static request header configured in a place that broadens access to the credential.
- A Git repository, example form, screenshot, or support ticket.
On the Paperform side, the only essential value is the webhook endpoint URL, for example https://forms.example.com/hooks/paperform. If you use a shared secret to authenticate incoming requests, put that secret in the URL only if Paperform’s webhook configuration cannot send a protected header, and treat that URL as a credential: do not publish it, log it in plain text, or reuse it across environments.
The Volanea key lives in the relay’s VOLANEA_API_KEY environment variable. The relay reads it at runtime and adds it to the outgoing API request. A respondent never sees it, and Paperform never has to store it.
This also gives you a clean revocation story. If a key is rotated, update one server-side secret and redeploy or restart the relay. You do not need to edit every form, update browser code, or wait for a cached front-end build to expire.
Configure the Paperform submission webhook
In the settings for the specific Paperform form, add a Webhook action to its post-submission workflow and point it at a publicly reachable HTTPS URL. The action must run on a successful form submission—the event that creates a Paperform submission—not merely when someone views the form or changes a field.
Before turning on live email, use a temporary test endpoint you control and submit the form with realistic values. Save the raw request body. This step matters because the identifiers used for answers are tied to your form: a field may be represented by its question label, a question key, or another form-specific identifier depending on the webhook payload and how the question was configured.
For the example in this article, the form contains these questions:
| Paperform question | Purpose in the relay | Example answer |
|---|---|---|
Email address | Recipient for the confirmation | sam@example.net |
Full name | Greeting and internal notification | Sam Lee |
Company | Sales context | Northstar Labs |
Message | Internal lead context | We need API access |
Consent | Optional marketing permission | Yes |
Use required-field validation in Paperform for the email address if confirmation email is a core part of the experience. Still validate the address in your relay. A required browser/form validation rule improves completion quality, but it is not a replacement for server-side validation or abuse controls.
Keep production and test forms separate. A useful convention is to send test-form webhooks to https://staging.example.com/hooks/paperform and production webhooks to https://forms.example.com/hooks/paperform. That prevents a test submission from creating a real sales lead or sending a customer-facing email from your production domain.
Understand and map the Paperform webhook payload
A Paperform webhook is a POST request containing the submission and its answers. The exact answer keys are determined by the form’s questions, so capture a live test delivery and use those real keys in your mapping rather than guessing from the visual wording alone.
Conceptually, a submission payload contains submission metadata plus answer data. A relay should treat the submission identifier as the event identifier and the answers as untrusted input. A representative shape for a submitted form is:
{
"submission_id": "subm_01HZY8M2Q4K7",
"form_id": "frm_demo_request",
"created_at": "2026-09-23T10:14:31.000Z",
"data": {
"Email address": "sam@example.net",
"Full name": "Sam Lee",
"Company": "Northstar Labs",
"Message": "We need API access for product receipts.",
"Consent": "Yes"
}
}
The values in data are the values the respondent supplied. They are not safe HTML, authoritative identity data, or a guarantee that the recipient accepts marketing. Escape them before inserting them into HTML, do not use them to build unvalidated URLs, and keep consent separate from a transactional confirmation.
The mapping for this form is straightforward:
data["Email address"]becomes the customer email recipient.data["Full name"]becomes the greeting name after HTML escaping.data["Company"]anddata["Message"]go into the internal notification.submission_idbecomes the idempotency key used to avoid duplicate email sends.form_idis useful for routing when one endpoint receives webhooks from several forms.
Question labels are editable. If someone changes Email address to Work email, code that looks up the original label will no longer find it. For long-lived production forms, establish stable question keys where Paperform exposes them, document those keys alongside the integration, and run a webhook test after structural form edits.
Send email from Paperform with a server-side API call
The following Node.js example is an Express webhook relay. It accepts the Paperform POST body, extracts the fields shown above, prevents repeat sends for the same submission, and calls Volanea’s REST email endpoint.
The example deliberately sends only after basic validation. It returns a 2xx response only once the relay has recorded the submission as processed or successfully queued the send. In a production system, replace the in-memory processedSubmissionIds set with a database table, Redis key, or durable queue.
import express from "express";
const app = express();
app.use(express.json({ limit: "1mb" }));
const processedSubmissionIds = new Set();
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function validEmail(value) {
return typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}
app.post("/hooks/paperform", async (req, res) => {
// Optionally check a webhook secret here before processing.
// Do not use the Volanea API key as the inbound webhook secret.
const submission = req.body;
const answers = submission.data ?? {};
const submissionId = submission.submission_id;
const formId = submission.form_id;
const email = String(answers["Email address"] ?? "").trim().toLowerCase();
const fullName = String(answers["Full name"] ?? "").trim();
const company = String(answers["Company"] ?? "").trim();
const message = String(answers["Message"] ?? "").trim();
if (!submissionId || !formId) {
return res.status(400).json({ error: "Missing Paperform submission metadata" });
}
// Idempotency: Paperform may deliver again after a timeout or temporary failure.
if (processedSubmissionIds.has(submissionId)) {
return res.status(200).json({ status: "already_processed" });
}
if (!validEmail(email)) {
// Acknowledge a malformed response instead of repeatedly retrying it.
console.warn("Paperform submission has no usable email", { submissionId, formId });
return res.status(200).json({ status: "skipped_invalid_recipient" });
}
const safeName = escapeHtml(fullName || "there");
const safeCompany = escapeHtml(company || "Not supplied");
const safeMessage = escapeHtml(message || "Not supplied");
const volaneaResponse = await fetch("https://api.volanea.com/v1/email/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
from: "Example Company <hello@updates.example.com>",
to: [email],
subject: "We received your request",
html: `<p>Hi ${safeName},</p>
<p>Thanks for contacting Example Company. Our team will review your request and reply soon.</p>`,
text: `Hi ${fullName || "there"},\n\nThanks for contacting Example Company. Our team will review your request and reply soon.`,
headers: {
"X-Source": "paperform",
"X-Paperform-Submission-Id": submissionId
}
})
});
if (!volaneaResponse.ok) {
const detail = await volaneaResponse.text();
console.error("Volanea send failed", {
submissionId,
status: volaneaResponse.status,
detail
});
return res.status(502).json({ error: "Email provider rejected the send" });
}
processedSubmissionIds.add(submissionId);
// Internal notification is normally better sent through a queue or a second job.
console.info("Paperform confirmation queued", {
submissionId,
formId,
recipient: email,
company: safeCompany,
messagePreview: safeMessage.slice(0, 80)
});
return res.status(200).json({ status: "sent" });
});
app.listen(process.env.PORT || 3000);
Before deploying, compare the endpoint, authentication scheme, and message fields against the current email API reference and setup guides. The core security rule remains the same regardless of language: the relay, not Paperform or the browser, makes the authenticated API call.
For an internal notification, make a second send request after the customer confirmation, or preferably add a separate queued job. Use a fixed internal recipient such as sales@example.com; never route internal messages to a form answer without an allowlist. Include the customer’s email address, the submission ID, and sanitized answers in the internal email so the team can find the original submission when responding.
Use templates and transactional categories deliberately
A submission confirmation is generally transactional when it merely acknowledges a request the respondent has made. Its purpose is to confirm receipt, provide expected next steps, or deliver a requested resource. Do not turn that message into a broad promotional newsletter simply because the recipient submitted a form.
If the form includes an opt-in checkbox, store the precise consent result with the submission. Then use that consent only for the marketing purpose described on the form. A checkbox saying “contact me about this request” is not necessarily consent for an unrelated product announcement series.
A useful split is:
- Confirmation email: Sent immediately to the person who submitted the form; concise, expected, and tied directly to the request.
- Internal notification: Sent to your team with enough context for timely follow-up.
- Marketing enrollment: Performed only when the form captured appropriate permission and your workflow records that state.
- Operational follow-up: Sent later by a CRM or customer-success workflow when a person takes a defined next step.
Use a verified sender domain and a From address that matches the expectation created by the form. If the form is branded “Example Company Support,” an email from hello@updates.example.com is understandable if that domain is clearly associated with the company; an unrelated domain can reduce trust and make replies harder to manage.
Set a Reply-To address when replies should go to a monitored inbox different from the From address. For lead forms, an inbox owned by the team responding to requests is often more useful than a no-reply address. It makes the confirmation a real communication channel rather than a dead end.
Make the relay reliable before increasing form traffic
A webhook handler has two responsibilities that can conflict: acknowledge Paperform promptly and ensure no lead disappears. Sending directly inside the HTTP handler is acceptable for low volume, but a queue-backed design is more resilient.
In a queue-backed version, the handler validates the webhook, stores a durable event record keyed by submission_id, enqueues a send-confirmation job, and returns success. A worker then makes the Volanea request. The event record tracks states such as received, queued, sent, skipped, and failed.
That design makes failures observable. If Volanea is temporarily unavailable, the worker can retry with controlled backoff without forcing Paperform to wait. If your server restarts after receiving the webhook but before sending, the stored event remains available for recovery.
Idempotency is not optional
Webhook delivery should be designed as at-least-once. A sender may retry when it does not receive a timely successful response, and network failures can leave you uncertain whether the upstream system received your response. Without idempotency, one form submission can create two or more confirmation emails.
Use the Paperform submission ID as the natural deduplication key. Store it in a database table with a unique constraint. A simple table might include:
| Column | Why it exists |
|---|---|
paperform_submission_id | Unique idempotency key |
form_id | Supports routing and audits |
recipient | Lets you investigate delivery questions |
status | Shows processing state |
volanea_message_id | Connects your event to provider activity, if returned |
created_at and sent_at | Supports operations and retention rules |
Do not deduplicate only on the recipient email. One person may legitimately submit two different requests. Do not deduplicate only on a timestamp either; clocks and retries make that unreliable. The submission ID represents the actual event you want to process once.
Return quickly, but do not hide failure
A webhook endpoint should not perform slow CRM calls, AI enrichment, file processing, and multiple email sends synchronously. Long work increases timeout risk. It can also cause Paperform to retry, which amplifies the duplicate-send problem.
Return a successful response only when you have safely accepted responsibility for the event—either by persisting it or completing the send. If your database is unavailable, return an error so the upstream delivery can be retried, but make sure your idempotency record and email send are coordinated well enough not to create duplicates after recovery.
When this breaks: Paperform webhook failure modes
The most common problems occur in the hop between Paperform’s form submission and your webhook relay, not in the email content itself. Build diagnostics around that hop from the start.
Retries can create duplicate sends
Paperform can attempt webhook delivery again when your endpoint does not return a successful response in time or returns an error. A timeout may occur after your relay has already sent the email but before Paperform receives the response. If your relay treats the retry as a new event, the customer receives duplicate confirmations.
Fix this with durable idempotency keyed on submission_id. Record the submission before or atomically with the enqueue operation, and return a successful response for subsequent deliveries of the same completed event. Log whether a request was newly processed or recognized as a duplicate.
Webhook timeouts usually point to synchronous work
If delivery times out, inspect your endpoint’s request duration and dependency timings. DNS lookups, cold starts, database waits, large file downloads, and a slow email-provider response can all add enough latency to make an otherwise valid workflow unreliable.
Keep the webhook handler small. Parse and validate the payload, persist a job, and acknowledge it. Move email sending, attachment preparation, CRM synchronization, and third-party enrichment to background workers. If you choose direct sending for simplicity, set a short outbound timeout and monitor failures rather than letting requests hang indefinitely.
Expected fields can be missing
A form answer may be absent because the question is optional, hidden by conditional logic, deleted, renamed, not included in a version of the form, or unavailable in the particular Paperform feature or plan configuration being used. Do not assume that every payload has every visible question.
The relay should distinguish between required operational fields and optional context. An absent recipient email should normally result in a logged skipped_invalid_recipient event, not an attempt to call the sending API with an empty to value. An absent company name can safely fall back to “Not supplied.”
Test all conditional paths. If a question appears only after a respondent selects a certain option, submit the form both with and without that option. Validate plan-specific capabilities before making a field, workflow action, or attachment-dependent path essential to your automation.
Field names drift after form edits
A seemingly harmless rename can break a hard-coded lookup. This is especially likely when field labels are used as payload keys. Protect against it by keeping a mapping document, using stable identifiers where available, and alerting when a required key disappears.
A practical monitoring rule is: if a form submission arrives with a known form_id but no mapped email field, create an internal alert containing the submission ID and the keys actually received. That turns a silent business failure into an actionable configuration issue.
Validate recipients and protect the sending domain
Paperform’s email question type and required validation improve data quality, but they cannot guarantee a real or deliverable mailbox. A typo such as sam@gmial.com can still pass a basic format check; a disposable or role address may also be inappropriate for your use case.
For high-value lead flows, validate addresses in the relay before sending an expensive or important follow-up. Volanea’s free address verification tool can help check an address before it reaches your email workflow. Keep your policy proportionate: a simple acknowledgement may be safe to send to syntactically valid addresses, while account provisioning or sensitive document delivery should have stricter verification and authentication controls.
Also consider abuse. Public forms can attract bots that submit arbitrary addresses, creating unwanted mail and damaging sender reputation. Useful safeguards include CAPTCHA or Paperform’s available anti-spam controls, rate limits at the webhook endpoint, per-IP anomaly detection where appropriate, and a rule that prevents a single recipient from receiving repeated confirmations within a short period.
Do not log more personal information than you need. Application logs should usually record the submission ID, form ID, processing status, and perhaps a redacted recipient such as s***@example.net. Avoid dumping full webhook bodies into long-retention logs, especially if forms collect phone numbers, files, health information, financial details, or free-text messages.
Test the whole integration, not just the API request
A successful API response proves that your relay can submit an email. It does not prove that Paperform sends the expected data, that the answer mapping survives a form edit, or that recipients see the message as intended.
Run a release checklist whenever you add or materially change a form:
- Submit the published form with a test mailbox you control.
- Confirm that the webhook reaches the expected environment.
- Compare the received raw payload with the mapping configuration.
- Verify the customer confirmation has the correct recipient, subject, sender, reply address, text version, and HTML rendering.
- Verify the internal notification contains sanitized context and no unnecessary sensitive data.
- Repeat the same submission delivery or invoke the saved payload twice to confirm idempotency.
- Test missing optional fields and every major conditional-logic branch.
- Review logs for the submission ID and confirm that failures are visible to the right team.
Use a dedicated test recipient rather than coworkers’ personal inboxes. Include a recognizable marker such as [staging] in non-production subjects. For production smoke tests, use a controlled internal mailbox and remove temporary test answers from downstream CRM systems if required by your data-retention policy.
Alternatives when a custom relay is not practical
A small serverless function is usually the best direct integration because it gives you secret management, durable logging, and control over payload changes. It does not have to be a permanently managed server: a function on your existing application platform can be enough.
If your team cannot operate code, use an automation platform as middleware between Paperform and your email workflow. Paperform supports automation-oriented integrations such as Zapier and Make, which can receive new submissions, map form fields, call an HTTP endpoint, and create follow-up records. This can be useful for low-volume internal notifications or a prototype.
However, review the trade-offs before relying on no-code middleware for customer-facing transactional email:
- A multi-step scenario introduces another retry and duplicate-handling boundary.
- API credentials must still be stored only in the automation platform’s protected connection or secret settings.
- Complex conditional forms can become difficult to map and test visually.
- Operational logs may be split across Paperform, the automation platform, Volanea, and your CRM.
- Per-task pricing can rise with submission volume.
For a production workflow that sends consequential messages, a webhook relay plus a queue provides clearer auditability. It also lets you evolve from a plain confirmation to templating, localization, attachment handling, CRM routing, or event-driven onboarding without replacing the fundamental architecture.
Conclusion
The reliable way to send email from Paperform is to use a Paperform form submission webhook as the trigger and let a server-side relay call Volanea. The webhook supplies the event and answers; your relay supplies the security, validation, idempotency, template logic, and observability that a production email workflow needs.
Start with one form, one confirmation message, one durable submission-ID record, and a real end-to-end test. Once that foundation is in place, adding internal notifications, routing rules, consent-aware marketing enrollment, or a queue becomes an incremental improvement rather than a fragile rewrite.
FAQ
Does Paperform have a native Volanea integration?
No native Paperform marketplace app is required for this setup. Use Paperform’s webhook capability to notify your HTTPS endpoint, then have that endpoint call Volanea’s REST API with a server-side API key.
What Paperform event sends the email?
The trigger is a successful Paperform form submission. Configure the webhook as a post-submission action so that a completed respondent submission produces the outbound HTTP request.
Can I call Volanea directly from Paperform without a server?
A direct browser-side call is not appropriate because it would expose the sending API credential. A serverless function, application endpoint, or carefully configured middleware platform should hold the key and make the authenticated request.
How do I stop duplicate confirmation emails?
Store the Paperform submission_id as a unique idempotency key before sending or queueing email. If the same webhook arrives again, return success without creating another send.
What should happen if the submitted email address is missing?
Treat it as a controlled skip: log the submission ID and mapping failure, return a response that avoids endless retries, and alert the form owner if the missing value indicates a renamed, hidden, or misconfigured required field.