Sending email from Wufoo with Volanea is best handled as a webhook-to-server-to-email flow: a Wufoo form submission posts its field data to your endpoint, and that endpoint calls Volanea’s REST API. There is no native Volanea app or Wufoo marketplace plugin to install, but Wufoo’s outbound WebHook integration provides the event trigger needed for a reliable direct integration.

The important architectural detail is that Wufoo should notify your server, not call Volanea with a secret embedded in a browser form or exposed configuration. Your server receives the submission, validates it, maps Wufoo field IDs to meaningful values, and sends the resulting transactional message through Volanea.

What this Wufoo integration does

This integration sends an email after a person submits a Wufoo form. In Wufoo terminology, the trigger is a form submission: when someone submits the form, Wufoo sends an HTTP POST containing the submitted entry data to the WebHook URL configured for that form.

That makes the pattern useful for contact forms, lead-routing notifications, application confirmations, event registrations, support requests, and internal alerts. A single submission can produce one email to the submitter, one email to your team, or separate messages to both audiences.

The end-to-end path is:

  1. A visitor completes and submits a Wufoo form.
  2. Wufoo creates the form entry and sends its fields to your configured WebHook URL as an HTTP POST.
  3. Your webhook receiver parses the form-encoded payload, validates the request, and builds an email payload.
  4. Your server sends that message to Volanea with POST https://api.volanea.com/v1/send.
  5. Volanea accepts the message for sending, applies suppression checks and sending-domain rules, and records the send in the same email infrastructure used for your other transactional mail.

Wufoo WebHooks are a paid-plan integration feature. In the current Wufoo interface, you configure one from a form’s Integrations area: choose WebHook, provide the endpoint URL, optionally provide a WebHook Handshake Key, and optionally include field and form structures with the entry data. Wufoo permits up to 10 webhooks per form. The WebHook is for future entries only; it does not replay submissions collected before you configured it.

Why use a relay instead of pointing Wufoo at an email API

Wufoo’s WebHook sends the entry data as an HTTP POST. It is not a native email-provider action builder where you can safely store a Volanea API key, generate an Authorization header, transform a payload, and make a second authenticated request.

A relay is therefore not unnecessary plumbing. It is the secure integration boundary between an externally initiated form submission and an email-sending credential.

The relay protects your Volanea key

Your Volanea API key belongs in a server-side secret store or environment variable such as VOLANEA_API_KEY. It must not appear in:

  • Wufoo form JavaScript or custom client-side code.
  • A public form page, HTML source, or URL parameter.
  • A front-end application bundle.
  • A client-visible automation configuration.
  • A WebHook URL query string.

Anyone who obtains a sending API key may be able to send mail under your account, consume sending capacity, inspect API-accessible data depending on key scope, or damage your sender reputation. A URL query string is especially poor secret storage because URLs can be retained in logs, browser history, reverse proxies, observability tools, and referrer data.

The safe arrangement is simple: Wufoo knows only the HTTPS URL of your receiver and, optionally, a WebHook Handshake Key. The receiver knows the Volanea API key through a private server environment variable. The browser that submits the form knows neither secret.

The relay gives you business logic Wufoo cannot provide

Form fields are not email semantics. A Wufoo form may have Field1, Field2, and Field5; an email request needs a recipient, sender, subject, and message body. A relay lets you decide what happens when the email field is blank, malformed, or intentionally absent.

It also lets you use an internal routing rule. For example, a “Sales” selection can notify sales@example.com, while a “Support” selection notifies support@example.com. You can preserve the entry ID in a custom header, add a reply-to address, strip unsafe HTML from free-text inputs, and prevent a retry from sending the same confirmation twice.

For the full request format and sending-domain setup, see the Volanea email API reference and setup guides.

How Wufoo WebHook payloads are shaped

Wufoo sends WebHook data as an HTTP POST containing a collection of field identifiers and submitted values. This is not a JSON event envelope by default. Treat it as form data and parse it accordingly with an application/x-www-form-urlencoded parser.

The exact field names depend on the form’s API IDs. Wufoo assigns each form field an API ID, commonly shaped like Field1, Field2, and so on. The field labels that your respondents see—such as “First name,” “Work email,” or “How can we help?”—are not the stable identifiers your code should rely on.

A typical parsed submission can look like this:

