Gleam can collect newsletter subscribers and campaign entries, while Volanea can send the email that follows. To send email from Gleam reliably, connect the two with a server-side webhook flow: Gleam posts an event to an endpoint you control, and that endpoint calls Volanea with your secret API key.

There is no native Volanea app, marketplace listing, or one-click plugin for Gleam. That is a feature of the architecture, not a gap to paper over with client-side code: a Volanea secret key must stay on infrastructure you control, never in a public campaign embed, browser script, or front-end configuration.

The correct Gleam trigger for this integration

The direct integration begins with a Subscribe to Newsletter action in a Gleam campaign. Gleam’s Integration Webhooks trigger for Subscribe actions when an entry is created, which makes this the appropriate route for a post-subscription welcome, coupon follow-up, download instructions, or lead-routing confirmation.

This detail matters because not every Gleam action is an email-consent event. A visitor who follows a social profile, watches a video, or completes a generic competition action has not necessarily agreed to receive email. Build the send around the explicit Subscribe action and make the message match the consent the person gave.

Gleam documents two webhook types:

  • Integration Webhooks are designed for Subscribe actions and can include custom fields and other data that may not sync to email-provider integrations.
  • Post Entry Webhooks are configured from the Post Entry tab of Competitions and Rewards and send a POST when an action is completed.

For an opted-in lead email, use an Integration Webhook connected to the campaign’s Subscribe to Newsletter action. Gleam notes that Integration Webhooks generally pass through its fraud filter before delivery, so they are not instant for most campaign types; the documented typical delay is five to ten minutes, except for Captures. That means this flow is excellent for a welcome, lead magnet, or next-step email, but it is not the right choice for an email that must appear immediately after a button press.

What the finished architecture looks like

The secure path has three hops:

  1. A visitor completes the Subscribe to Newsletter action in your Gleam campaign.
  2. Gleam sends a JSON POST payload to a webhook endpoint you operate.
  3. Your endpoint validates and de-duplicates the event, then sends an email through POST /v1/send on Volanea.

The important design decision is the boundary between Gleam and Volanea. Gleam sends campaign data to your endpoint. Your endpoint owns the email decision: whether the person is eligible, which template or content to send, what sender to use, how to record the result, and how to prevent a retry from becoming a duplicate message.

Do not attempt this flow from JavaScript loaded beside a Gleam widget. Any secret embedded in browser code can be copied by visitors, automated scanners, browser extensions, page caches, and anyone who views the page source. A browser also cannot be trusted to enforce consent, business rules, or duplicate controls.

A small serverless function, an API route in your existing app, or a dedicated webhook service is enough. The endpoint should be HTTPS-only, should return quickly, and should hold the Volanea key in its server-side secret manager or environment configuration.

Before you build: choose the email you actually need

A campaign subscriber does not always need the same email. Write down the event-to-message contract before you configure anything.

For example, a giveaway campaign might use this mapping:

Gleam event dataEmail decision
user.emailRecipient address
user.first_nameGreeting fallback when available
campaign.nameCampaign-specific subject or copy
campaign.keyStable campaign identifier for routing
entry.idIdempotency and duplicate prevention key
entry.actionConfirm that this is the intended subscription action
user.detailsOptional, campaign-specific personalization

Avoid treating user.details as a fixed schema. Gleam represents custom-field responses as an object keyed by the visible field label. If you rename a field from Favourite product to Favorite product, your code must account for the change. Field labels are useful for campaign operations, but they are less stable than deliberately managed API field names.

A practical strategy is to keep the send generic at first: use email address, first name, campaign name, and entry ID. Add custom-field personalization only after you have inspected real webhook examples from every active campaign.

Set up the Gleam side without exposing a mail key

First, create or update the campaign that will collect the opt-in. Add a Subscribe to Newsletter action and make the consent language specific about what the subscriber will receive. If you want to collect information beyond identity and email, configure the campaign fields intentionally rather than assuming a field will appear in every payload.

Gleam’s webhook capability for this use case is a Premium feature. Custom Fields are separately documented as available for Competitions and Rewards on the Business plan, so plan entitlement can affect both whether you can emit the webhook and which optional data you can collect. Confirm the capabilities of the account that owns the live campaign before depending on custom values in an email.

Next, configure an Integration Webhook with the URL for the endpoint you control. The URL should point to a dedicated route, such as:

