Typeform can collect a lead, support request, RSVP, or application in seconds; the useful next step is to send email from Typeform without exposing credentials or relying on a manual export. The reliable architecture is Typeform → your server-side webhook endpoint → Volanea’s email API.

Typeform does not need a native Volanea marketplace app for this workflow. Its webhook capability can deliver a form-response event to an HTTPS endpoint that you control. That endpoint verifies the request, reads the submitted answers, decides whether an email should be sent, and makes the authenticated Volanea REST request.

This guide uses a completed Typeform submission as the trigger. It covers the actual Typeform webhook payload structure, a practical field-mapping approach, secure API-key storage, and the operational safeguards that matter once real people begin completing your forms.

The integration architecture

A Typeform response is not an email event by itself. It is an event containing answers, metadata, and a response token. Your integration needs to translate that event into an email request.

The flow has three parts:

  1. A respondent completes and submits a Typeform form.
  2. Typeform sends a form_response webhook payload to your HTTPS endpoint.
  3. Your endpoint verifies the Typeform signature, extracts the answers it needs, and sends the email through Volanea.

This design is preferable to putting an email API call in front-end JavaScript. The browser that displays a Typeform is not a secure environment for a sending key. A webhook relay also gives you a place to validate inputs, suppress duplicate notifications, log delivery requests, and choose different email templates based on the response.

For example, a consultation form might collect name, email, company, and topic. The relay can send:

  • a confirmation email to the respondent’s submitted address;
  • a notification email to the sales team; or
  • both messages, each with a different subject, recipient, and template.

The key point is that the Typeform event is the trigger, while your server defines the email policy. Do not blindly turn every field into HTML or assume every response contains every answer.

The Typeform trigger: a submitted form response

The concrete Typeform event to use is a webhook event with event_type set to form_response. Typeform sends it after a respondent submits a form. That is the event your webhook endpoint should accept.

A Typeform webhook payload has top-level event data and a form_response object. The exact answer objects vary by question type, but the fields most integrations use are consistent:

  • form_response.token is the unique token for that submitted response.
  • form_response.form_id identifies the source form.
  • form_response.submitted_at records when the form was submitted.
  • form_response.answers is an array of answer objects.
  • Each answer has a field object, including the question’s id, ref, and type.
  • The answer value appears in a type-specific property such as email, text, choice, number, or boolean.

A simplified payload for a form with name, email, and message fields looks like this:

{
  "event_id": "01HVEXAMPLEEVENT",
  "event_type": "form_response",
  "form_response": {
    "form_id": "AbCdEf",
    "token": "01HVEXAMPLERESPONSE",
    "landed_at": "2026-09-25T09:58:13Z",
    "submitted_at": "2026-09-25T10:01:42Z",
    "definition": {
      "id": "AbCdEf",
      "title": "Request a demo",
      "fields": []
    },
    "answers": [
      {
        "type": "text",
        "text": "Avery Lee",
        "field": { "id": "name_field", "ref": "contact_name", "type": "short_text" }
      },
      {
        "type": "email",
        "email": "avery@example.com",
        "field": { "id": "email_field", "ref": "contact_email", "type": "email" }
      },
      {
        "type": "text",
        "text": "We need a transactional email provider.",
        "field": { "id": "message_field", "ref": "request_message", "type": "long_text" }
      }
    ]
  }
}

The sample is deliberately representative rather than a form schema you should hard-code. A field ID is generated by Typeform and can change if a question is recreated. A field reference (ref) is the better integration contract because you can assign and maintain a meaningful value such as contact_email or request_message in the form configuration.

Use field references, not question wording

Do not map answers by question title such as “What is your email address?” Titles are content, and someone will eventually edit them for clarity, localization, or a campaign. Map by field reference instead.

Before deploying, assign stable references to every field the email workflow uses. A simple convention works well:

Form questionSuggested field referenceExpected value
Namecontact_nameanswer.text
Work emailcontact_emailanswer.email
Companycompany_nameanswer.text
Requestrequest_messageanswer.text
Consent checkboxemail_consentanswer.boolean

The event payload can include fields that your email logic does not need. Treat the incoming payload as untrusted input: select only the expected references, validate their values, and escape text before placing it in HTML.

Create the Typeform webhook

Typeform’s Webhooks API creates a webhook for a particular form. The endpoint is identified by a form ID and a webhook tag, which lets you name the subscription in a way that makes its purpose clear, such as volanea-production.

The request uses a Typeform personal access token or an appropriate OAuth access token. That Typeform credential is for administering the webhook; it is not the Volanea sending key.

curl --request PUT \
  --url "https://api.typeform.com/forms/AbCdEf/webhooks/volanea-production" \
  --header "Authorization: Bearer $TYPEFORM_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "url": "https://forms.example.com/webhooks/typeform",
    "enabled": true,
    "verify": true
  }'