EntryId=42
EntryStatus=Submitted
DateCreated=2026-09-26+14%3A03%3A11
Field1=Avery+Nguyen
Field2=avery%40example.com
Field3=I%27d+like+to+request+a+demo.
Field4=Sales

After Express parses the request body, that becomes an object similar to:

{
  "EntryId": "42",
  "EntryStatus": "Submitted",
  "DateCreated": "2026-09-26 14:03:11",
  "Field1": "Avery Nguyen",
  "Field2": "avery@example.com",
  "Field3": "I'd like to request a demo.",
  "Field4": "Sales"
}

The example field mapping in this guide assumes:

Wufoo API IDForm label in this exampleUsed for
Field1Full namePersonalizing the confirmation and internal alert
Field2Email addressRecipient and reply-to address
Field3MessageEmail body content
Field4Team or topicRouting internal notifications
EntryIdWufoo entry identifierIdempotency and operational tracing

Do not copy these field IDs blindly. Open the form’s API Information in Wufoo and replace the example IDs with the IDs assigned to your own fields. If you edit a form later, verify the IDs and test the webhook again before changing production routing.

Optional form metadata is not your primary mapping strategy

Wufoo can optionally include field and form structures with entry data when you enable Include Field and Form Structures with Entry Data in the WebHook configuration. That can help during development or when your middleware needs to discover a form schema.

For production email routing, however, explicitly mapping known API IDs is usually safer. A label can be renamed by a form editor without the code owner noticing. A stable mapping table in your receiver makes schema changes deliberate, reviewable, and testable.

Set up the Wufoo WebHook

Before writing code, build and publish the form. You need its exact field API IDs, and you should decide whether every submission should send a confirmation, an internal alert, or both.

In Wufoo, configure the outbound WebHook for the individual form:

  1. Go to Forms.
  2. Locate the form you want to connect.
  3. In the new Wufoo experience, open the More menu and choose Integrations. In legacy Wufoo, use Edit and then Add integrations.
  4. Choose WebHook from the integration dropdown.
  5. Enter a public HTTPS endpoint, such as https://forms.example.com/webhooks/wufoo/contact.
  6. Add a WebHook Handshake Key if you use one.
  7. Optionally enable Include Field and Form Structures with Entry Data while you are developing or when your receiver has a specific need for the metadata.
  8. Save the integration.

Use a purpose-specific endpoint per form where practical. Separate routes such as /webhooks/wufoo/contact, /webhooks/wufoo/applications, and /webhooks/wufoo/event-registration make validation, field mapping, logging, and recipient routing much clearer than one generic endpoint with a large collection of conditional rules.

Use HTTPS and a public endpoint

Wufoo needs to reach your server over the public internet. localhost and a private network address cannot receive its production WebHook deliveries. During development, use a secure tunnel with a temporary HTTPS URL, then replace it with your real endpoint before publishing the form.

If your network firewall allowlists outbound integration IP addresses, Wufoo publishes IP addresses for integrations in its help documentation. Do not use IP allowlisting as your only control: infrastructure address ranges can change, and a receiver should still require an unguessable route or a valid shared secret before it performs an email send.

Working Node.js code: Wufoo POST to Volanea email

The following Express example is a complete server-side relay. It accepts Wufoo’s URL-encoded WebHook payload, maps the fields, prevents duplicate sends with a stable Idempotency-Key, and makes a Volanea REST API call.

Install Express:

npm install express

Set server-only environment variables before starting the process:

export VOLANEA_API_KEY="your-volanea-secret-api-key"
export WUFOO_HANDSHAKE_KEY="a-long-random-shared-value"
export VOLANEA_FROM="Example Team <hello@updates.example.com>"
export SALES_INBOX="sales@example.com"
export SUPPORT_INBOX="support@example.com"

Then create server.mjs:

import crypto from "node:crypto";
import express from "express";

const app = express();

// Wufoo WebHooks POST form-style fields, not a JSON event body.
app.use(express.urlencoded({ extended: false }));

const {
  VOLANEA_API_KEY,
  WUFOO_HANDSHAKE_KEY,
  VOLANEA_FROM,
  SALES_INBOX,
  SUPPORT_INBOX,
} = process.env;

if (!VOLANEA_API_KEY || !VOLANEA_FROM || !SALES_INBOX || !SUPPORT_INBOX) {
  throw new Error("Missing required server environment variables");
}