https://hooks.example.com/gleam/subscriber/your-long-random-route-secret

The long random value is not your Volanea key. It is an inbound routing secret that helps prevent unsolicited traffic from casually reaching the endpoint. Store it as a server-side secret and configure the same value in the Gleam webhook URL. Avoid putting that webhook URL in public documentation, source code, client-side configuration, screenshots, or issue tickets.

Keep the Volanea API key entirely off the Gleam side. Gleam should know only the destination webhook URL. Your receiving service reads VOLANEA_API_KEY from a secret store or environment variable when it needs to call Volanea. That separation means a person with campaign-editing access cannot accidentally expose email-sending credentials in a widget, custom HTML block, or URL.

The Gleam webhook payload you should expect

Gleam sends a JSON POST request. Its published Integration Webhook example includes campaign, user, entry, reward, coupon, and social-link data. The pieces needed for a subscription email are typically campaign, user, and entry.

A representative payload has this shape:

{
  "campaign": {
    "name": "Spring Product Giveaway",
    "key": "a1XyD",
    "type": "Competition"
  },
  "reward": {
    "type": "Download",
    "code": "1234"
  },
  "coupon": {
    "type": "Coupon",
    "code": "1234"
  },
  "user": {
    "name": "Joe Bloggs",
    "first_name": "Joe",
    "last_name": "Bloggs",
    "email": "joe@example.com",
    "country": "Australia",
    "region": "Queensland",
    "city": "Bloggstown",
    "country_code": "AU",
    "actions_completed": 1,
    "details": {
      "I have read the terms and conditions": "true",
      "Postcode": 8282
    }
  },
  "entry": {
    "id": 244523423,
    "entry_method_id": 334222,
    "action": "Subscribe to our newsletter",
    "created_at": "2015-11-18 05:14:37 UTC",
    "type": "email_subscribe",
    "value": "Example user answer",
    "worth": 1,
    "landing_url": "https://example.com",
    "referring_url": "https://example.com"
  },
  "social_links": [
    {
      "provider": "twitter",
      "uid": "1345519622",
      "reference": "gleamapp"
    }
  ]
}

Treat this as a flexible event envelope, not a guarantee that every property will be populated. In particular, optional objects such as reward, coupon, social_links, and custom user.details values depend on the campaign configuration and entrant behavior. Your code should safely handle missing values.

The fields that should be considered essential for this welcome-email pattern are user.email, campaign.key, campaign.name, and entry.id. If the email is absent or malformed, do not send. Log the event with sensitive values redacted, return a controlled response according to your retry policy, and investigate the campaign configuration.

Working webhook-to-Volanea example

The following Node.js example receives the Gleam Integration Webhook, maps its documented fields, de-duplicates on campaign.key plus entry.id, and calls Volanea’s REST API. It uses Express and PostgreSQL because an in-memory set disappears when a server restarts and is not safe across multiple instances.

Install the dependencies in the service that hosts the endpoint:

npm install express pg

Set server-side environment variables in your host’s secret manager:

VOLANEA_API_KEY=sk_live_replace_with_your_secret_key
VOLANEA_FROM=hello@your-verified-domain.example
VOLANEA_FROM_NAME=Example Company
DATABASE_URL=postgres://...
GLEAM_WEBHOOK_ROUTE_SECRET=replace-with-a-long-random-value

Create a table once in PostgreSQL:

CREATE TABLE gleam_email_events (
  event_key TEXT PRIMARY KEY,
  received_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  volanea_response JSONB
);

Then deploy this endpoint:

import express from "express";
import pg from "pg";

const { Pool } = pg;
const app = express();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

app.use(express.json({ limit: "256kb" }));

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