Replace AbCdEf with the form ID and use a publicly reachable HTTPS URL. When verification is enabled, Typeform verifies the webhook URL during setup. Build the endpoint before enabling the production webhook, and make sure it can return a successful response without requiring a browser session, cookie, or interactive login.

Your endpoint should acknowledge a valid webhook quickly. It should not wait for a slow CRM lookup, a large database query, or downstream analytics before responding. If the send itself needs substantial processing, persist a job keyed by the response token and let a worker send the message asynchronously.

Confirm the event before sending live mail

Submit a test response through the published form rather than relying only on a manually constructed JSON example. Check these items in your endpoint logs:

  1. The event is a form_response event from the expected form_id.
  2. The expected field references appear in answers.
  3. The email answer is an address, not an empty or malformed value.
  4. The sender domain configured in Volanea is the domain you intend to use.
  5. The output email contains escaped user-provided text and no unreviewed internal data.

This test catches the most common integration mistake: building the code against a draft assumption about a field rather than the payload emitted by the live form.

Send the mapped response through Volanea

The following Node.js example is a webhook relay. It verifies Typeform’s HMAC signature before parsing the request, maps answer fields by field.ref, performs basic validation, and sends a confirmation email using Volanea’s REST email endpoint.

The code assumes these server-only environment variables exist:

  • TYPEFORM_WEBHOOK_SECRET: the secret associated with the Typeform webhook.
  • VOLANEA_API_KEY: the Volanea API key with permission to send mail.
  • VOLANEA_FROM: a verified sender, such as Forms <forms@example.com>.
import crypto from "node:crypto";
import express from "express";

const app = express();

// Keep the raw body intact: the Typeform signature covers the raw payload.
app.post("/webhooks/typeform", express.raw({ type: "application/json" }), async (req, res) => {
  const signature = req.get("Typeform-Signature") || "";
  const expected = "sha256=" + crypto
    .createHmac("sha256", process.env.TYPEFORM_WEBHOOK_SECRET)
    .update(req.body)
    .digest("base64");

  const signatureBuffer = Buffer.from(signature);
  const expectedBuffer = Buffer.from(expected);
  if (
    signatureBuffer.length !== expectedBuffer.length ||
    !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)
  ) {
    return res.status(401).send("Invalid Typeform signature");
  }

  const event = JSON.parse(req.body.toString("utf8"));
  if (event.event_type !== "form_response") {
    return res.status(204).end();
  }

  const response = event.form_response;
  if (response.form_id !== process.env.TYPEFORM_FORM_ID) {
    return res.status(403).send("Unexpected form");
  }

  // In production, make this a durable unique-record check using response.token.
  // If token was already processed, return 204 and do not send again.
  const answersByRef = Object.fromEntries(
    (response.answers || [])
      .filter((answer) => answer.field?.ref)
      .map((answer) => [answer.field.ref, answer])
  );

  const name = answersByRef.contact_name?.text?.trim() || "there";
  const email = answersByRef.contact_email?.email?.trim().toLowerCase();
  const message = answersByRef.request_message?.text?.trim() || "";
  const consent = answersByRef.email_consent?.boolean;

  if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    return res.status(422).send("Missing or invalid contact_email");
  }

  // Use an explicit consent rule where the form is collecting marketing permission.
  // A transactional acknowledgement of the submitted request has a different basis.
  const escapeHtml = (value) => value.replace(/[&<>"']/g, (character) => ({
    "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;"
  }[character]));

  const html = `
    <h1>Thanks, ${escapeHtml(name)}</h1>
    <p>We received your request and will respond shortly.</p>
    ${message ? `<p><strong>Your message:</strong><br>${escapeHtml(message)}</p>` : ""}
  `;

  const volaneaResponse = await fetch("https://api.volanea.com/v1/emails", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      from: process.env.VOLANEA_FROM,
      to: [email],
      subject: "We received your request",
      html,
      text: `Thanks, ${name}. We received your request and will respond shortly.${message ? ` Your message: ${message}` : ""}`,
      tags: [
        { name: "source", value: "typeform" },
        { name: "form_id", value: response.form_id }
      ]
    })
  });

  if (!volaneaResponse.ok) {
    const detail = await volaneaResponse.text();
    console.error("Volanea send failed", volaneaResponse.status, detail);
    return res.status(502).send("Email provider request failed");
  }

  // Store response.token as processed before returning success in a durable implementation.
  console.info("Typeform response processed", {
    responseToken: response.token,
    email,
    consent
  });
  return res.status(204).end();
});

app.listen(3000);