function escapeHtml(value = "") {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

function isEmail(value) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value || ""));
}

function fixedTimeEqual(left, right) {
  const a = Buffer.from(String(left || ""));
  const b = Buffer.from(String(right || ""));
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhooks/wufoo/contact", async (req, res) => {
  // The optional Handshake Key is a shared receiver check. Confirm the
  // exact key field delivered by your Wufoo configuration in a test request.
  // This route accepts conventional HandshakeKey casing and rejects requests
  // when a server-side key has been configured.
  const deliveredHandshakeKey = req.body.HandshakeKey;
  if (
    WUFOO_HANDSHAKE_KEY &&
    !fixedTimeEqual(deliveredHandshakeKey, WUFOO_HANDSHAKE_KEY)
  ) {
    return res.status(401).send("Invalid Wufoo webhook handshake key");
  }

  // Replace these API IDs with the IDs from this specific Wufoo form.
  const entryId = String(req.body.EntryId || "");
  const fullName = String(req.body.Field1 || "").trim();
  const email = String(req.body.Field2 || "").trim().toLowerCase();
  const message = String(req.body.Field3 || "").trim();
  const team = String(req.body.Field4 || "").trim().toLowerCase();

  if (!entryId) {
    return res.status(400).send("Wufoo EntryId is required");
  }

  if (!isEmail(email)) {
    // A malformed email should not become a Volanea send attempt.
    // Return a clear failure so it is visible in your webhook logs.
    return res.status(422).send("Submitted email address is invalid");
  }

  const destination = team === "support" ? SUPPORT_INBOX : SALES_INBOX;
  const safeName = escapeHtml(fullName || "there");
  const safeMessage = escapeHtml(message || "No message provided.")
    .replaceAll("\n", "<br>");

  const volaneaPayload = {
    from: VOLANEA_FROM,
    to: destination,
    replyTo: email,
    subject: `New Wufoo ${team || "contact"} request from ${fullName || email}`,
    html: `
      <h1>New form submission</h1>
      <p><strong>Name:</strong> ${safeName}</p>
      <p><strong>Email:</strong> ${escapeHtml(email)}</p>
      <p><strong>Topic:</strong> ${escapeHtml(team || "Not selected")}</p>
      <p><strong>Message:</strong><br>${safeMessage}</p>
      <p><small>Wufoo entry ID: ${escapeHtml(entryId)}</small></p>
    `,
    text: [
      "New form submission",
      `Name: ${fullName || "Not supplied"}`,
      `Email: ${email}`,
      `Topic: ${team || "Not selected"}`,
      `Message: ${message || "No message provided."}`,
      `Wufoo entry ID: ${entryId}`,
    ].join("\n"),
  };

  const response = await fetch("https://api.volanea.com/v1/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${VOLANEA_API_KEY}`,
      "Content-Type": "application/json",
      // Keep this stable for the same Wufoo entry. If Wufoo redelivers the
      // webhook after a timeout, Volanea can recognize the request as the
      // same send instead of creating a second internal notification.
      "Idempotency-Key": `wufoo-contact-${entryId}`,
    },
    body: JSON.stringify(volaneaPayload),
  });

  const responseText = await response.text();

  if (!response.ok) {
    console.error("Volanea send failed", {
      entryId,
      status: response.status,
      responseText,
    });
    return res.status(502).send("Email provider rejected the send");
  }

  console.info("Volanea email accepted", { entryId, responseText });
  return res.status(200).send("OK");
});

app.listen(3000, () => {
  console.log("Wufoo relay listening on port 3000");
});

This example intentionally sends an internal notification rather than an automatic email to the person who filled out the form. That is often the safest default for a contact form because the email recipient is controlled by your own configuration and the submitter’s address becomes the replyTo value.

Sending a confirmation to the submitter instead

If the form clearly tells people they will receive a confirmation, replace to: destination with to: email and use a static, transactional subject and body. Do not blindly echo all form fields back to the submitter, especially if the form contains private details, payment-related information, sensitive application answers, or internal routing values.

A confirmation payload can be as small as:

const confirmationPayload = {
  from: VOLANEA_FROM,
  to: email,
  subject: "We received your request",
  html: `<p>Hi ${safeName},</p><p>Thanks for contacting us. Our team has received your request.</p>`,
  text: `Hi ${fullName || "there"},\n\nThanks for contacting us. Our team has received your request.`,
};