app.post("/gleam/subscriber/:routeSecret", async (req, res) => {
  if (req.params.routeSecret !== process.env.GLEAM_WEBHOOK_ROUTE_SECRET) {
    return res.status(404).json({ error: "not_found" });
  }

  const { campaign = {}, user = {}, entry = {} } = req.body ?? {};
  const recipient = String(user.email ?? "").trim().toLowerCase();
  const campaignKey = String(campaign.key ?? "").trim();
  const entryId = String(entry.id ?? "").trim();

  // Require the fields that make this event uniquely identifiable and sendable.
  if (!recipient || !campaignKey || !entryId) {
    return res.status(400).json({ error: "missing_required_gleam_fields" });
  }

  // This route is intended for newsletter subscription events only.
  if (entry.type && entry.type !== "email_subscribe") {
    return res.status(202).json({ skipped: "not_an_email_subscribe_entry" });
  }

  const eventKey = `gleam:${campaignKey}:entry:${entryId}`;

  // Insert first. A retry with the same campaign and entry ID becomes a no-op.
  const inserted = await pool.query(
    "INSERT INTO gleam_email_events (event_key) VALUES ($1) ON CONFLICT DO NOTHING RETURNING event_key",
    [eventKey]
  );

  if (inserted.rowCount === 0) {
    return res.status(200).json({ duplicate: true, eventKey });
  }

  const firstName = String(user.first_name || user.name || "there").trim();
  const campaignName = String(campaign.name || "our campaign").trim();
  const rewardCode = req.body?.reward?.code ? String(req.body.reward.code) : "";
  const couponCode = req.body?.coupon?.code ? String(req.body.coupon.code) : "";

  const subject = `Thanks for subscribing to ${campaignName}`;
  const html = `
    <p>Hi ${escapeHtml(firstName)},</p>
    <p>Thanks for subscribing through <strong>${escapeHtml(campaignName)}</strong>.</p>
    ${couponCode ? `<p>Your coupon code: <strong>${escapeHtml(couponCode)}</strong></p>` : ""}
    ${rewardCode ? `<p>Your reward code: <strong>${escapeHtml(rewardCode)}</strong></p>` : ""}
    <p>We will send the next steps to this address.</p>
  `;
  const text = [
    `Hi ${firstName},`,
    "",
    `Thanks for subscribing through ${campaignName}.`,
    couponCode ? `Your coupon code: ${couponCode}` : "",
    rewardCode ? `Your reward code: ${rewardCode}` : "",
    "We will send the next steps to this address."
  ].filter(Boolean).join("\n");

  const volaneaPayload = {
    to: recipient,
    from: process.env.VOLANEA_FROM,
    fromName: process.env.VOLANEA_FROM_NAME,
    subject,
    html,
    text,
    headers: {
      "X-Source": "gleam-webhook",
      "X-Gleam-Campaign-Key": campaignKey,
      "X-Gleam-Entry-Id": entryId
    }
  };

  try {
    const response = await fetch("https://api.volanea.com/v1/send", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${process.env.VOLANEA_API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(volaneaPayload),
      signal: AbortSignal.timeout(8000)
    });

    const responseBody = await response.json().catch(() => ({}));

    if (!response.ok) {
      // Remove the reservation so a later Gleam retry can attempt the send again.
      await pool.query("DELETE FROM gleam_email_events WHERE event_key = $1", [eventKey]);
      return res.status(502).json({
        error: "volanea_send_failed",
        status: response.status
      });
    }

    await pool.query(
      "UPDATE gleam_email_events SET volanea_response = $2 WHERE event_key = $1",
      [eventKey, JSON.stringify(responseBody)]
    );

    return res.status(200).json({ accepted: true, eventKey });
  } catch (error) {
    await pool.query("DELETE FROM gleam_email_events WHERE event_key = $1", [eventKey]);
    return res.status(502).json({ error: "volanea_request_error" });
  }
});

app.listen(process.env.PORT || 3000);

This is field mapping rather than a blind relay:

  • Gleam user.email becomes Volanea to.
  • Your verified sender address becomes Volanea from.
  • Your sender display name becomes fromName.
  • Gleam campaign.name becomes part of the subject and message content.
  • Gleam user.first_name becomes the greeting, with user.name and then there as safe fallbacks.
  • Gleam entry.id and campaign.key form the persistent duplicate-control key.
  • Optional reward.code and coupon.code are included only when supplied.

Use a sender address from a domain you have already verified in Volanea. An unverified sender domain is rejected rather than silently accepted, so domain verification belongs in your pre-launch checklist. For endpoint details, templates, sending options, and event handling, see the Volanea email API reference and setup guides.

Authentication: where each secret belongs

The cleanest way to reason about authentication is to separate inbound and outbound credentials.

The Gleam webhook URL belongs in Gleam

