Loyoly can generate valuable moments for customer communication: a loyalty action is completed, a referral is made, a reward is unlocked, or a member reaches a milestone. This guide explains how to send email from Loyoly with Volanea without pretending that a native Volanea app exists inside Loyoly.
Volanea does not provide a native Loyoly marketplace installation or plug-in. The practical supported route is to use Loyoly’s Zapier connection as the event source, pass the event to a server-side endpoint you control, and have that endpoint call Volanea’s REST email API. That design keeps the sending key private, gives you a place to validate event data, and makes duplicate prevention possible.
What this integration does—and does not do
This is an event-driven integration, not a contact-sync integration. Loyoly emits an event into Zapier; Zapier posts a structured payload to your middleware; middleware selects the recipient and message; Volanea delivers the email.
That distinction matters. A loyalty platform is the source of truth for loyalty actions and rewards. Volanea is the sending infrastructure. Your integration layer is the decision point that decides whether a particular loyalty event deserves an email, which template to use, and whether the event has already been sent.
The flow is:
- A member activity creates a New Event in Loyoly, which is the Zapier trigger used in this recipe.
- Zapier receives the Loyoly event and sends it to your HTTPS endpoint with a Webhooks by Zapier action.
- Your endpoint validates the webhook request, normalizes the fields, and checks an idempotency store.
- Your endpoint sends a REST request to Volanea.
- Volanea accepts the message for delivery and returns a message identifier.
- Your endpoint records the event ID and Volanea message ID before responding successfully to Zapier.
The integration does not mean Loyoly directly stores a Volanea key or makes a browser-side call to Volanea. It also does not turn every loyalty event into a marketing email automatically. You should explicitly choose the event types and messages that are appropriate for your consent model and local email rules.
The Loyoly trigger: New Event
For this build, the concrete event that starts a send is Loyoly’s New Event trigger in Zapier. In practice, this means you create a Zap, choose Loyoly as the trigger app, select New Event, connect the Loyoly account authorized to read events, and use a recent real event to test the field mapping.
An event is intentionally broader than a single loyalty use case. Depending on how your Loyoly program is configured, events can represent activities associated with a member, such as loyalty actions, referrals, points-related activity, or reward-related activity. Do not assume that every New Event has the same useful fields. A reward-related event may include a reward label or code, while another activity may only include the member and event metadata.
Filter before you send
Put a Zapier Filter step immediately after the Loyoly trigger when only one event class should send an email. For example, a "reward unlocked" email should not be sent for every event produced by the program.
Useful filter conditions typically include:
- An event type, name, or action value that identifies the loyalty activity you want.
- A member email field that exists and is not blank.
- A member status or program condition, where your Loyoly data provides one.
- A reward or coupon value when the message cannot be useful without it.
Test with multiple event samples, not only the first sample Zapier offers. Automation builders frequently retain fields that happened to exist in the sample, even when those fields are absent on another event subtype. That is one of the main reasons loyalty automations appear to work in testing and then fail for a subset of production events.
Treat the Zapier event as the integration contract
Loyoly’s Zapier trigger is the contract relevant to this recipe. Zapier presents the fields returned for the selected New Event sample; those values are what you map into the webhook action. The exact fields can vary by event type, connected store data, and Loyoly configuration, so do not hard-code a guessed nested Loyoly object in production.
Instead, create an explicit, stable payload in the Webhooks by Zapier action. This is better than forwarding every input field because it gives your endpoint one small schema to validate. It also avoids accidentally exporting more member data than the email operation needs.
Build the Zapier handoff
After the Loyoly New Event trigger and any Filter step, add Webhooks by Zapier and choose the POST action. Point it to an HTTPS endpoint that you own, such as https://email.example.com/hooks/loyoly.
Use JSON as the request payload type. Map values from the New Event output using Zapier’s field picker. The field labels in your Zap may differ from the example because Zapier displays the fields supplied by your actual Loyoly event; map the member email, member name, event identifier, event type, and any reward value from the matching displayed fields.
A deliberately small payload should look like this after Zapier has substituted the Loyoly fields:
{
"source": "loyoly",
"event_id": "evt_01HTY8KQ2A4Z7M9P6R3D",
"event_type": "reward_unlocked",
"occurred_at": "2026-10-08T14:22:31Z",
"member": {
"email": "alex@example.com",
"first_name": "Alex"
},
"reward": {
"name": "10% off your next order",
"code": "LOYAL10"
}
}
This is the payload shape your Zap sends to middleware, rather than an undocumented claim about a universal raw Loyoly webhook schema. In the Webhooks by Zapier fields, map event_id to the Loyoly event’s unique ID, event_type to its type/name field, occurred_at to the event time, and the member and reward values to the corresponding New Event fields available in your Zap.
If your specific event does not expose a reward code, remove reward.code and choose a message that does not require it. Sending a placeholder such as “Your code is undefined” is worse than declining the event with a visible error and fixing the mapping.
Add a shared webhook secret
Set a custom request header in the Webhooks by Zapier action, for example:
X-Loyoly-Relay-Secret: a-long-random-secret
Store that value as a Zapier secret or in the secure configuration available to the account operating the Zap. Your middleware compares it with its own server-side secret. This does not replace HTTPS, but it prevents an arbitrary party who discovers the endpoint URL from submitting accepted events.
Avoid putting the Volanea API key in this Zapier request, in a query string, or in the JSON body. The Zap should authenticate only to your relay. The relay alone authenticates to Volanea.
Why a middleware endpoint is the right security boundary
A direct browser request to an email API is not an option. Any key exposed in front-end JavaScript, a public mobile build, a visible URL, or a client-accessible configuration file can be copied and used to send mail from your account. That can create abuse, damage domain reputation, and produce an unexpected bill.
Loyoly’s Zapier integration is designed to pass event data to automation steps; it is not a secure secret-management substitute for issuing unrestricted email-sending credentials to third parties. Keep the Volanea API key in the secrets facility of your server platform: for example, a managed secret store, an encrypted environment variable configured in your hosting provider, or an equivalent server-only secret mechanism.
The middleware can be small. A Cloudflare Worker, serverless function, container service, or conventional application route can all work. What matters is that it runs server-side, receives HTTPS traffic, can read a secret without returning it to the caller, and has persistent storage available for idempotency records.
Minimum responsibilities of the relay
Your relay should do more than forward a request. At minimum, it should:
- Verify the
X-Loyoly-Relay-Secretheader before processing a payload. - Validate that
event_id,event_type, andmember.emailare present and plausible. - Allow only event types that you intentionally configured for email.
- Check whether the event has been processed already.
- Construct the recipient, subject, and HTML from trusted server-side rules.
- Call Volanea with the API key stored only in server configuration.
- Record the accepted send result and return a 2xx response only after the operation is safely handled.
This boundary also lets you change messaging without editing an automation in multiple places. For example, you can switch from a plain HTML message to a Volanea template or alter a subject line at the relay while leaving the Loyoly trigger unchanged.
Map the Loyoly event into a Volanea email
The important mapping is not merely technical; it controls the message’s meaning. A loyalty event should carry an event-specific email, not a generic blast. Use the member email as the recipient, and use the event type to select a server-owned template or message branch.
Here is the field mapping used by the example payload:
| Relay input | Volanea email value | Why it is used |
|---|---|---|
member.email | to | The loyalty member’s delivery address. |
member.first_name | HTML content | Personalization; escape before rendering. |
event_type | template/subject selection | Ensures only allowed event classes produce mail. |
reward.name | subject and HTML content | Explains what the member received. |
reward.code | HTML content | Includes a redemption code when available. |
event_id | idempotency record and custom metadata | Prevents retries from sending the same message twice. |
occurred_at | custom metadata or audit record | Supports support investigations and reporting. |
The following Node.js handler shows the complete handoff. It assumes the Volanea REST email endpoint is POST /v1/emails, using Bearer authentication and the common from, to, subject, and html email payload. Confirm the currently supported request fields and sending-domain setup in the email API reference and setup guides before deploying, particularly if you use templates, tags, or custom headers.
import crypto from "node:crypto";
const VOLANEA_API_KEY = process.env.VOLANEA_API_KEY;
const RELAY_SECRET = process.env.LOYOLY_RELAY_SECRET;
const FROM_EMAIL = "rewards@updates.example.com";
const FROM_NAME = "Example Rewards";
function escapeHtml(value = "") {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function safeEqual(a, b) {
if (!a || !b) return false;
const left = Buffer.from(a);
const right = Buffer.from(b);
return left.length === right.length && crypto.timingSafeEqual(left, right);
}
// Replace these two functions with Redis, Postgres, KV, or another durable store.
async function alreadyProcessed(eventId) { return false; }
async function recordProcessed(eventId, volaneaMessageId) {
console.log({ eventId, volaneaMessageId });
}
export async function handleLoyolyWebhook(request) {
const suppliedSecret = request.headers.get("x-loyoly-relay-secret");
if (!safeEqual(suppliedSecret, RELAY_SECRET)) {
return Response.json({ error: "unauthorized" }, { status: 401 });
}
const event = await request.json();
const email = event?.member?.email?.trim().toLowerCase();
const eventId = event?.event_id;
const eventType = event?.event_type;
if (!eventId || !email || !eventType) {
return Response.json({ error: "missing event_id, event_type, or member.email" }, { status: 422 });
}
if (eventType !== "reward_unlocked") {
return Response.json({ ignored: true, reason: "event type not enabled" }, { status: 200 });
}
if (await alreadyProcessed(eventId)) {
return Response.json({ duplicate: true, event_id: eventId }, { status: 200 });
}
const firstName = escapeHtml(event.member.first_name || "there");
const rewardName = escapeHtml(event.reward?.name || "a new reward");
const rewardCode = escapeHtml(event.reward?.code || "");
const subject = `You unlocked ${event.reward?.name || "a new reward"}`;
const html = `
<p>Hi ${firstName},</p>
<p>You unlocked <strong>${rewardName}</strong>.</p>
${rewardCode ? `<p>Your code: <strong>${rewardCode}</strong></p>` : ""}
<p>Thanks for being a member.</p>
`;
const volaneaResponse = await fetch("https://api.volanea.com/v1/emails", {
method: "POST",
headers: {
"Authorization": `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
from: { email: FROM_EMAIL, name: FROM_NAME },
to: [{ email }],
subject,
html,
metadata: {
source: "loyoly",
loyoly_event_id: eventId,
loyoly_event_type: eventType,
loyoly_occurred_at: event.occurred_at || ""
}
})
});
const result = await volaneaResponse.json();
if (!volaneaResponse.ok) {
console.error("Volanea send failed", result);
return Response.json({ error: "email provider rejected send" }, { status: 502 });
}
await recordProcessed(eventId, result.id);
return Response.json({ accepted: true, event_id: eventId, message_id: result.id });
}
The code intentionally creates email HTML on the server, escapes event-derived content, and allows only reward_unlocked. If your Loyoly event names use a different value, update the allow-list after checking actual Zap test data. Do not use an unrestricted event value as a subject, template identifier, or HTML fragment.
Configure Volanea before testing the Zap
An API call can be syntactically correct and still be a poor production implementation if the sender identity is not configured. Before activating the Zap, verify the domain you use in FROM_EMAIL, complete the necessary domain authentication in Volanea, and decide which address handles replies.
For loyalty-related transactional messages, use a recognizable sender such as rewards@updates.example.com or hello@example.com, provided that the domain is authenticated and the address has an intentional reply-handling policy. A reward email that invites a customer to reply should not route replies into an unmonitored mailbox.
Separate transactional events from broad promotion
A message confirming a reward or delivering a member-specific code may be operationally expected by the member. A recurring promotion to all members is a different class of email and may require different consent, segmentation, and unsubscribe treatment.
Keep these policies explicit:
- Send only to a valid member email that your program is authorized to contact.
- Include any legally required identification and unsubscribe mechanism for the message category and recipient location.
- Do not use a loyalty event as a reason to re-enable marketing for an unsubscribed recipient.
- Keep reward fulfillment messages narrowly related to the action that generated them.
- Use a verified sending domain and monitor bounces, complaints, and delivery results.
If you are deciding whether an event volume belongs on a transactional stream or a campaign workflow, review plans and what sending actually costs alongside your expected event volume, retry behavior, and retention needs.
When this breaks: failures specific to the Loyoly-to-Zapier hop
The most common failure is not that Volanea cannot send email. It is that the event changes shape, is retried, or takes too long at an earlier hop. Design the integration for those conditions before a loyalty campaign makes them visible.
Retries can create duplicate email
Automation systems can retry a webhook action when a destination times out, returns a 5xx response, or has an intermittent network failure. The first request may have reached your relay and even reached Volanea, while the caller did not receive the response. On retry, a naive implementation sends a second email.
Use the Loyoly event’s unique ID as the idempotency key. Store it in a durable database with a unique constraint before or together with the send state. A robust record has statuses such as processing, sent, and failed, plus the Volanea message ID. The unique constraint—not an in-memory JavaScript variable—is what protects you when two retries arrive concurrently.
If you cannot obtain a stable event ID from the New Event output, construct a fallback key from stable attributes such as the member ID, event type, and event timestamp, but treat that as less reliable. Ask whether the Loyoly event exposes an ID before launching an automation that can have material volume.
Webhook timeouts create ambiguous results
Do not make the Zapier request wait on slow downstream work, multiple database queries, or a long template-rendering process. A webhook timeout can cause a retry even when the original task continues running.
For a higher-volume setup, acknowledge the validated request quickly after durably enqueueing a job. A separate worker sends through Volanea and updates the idempotency record. For a simpler synchronous setup, keep the route fast, set a sensible outbound timeout, and make duplicate handling correct. Never return success before you have either persisted the job or completed a safely deduplicated send.
Some event fields may not exist on every event or configuration
A field appearing in Zapier’s test sample is not proof that it exists for every New Event. Reward codes, member names, timestamps, and metadata can be absent for particular activities or depend on how the Loyoly program and connected commerce stack are configured.
Validate required fields at the relay. Return a 422 response for data that makes the email impossible to send safely, such as a missing recipient. For optional fields, use a purposeful fallback: “You unlocked a new reward” is acceptable; an empty code block is not. Maintain an alert or error queue for rejected payloads so missing-field errors are discovered promptly.
Invalid, suppressed, or malformed addresses
Loyalty data is not a guarantee that an address is deliverable. Trim and normalize the email address, reject clearly malformed values, and respect suppression information from your sending system. Do not repeatedly retry a permanent address failure as if it were a transient webhook issue.
An address verification step can be useful before adding imported members or before a major campaign, but it should not override consent or suppression decisions. Volanea’s free address verification tool can help assess address quality; it is not a substitute for bounce handling and permission controls.
Observability and support workflow
Store enough data to answer the support question that inevitably arrives: “I earned a reward; where is my email?” At a minimum, record the Loyoly event ID, event type, recipient email or a privacy-conscious hash, event timestamp, relay receive time, Volanea message ID, and final status.
Use the event ID as the shared lookup key across systems. When a customer reports an issue, first find the Loyoly event in Zapier history, then locate the relay log by its event ID, and finally inspect the Volanea message result using the stored message ID. This sequence distinguishes four different problems: no loyalty event, no automation task, rejected relay payload, or an email delivery issue after acceptance.
Recommended test matrix
Do not activate the automation after one happy-path test. Test these cases in a non-production program or with internal recipients:
- A qualifying New Event with a complete member and reward payload.
- A non-qualifying New Event, which should be filtered or return an intentional ignored response.
- A qualifying event with no reward code, which should use the chosen fallback.
- A missing email, which should be rejected and logged without calling Volanea.
- The same event posted twice, which should result in one Volanea send.
- A simulated Volanea 4xx response, which should surface as a configuration or data issue.
- A temporary Volanea or network failure, which should be retried only after idempotency behavior is confirmed.
Also inspect the received message in a real inbox. Check the sender name, subject, mobile rendering, reward-code visibility, link destinations, reply handling, and whether the email is understandable without the customer remembering every loyalty-program detail.
Alternatives to the relay pattern
A serverless relay is usually the best balance of control and simplicity, but it is not the only architecture. The right option depends on volume, engineering capacity, and how much message logic belongs outside the automation builder.
A Zapier-only path can use a Webhooks by Zapier request directly to an email API, but it is a weaker option because it places a high-value sending credential in automation configuration and makes idempotency logic awkward. Use it only if your organization has evaluated the credential exposure and has no safer execution environment.
Make can serve a similar orchestration role if that is the automation platform your team already operates. The same principles apply: keep the Volanea key in a protected connection or server-side secret, construct a narrow schema, filter event types, and implement a durable duplicate check outside a transient scenario run when duplicates are costly.
For teams with an existing integration service, connect Zapier to that service rather than creating a separate loyalty-specific codebase. Add a /hooks/loyoly route, place loyalty event processing on a queue, and reuse your standard email, consent, audit, and alerting components.
A practical launch checklist
Before turning the Zap on for all members, verify the full chain:
- Loyoly’s Zapier account is connected and the New Event trigger returns a current test event.
- The Zap filters to the exact event types intended to send email.
- The Webhooks by Zapier action posts the explicit JSON schema to an HTTPS endpoint.
- The relay secret is configured on both the Zapier request and the server, without appearing in client code.
- The Volanea API key exists only in server-side secret storage.
- The From domain is configured for sending and the reply address is monitored or intentionally handled.
- A persistent idempotency store uses the Loyoly event ID as a unique key.
- Missing optional fields have tested fallbacks; missing required fields are rejected visibly.
- Logs connect the Loyoly event ID to the Volanea message ID.
- Consent, suppression, unsubscribe, and content requirements have been reviewed for the message type.
With those controls in place, the integration remains understandable as it grows. Loyoly continues to own the customer action, Zapier starts the workflow, your relay owns business logic and secrets, and Volanea owns the email send.
FAQ
Does Volanea have a native Loyoly integration?
No. Volanea does not ship a native Loyoly app, marketplace listing, or plug-in. Use Loyoly’s Zapier connection to send the New Event data to a secure middleware endpoint, then send through Volanea’s REST API.
What Loyoly event should trigger the email?
Use Loyoly’s New Event Zapier trigger, then filter it to the event type that represents the loyalty moment you want to communicate. Test the actual event fields from your program because available data can vary by event type and configuration.
Where should the Volanea API key be stored?
Store it only in server-side secret storage used by your relay, such as an encrypted environment variable or managed secret store. Do not put it in browser code, a public configuration object, a URL, or the payload sent from Zapier.
How do I stop duplicate reward emails?
Persist the Loyoly event ID in a database or key-value store with a unique constraint, and treat a repeated ID as already processed. This protects against webhook retries, timeouts, and concurrent deliveries.
What happens when a Loyoly event is missing a reward code?
Make the code optional only if the message remains useful without it. Use a fallback message, or reject and log the event if a code is required for fulfillment. Do not send a partially rendered message with blank or placeholder values.