Use a different idempotency key for a logically different message, such as wufoo-contact-confirmation-${entryId}. One Wufoo entry can legitimately create both an internal alert and a user confirmation, but each distinct send needs its own stable key.

Field mapping rules that prevent bad sends

A form integration should fail safely. The webhook receiver is the right place to decide which fields are required for email and what to do when the submission is incomplete.

Validate before calling Volanea

At a minimum, validate these items:

  • EntryId exists, because it is the durable event identity for your idempotency key and logs.
  • The recipient address is syntactically valid when you are sending a confirmation.
  • The chosen sender in VOLANEA_FROM is on a domain you have configured for sending.
  • Any routing value maps to an approved internal recipient rather than being used as a raw email address.
  • User-provided text is escaped before interpolation into an HTML email body.

The escapeHtml helper in the example is not cosmetic. Without it, a respondent could submit markup that becomes part of the email HTML. Escaping preserves the text while preventing the form content from controlling the message structure.

Keep routing server-controlled

Never create a routing rule such as to: req.body.Field4 unless that field is tightly controlled and validated against an allowlist. A public form field can be manipulated. If a visitor can make your server send messages to an arbitrary address, the form can become an open email relay.

Instead, map an approved option to a known address:

const recipients = {
  sales: SALES_INBOX,
  support: SUPPORT_INBOX,
};
const destination = recipients[team] || SALES_INBOX;

This approach is also easier to audit when your organization changes ownership of an inbox.

When this breaks: Wufoo-to-Volanea failure modes

A webhook integration spans multiple systems, so a successful form submission and a successful email are separate events. Build for ambiguity rather than assuming one HTTP request always means one email.

Wufoo retries can create duplicate send attempts

If Wufoo does not receive a successful response from your receiver—for example, because your process crashed after sending to Volanea but before responding—it may redeliver the webhook. Even without knowing whether the first delivery completed, your receiver must treat the same entry as a possible duplicate.

That is why the code uses a stable Volanea Idempotency-Key derived from the Wufoo EntryId. The key must be identical for repeated processing of the same logical message and different for different messages. Do not generate a random UUID on every webhook attempt; doing so defeats duplicate protection.

For high-value flows, add your own durable database record as well. Store EntryId, message type, time received, Volanea response identifier, and final processing status. Provider idempotency protects the API call; a local record helps you investigate and replay an entry deliberately.

Your receiver times out or returns too slowly

Wufoo is calling your endpoint synchronously. If your handler spends too long waiting for another service, it risks a timeout and a retry. Keep the route lean: parse, authenticate, validate, send, and respond.

For higher volume, move email work into a queue. The receiver can persist a uniquely keyed job and return a successful response after the job is safely stored. A worker then calls Volanea. The trade-off is that your queue must deduplicate by Wufoo EntryId and message type; otherwise you simply move the duplicate problem one layer deeper.

Expected fields are absent or renamed

Wufoo sends field API IDs, not your assumptions about field labels. A new version of the form may omit Field3, make an email field optional, add conditional logic, or change which questions appear to a respondent. Optional metadata may also be absent when you have not enabled the setting to include field and form structures with entry data.

Treat fields as potentially missing. Provide safe defaults for optional content, reject submissions that lack truly required sending data, and alert an operator when a schema expectation fails. Do not send undefined to a customer or silently route a message using a blank value.

The WebHook feature is unavailable on the account plan

Wufoo documents WebHooks under paid-plan integrations. If the account does not have access to the Integrations/WebHook option, there is no direct outbound HTTP route to your server from that Wufoo account. Do not pretend an API key in front-end code is an alternative.

In that situation, use middleware that supports Wufoo as a trigger and can make an authenticated HTTP request from a server-side credential store. Zapier or Make can serve as the bridge: trigger on a new Wufoo form entry, map the fields, then call a protected endpoint you control. Keep the Volanea key in that endpoint, not in a browser-accessible request configuration. The direct WebHook relay is generally more controllable because you own validation, logging, idempotency, and code review.

Volanea accepts the API request but mail is not delivered

An accepted API request is not the same as an inbox placement guarantee. A recipient can be suppressed, the recipient server can reject or defer the mail, or the address may be invalid. Use an authenticated sending domain, send transactional content only to people who expect it, and monitor events and suppression state in your email operations workflow.