The relevant field mapping is visible in the answersByRef lookups: contact_email maps to answer.email, while text questions map to answer.text. Choice and boolean answers need different handling. For a multiple-choice question, inspect the actual test payload and map the appropriate choice property rather than assuming it is text.

For current request fields, authentication options, and sender setup, use the Volanea email API reference and setup guides. Keep the payload purpose-built: the confirmation message needs a recipient, sender, subject, and rendered content; it does not need the full Typeform response stored in the email body.

Keep the Volanea API key off Typeform and out of the browser

The Volanea API key belongs in the secret store or environment configuration of the middleware, not in Typeform fields, URL parameters, hidden fields, client-side code, or a public repository.

A native Typeform webhook is designed to deliver an HTTP request to your URL. It is not a safe place to embed an arbitrary third-party bearer token that would authorize email sending. Even if a tool appears to let you configure a URL or test payload, do not treat that configuration as a vault for a Volanea credential.

A secure setup separates credentials by responsibility:

CredentialWhere it belongsWhat it does
Typeform access tokenDeployment secret store or CI secretCreates and manages the webhook
Typeform webhook secretMiddleware secret storeVerifies that the incoming event is authentic
Volanea API keyMiddleware secret storeAuthorizes the outgoing email request
Sender domain configurationVolanea account and DNSEstablishes an approved From identity

Use environment variables locally only for development. In production, use the secret mechanism provided by your host, whether that is a cloud function secret manager, container platform secret, or encrypted deployment configuration. Rotate a key if it is accidentally logged, committed, included in a support ticket, or otherwise exposed.

Do not log request headers, raw webhook bodies containing sensitive form answers, or the Authorization header used for Volanea. Log narrow operational identifiers instead: the Typeform form ID, response token, destination domain, Volanea request result, and a redacted error code.

Design the email behavior before writing the template

A form submission can justify several kinds of mail, but they do not have the same consent and deliverability implications. Define the message class first.

Transactional acknowledgement

A direct acknowledgement such as “We received your support request” is usually tied to the action the respondent just took. Keep it narrow: confirm receipt, summarize the request if helpful, and state what happens next. Avoid adding unrelated product promotions merely because you have the recipient’s address.

Internal notification

An internal notification goes to your team rather than the respondent. Send it to a controlled address or a routing alias, and include enough context for triage: response token, form ID, name, email, selected topic, and a link to the record in your own system if one exists. Do not forward sensitive answers broadly.

Marketing follow-up

A marketing sequence is a separate decision. If the Typeform collects marketing permission, make the consent field explicit and store its value with the response. If consent is absent, false, or unavailable, do not silently treat form completion as a subscription.

This distinction also affects sender reputation. People expect a receipt after a request. They are less likely to welcome an unrelated campaign, and unwanted mail increases complaints, unsubscribes, and domain-level deliverability risk.

Validate recipients and protect your sender reputation

Typeform’s email question type provides useful format validation at collection time, but it does not prove that an address can receive mail or that it belongs to the person completing the form. Your relay should still reject absent, malformed, or clearly unusable addresses before making a send request.

For high-value flows, such as account invitations or lead-routing notifications, consider verifying addresses before creating a sequence or expensive downstream work. Volanea’s email address verification tool is useful when you need an additional check before a follow-up process. Verification is a signal, not a replacement for consent or for handling bounces and complaints.

Also protect against content injection. A respondent can type angle brackets, fake instructions, URLs, or deceptive text in a long-text field. Escape all user-provided data in HTML as the example does, and offer a plain-text email alternative. Never interpolate raw form text into an HTML template, email header, recipient list, or internal command.

Apply reasonable limits too. A 20,000-character message may be legitimate for a support form, but it may be unsuitable for an email notification. Truncate safely, store the full response in your application if needed, and include a secure internal link rather than forwarding every field to every inbox.

When this breaks: Typeform-to-email failure modes

A webhook integration is a distributed system, not a single atomic button. The failure can occur before Typeform reaches your endpoint, while the endpoint processes the event, or after the request reaches Volanea.

Retries can produce duplicate sends

Typeform may retry webhook delivery when it does not receive a successful response. A timeout after Volanea accepts the message is especially dangerous: your endpoint may not know whether the email send succeeded, while Typeform sees no completed webhook response and sends the same event again.

Use form_response.token as your idempotency key. Store it in a database table with a unique constraint before or as part of processing. If the same token arrives again, return a successful no-content response without sending another email. An in-memory Set is not enough for production because restarts, multiple instances, and deployments erase or split that state.

For critical sends, store a state machine such as received, sending, sent, and failed, plus the outbound provider request identifier when available. That makes it possible to distinguish “definitely not sent” from “send outcome unknown.”

Webhook timeouts and slow dependencies

Typeform expects your endpoint to respond; it is not a long-running job runner. A slow database, cold serverless function, DNS issue, or email API delay can lead to timeout and retry behavior.