Gleam needs the URL of your receiver. If you use a route secret, that secret appears only as part of the webhook URL configured in Gleam and in the receiving service’s secret configuration. It protects the inbound route from routine guessing, but it does not grant Volanea access.

Limit who can change the webhook destination. A modified webhook URL can divert subscriber data to an unauthorized system even though it cannot reveal the Volanea key.

The Volanea API key belongs only on your server

Store VOLANEA_API_KEY in the environment or secret manager for the webhook host. It should never be placed in:

  • A Gleam custom HTML block.
  • A public JavaScript bundle.
  • A front-end framework environment variable that is exposed to the browser.
  • A Zap field, campaign text field, or redirect URL.
  • A repository file committed to source control.

The API key authorizes email sending, so exposing it creates more than a data-leak risk. An attacker could send mail through your account, harm sender reputation, consume quota, and create an incident that is harder to diagnose because messages appear to originate from your legitimate infrastructure.

Rotate the key if it is exposed, then update the secret in the webhook host. Do not rely on replacing a browser value or changing a Gleam setting to remediate a leaked server credential.

When this breaks: handle the real failure modes

A campaign-to-email integration spans separate systems, networks, and queues. Design for partial success rather than assuming a single synchronous operation.

A Gleam retry creates a duplicate send

A webhook sender may repeat delivery when it does not receive a successful response, including cases where your endpoint completed work but the response was interrupted. That is why the example inserts gleam:${campaign.key}:entry:${entry.id} before calling Volanea.

If the same entry is delivered again, the primary-key conflict causes the endpoint to return 200 with duplicate: true rather than sending another email. The duplicate key is based on the campaign key and entry ID, not just the email address, because the same person may intentionally subscribe through different campaigns.

Do not deduplicate solely by recipient email. That strategy can accidentally suppress a legitimate campaign-specific email, particularly when an existing subscriber enters a later giveaway or redeems a separate reward.

The webhook times out

There are two timeout boundaries: Gleam waiting for your endpoint, and your endpoint waiting for Volanea. Keep request work short. Validate, reserve the event ID, send, store the result, and respond. Do not render a large report, call unrelated third-party APIs, or run a long database task on the webhook request path.

The example applies an eight-second timeout to the Volanea call. That number is a service-level choice, not a promise about either platform’s timeout policy. Tune it to leave enough time for your endpoint to produce a clear response before your upstream webhook delivery window closes.

The difficult case is an unknown outcome: Volanea may accept the request while the connection fails before your service receives the response. The durable event record is the starting point for resolving that ambiguity. In a high-volume production system, store a status such as pending, use an outbox worker, and reconcile uncertain sends against Volanea’s email events or send log before attempting another send.

Fields are missing because the campaign or plan differs

Never assume all Gleam payloads contain the same optional fields. Custom Fields are available for Competitions and Rewards on Gleam’s Business plan, and they appear under user.details only when the campaign is configured to collect them. A campaign without that configuration will not give your code a postcode, product preference, consent answer, or other custom value to personalize with.

Likewise, campaign type and action setup determine whether reward, coupon, upload, and social data exist. Make optional mapping explicit, as the example does for reward.code and coupon.code. If a field is operationally required, validate it before sending and route the event to an exception queue or alert rather than mailing incomplete information.

This is especially important when one webhook endpoint serves multiple campaigns. Maintain a small per-campaign configuration map keyed by campaign.key, with rules such as required fields, sender identity, template choice, and permitted entry type.

The recipient address is syntactically present but not useful

A non-empty string is not the same thing as a deliverable address or a valid email consent record. Gleam can collect email, but your service should still reject obviously blank or malformed input and ensure the campaign’s consent wording is appropriate for the email you plan to send.

For a higher-confidence pre-send check, use an email address verification tool in your lead-quality workflow. Verification can reduce obvious errors, but it does not replace consent, suppression handling, or bounce monitoring.

Volanea returns success but the person does not receive mail

An accepted API request is not the same as final inbox placement or delivery. Email can subsequently be skipped because the recipient is suppressed, unsubscribed, over quota, or otherwise ineligible; delivery can also fail downstream through a bounce or complaint.

Record the Volanea response, preserve your Gleam correlation values, and subscribe your own operational systems to Volanea delivery, bounce, and complaint events. A support team should be able to answer three separate questions: did Gleam emit the event, did your webhook accept it, and what happened to the email after Volanea accepted the send.