For a public form, consider validating addresses before relying on them for confirmations. You can use the free email address verification tool as part of testing and operational checks, but do not use validation as a substitute for consent, suppression handling, or sound list practices.

Testing the integration safely

Test the exact form and exact field mapping before enabling customer-facing confirmations. A test that only hits your endpoint with hand-written JSON does not prove the Wufoo parser works, because Wufoo WebHooks post form-style fields.

Use this checklist:

  1. Submit the real Wufoo form with a test address you control.
  2. Log only non-sensitive diagnostic fields in development, such as EntryId, field names, and routing decision. Avoid logging full sensitive answers.
  3. Confirm that req.body includes the expected API IDs.
  4. Verify the receiver returns a successful HTTP response quickly.
  5. Confirm Volanea accepts the request and that the message has the expected sender, recipient, subject, and reply-to address.
  6. Submit the form twice with different data and confirm the two entries produce two separate sends.
  7. Replay the same stored payload or simulate a second delivery with the same EntryId and verify that the idempotency key prevents a second logical send.
  8. Test missing Field2, missing Field3, and an unrecognized Field4 value to ensure the failure behavior is intentional.

Use a staging sender and test recipients while developing. Once production is enabled, keep a small observability trail linking the Wufoo EntryId to your application log and Volanea response. That turns a vague report such as “I submitted the form but did not get an email” into a traceable sequence.

Operational and deliverability considerations

A form confirmation is transactional email, not a campaign. Its purpose is to acknowledge an action the recipient just took, deliver requested information, or set an expectation about the next step. Keep it concise and recognizable.

Use a stable sender identity such as Example Team <hello@updates.example.com>, not a visitor-supplied address in the from field. Put the visitor’s address in replyTo for internal alerts. This protects domain alignment and avoids the common mistake of trying to send mail “from” addresses your domain does not control.

Choose the right email pattern

For a contact form, two-message delivery is often best:

  • Internal alert: sent to an approved team inbox, with the submitter in replyTo.
  • Customer confirmation: sent to the address the respondent entered, with a short confirmation and realistic response expectation.

For a registration form, a confirmation email might include registration details or a calendar link. For an application form, an acknowledgement should avoid repeating sensitive answers. For support requests, the internal alert can create a ticket while the submitter receives a case-received message.

The form event is immediate, so the email should also be immediate. If your actual support response takes two business days, say that in the transactional confirmation instead of implying instant human follow-up.

Conclusion

To send email from Wufoo with Volanea, use Wufoo’s paid-plan WebHook as the trigger and a server-side relay as the secure translation layer. The concrete event is a form submission; Wufoo posts the resulting entry fields to your endpoint, and your endpoint maps those fields into a Volanea POST /v1/send request.

The reliable version of this integration does more than forward fields. It keeps the Volanea API key in server-only configuration, validates and escapes user input, uses explicit API-ID mappings, routes only to approved recipients, and attaches a stable idempotency key based on Wufoo’s EntryId. Those details protect against secret exposure, schema drift, retries, duplicate messages, and accidental open-relay behavior.

FAQ

Can Wufoo send directly to Volanea without a server?

Not securely through a native Volanea-Wufoo app, because no such native integration is available. Use Wufoo’s WebHook to call a server-side receiver, then have that receiver call Volanea with the API key stored privately.

What triggers the email in Wufoo?

A form submission triggers it. Wufoo creates the entry and sends the submitted field data as an HTTP POST to the WebHook URL configured for that specific form.

Is the Wufoo WebHook payload JSON?

No. Wufoo describes its WebHooks as HTTP POSTs containing a collection of field IDs and submitted values. Parse the request as URL-encoded form data, then transform it into JSON for Volanea’s REST API.

Which Wufoo field should I use as the idempotency key?

Use EntryId as the stable source identifier, usually combined with a message type. For example, use wufoo-contact-internal-42 for an internal alert and wufoo-contact-confirmation-42 for a separate confirmation from the same entry.

What if my Wufoo plan does not include WebHooks?

Use an automation middleware route such as Zapier or Make to receive the new Wufoo entry and call a protected endpoint you control. Keep the Volanea key on the protected server side, and retain the same validation and duplicate-prevention design.