Keep synchronous work small: validate the signature, check the form ID, create an idempotent job, and return a successful response. A queue worker can then render the template and call Volanea. If you choose to send inline for simplicity, set a short outbound timeout and make duplicate protection non-negotiable.

Monitor both sides of the hop. A healthy Typeform webhook response does not prove that the email was accepted, and a successful Volanea API response does not prove that a recipient read it. Track webhook receipt, email API outcome, delivery events where available, and business completion separately.

Missing answers and changing form configuration

An answer may be missing because a respondent skipped an optional question, took a conditional path that hid the question, abandoned a required pattern before a later question, or because the form was edited after the integration was built. Features, integrations, and data available to an account can also vary by Typeform plan, so do not base production logic on a field you have not observed in the payload for your own form and plan.

Handle absence deliberately. The example treats name and message as optional but rejects a missing email because it cannot send a confirmation without one. Your own form may instead route an internal notification when no email exists. Avoid code such as answersByRef.contact_email.email without optional checks; one omitted field can otherwise turn into a 500 error and trigger a retry loop.

Signature verification failures

A signature mismatch usually means the webhook secret is wrong, the raw request body was altered before HMAC verification, or a framework parsed and re-serialized JSON before your code inspected it. Verify against the raw bytes and compare signatures using a timing-safe comparison. Do not disable verification just to make a test request pass.

If you rotate or recreate a webhook, update the secret in the middleware deployment through your secret manager and test with a non-production recipient first.

Alternatives when you do not want to run middleware

A low-code automation platform can sit between Typeform and Volanea when maintaining an endpoint is not appropriate for the team. Typeform supports integrations through automation services such as Zapier and Make, where a new Typeform entry or response can start a scenario.

That option is useful for simple internal alerts and early prototypes, but assess it carefully before using it for customer-facing transactional email:

  • Confirm the platform can make the required authenticated Volanea HTTP request without exposing the key.
  • Confirm how it maps Typeform email and text answer values, especially after a form edit.
  • Confirm its retry behavior and whether it offers a durable deduplication key based on the response token.
  • Confirm where form data is stored, how long it is retained, and who can access it.
  • Confirm its error alerting and its behavior when the email provider is temporarily unavailable.

For a single form and low volume, an automation may be enough. For account emails, consent-sensitive flows, high volume, or workflows that require exact duplicate control, a small owned middleware service is usually easier to audit and evolve.

Production checklist for a dependable setup

Before treating the integration as production-ready, work through this checklist:

  • Use a stable Typeform field reference for every answer that drives logic.
  • Accept only form_response events for the expected form ID.
  • Verify the Typeform-Signature against the raw request body.
  • Store the Typeform response token with a uniqueness guarantee.
  • Keep the Volanea API key only in server-side secrets.
  • Use a verified sender identity and a purpose-appropriate From address.
  • Validate recipients and escape all submitted content used in HTML.
  • Build a plain-text version of each email.
  • Test required, optional, conditional, and malformed-answer paths.
  • Alert on failed webhook processing and failed email API requests.
  • Document the field references, template version, and owner of the form.

The last item is more valuable than it looks. Forms tend to change ownership over time. A short integration record prevents a harmless-looking question edit from breaking a customer notification months later.

Conclusion

To send email from Typeform reliably, use a Typeform form_response webhook as the trigger and let a server-side relay call Volanea. The relay is where security, field mapping, consent rules, duplicate protection, and error handling belong.

Start with one clearly scoped message, such as an acknowledgement of a submitted request. Map fields by Typeform reference, store the response token for idempotency, verify the webhook signature, and keep the Volanea API key outside anything a respondent can inspect. That foundation supports more sophisticated routing later without turning a simple form into an unreliable email source.

FAQ

Can Typeform send directly to Volanea without middleware?

Typeform can send a webhook to an HTTPS URL, but the safe pattern is a server-side relay that receives the webhook and calls Volanea with the API key. Do not put a sending credential in browser-visible code or form configuration.

What Typeform event should trigger the email?

Use the form_response webhook event. It represents a submitted Typeform response and includes form_response.answers, the response token, form ID, and submission metadata.

Which Typeform field should prevent duplicate emails?

Use form_response.token as the idempotency key. Persist it with a unique constraint and return success without sending again when Typeform retries an already processed response.

Why are some Typeform answers missing from my webhook payload?

A question may be optional, hidden by conditional logic, renamed or recreated, or unavailable in the path a respondent took. Inspect a real submitted payload and map by field.ref, with explicit fallback behavior for missing values.

Should a form confirmation also be a marketing email?

Usually no. A confirmation should be limited to the request the person just made. Send marketing follow-up only when you have collected and recorded the appropriate consent for that purpose.