Make deliverability part of the integration design

A competition or giveaway can create fast bursts of new addresses. That makes sender identity and list hygiene especially important. Send from a verified domain, use a recognizable From name, and ensure the message immediately explains why the person is receiving it.

A good first email references the campaign, avoids generic marketing language, and gives the recipient a useful next action. For example, Thanks for subscribing through Spring Product Giveaway is more recognizable than an unexplained Welcome! subject line.

Keep campaign confirmation separate from ongoing marketing where your consent model requires it. A person may be entitled to receive reward instructions or a confirmation associated with a Subscribe action, while promotional follow-ups may require a distinct consent promise and unsubscribe handling. Your middleware is the correct place to encode those rules because it can evaluate the specific campaign and event type before it sends.

Test the full path before promoting the campaign

Do not launch based only on a successful HTTP response from your local code. Test the complete route with a real test subscription in Gleam and a mailbox you control.

Use this launch checklist:

  1. Confirm the campaign contains the intended Subscribe to Newsletter action and consent language.
  2. Confirm the Integration Webhook targets the production HTTPS endpoint, not a temporary development URL.
  3. Verify the Volanea sender domain and sender address before the campaign goes live.
  4. Submit a test subscription using a real inbox you control.
  5. Inspect the received Gleam payload in redacted logs and compare it with your mapping assumptions.
  6. Confirm the campaign.key, entry.id, recipient, and Volanea send response are stored together.
  7. Re-deliver the same payload in a test environment and confirm the endpoint returns a duplicate result without sending again.
  8. Test a payload with no optional reward, coupon, or custom-field values.
  9. Check the received email on desktop and mobile, including the plain-text alternative.
  10. Verify that delivery and bounce events can be traced back to the Gleam entry.

For test data, avoid copying a live subscriber’s full webhook body into a ticket or chat thread. Campaign payloads can contain email addresses, locations, custom answers, referral URLs, and social information. Redact or replace personal data before sharing logs.

Direct webhook versus Zapier

Gleam also supports Zapier for subscriber data. Its documented Zapier trigger is New Subscriber, which fires when someone completes the Subscribe action, and it requires the campaign to include that Subscribe action. Zapier can be a reasonable route when you need no custom server logic and the destination app supports the action you need.

For Volanea, the direct webhook-to-server route is usually the better fit when you need to call the REST API safely. It keeps the Volanea secret key in your infrastructure, gives you direct access to the original event envelope, and allows durable duplicate handling tied to Gleam’s entry.id.

Choose a middleware automation route only when it can safely store the Volanea credential, provides the fields you require, and gives you enough control over retries and duplicate prevention. Do not choose it just because it removes code; a no-code flow still needs the same consent, security, monitoring, and idempotency decisions.

Conclusion

The reliable way to send email from Gleam with Volanea is not a native plugin installation. It is a deliberate server-side integration: trigger on a Gleam Subscribe action, receive the documented webhook JSON, map only the fields you need, keep the Volanea key in a server secret, and de-duplicate with the campaign key plus entry ID.

That design remains understandable when campaigns evolve, optional custom fields disappear, traffic spikes, or a webhook delivery is repeated. It also gives you a clean operational trail from the Gleam entry to the Volanea email record—exactly what you need when a subscriber asks where their message is.

FAQ

Does Volanea have a native Gleam integration?

No. There is no native Volanea Gleam app, marketplace listing, or one-click plugin. Use Gleam’s webhook capability to send an event to a server you control, then call Volanea from that server.

What Gleam event should trigger the email?

For an opt-in email, use the Subscribe to Newsletter action with an Integration Webhook. The event is created when the subscriber completes that action, subject to Gleam’s webhook and fraud-filter processing.

Can I put my Volanea API key in Gleam?

No. Keep the Volanea API key only in your webhook host’s server-side environment or secret manager. Gleam should receive only the webhook destination URL, never the mail-sending credential.

Why did a subscriber receive two emails?

A repeated webhook delivery can happen when a response is delayed, interrupted, or retried. Prevent duplicates by storing a persistent key based on Gleam campaign.key and entry.id before you call Volanea.

Can I personalize emails with Gleam custom fields?

Yes, when the campaign collects them. Gleam places custom responses in user.details, but treat every custom field as optional and validate it before using it in a subject line, template variable, or segmentation rule.