Recharge can tell your systems when a subscription changes, but it is not an email-delivery service. To send email from Recharge reliably with Volanea, use Recharge’s webhook events as the trigger and place a small server-side relay between Recharge and the Volanea REST API.

That architecture matters. Recharge webhooks provide event notifications, while an email API needs an authenticated request with a recipient, sender, subject, and rendered content. A relay gives you the place to map data, retrieve a customer email when the event does not include it, keep credentials private, and make duplicate-send decisions deliberately.

The integration at a glance

There is no native Volanea app, Recharge marketplace listing, or one-click connector to install. The practical integration is a webhook-to-API workflow:

  1. A Recharge event occurs, such as a subscription being created.
  2. Recharge posts the event payload to an HTTPS endpoint you control.
  3. Your endpoint validates the inbound request and records the event ID.
  4. The endpoint maps the Recharge subscription data to an email payload.
  5. The endpoint calls Volanea’s REST email endpoint using a server-side API key.
  6. Volanea accepts the message for delivery, and your application records the result.

For this guide, the concrete trigger is Recharge’s subscription/created webhook topic. It is a useful example because it supports a common lifecycle message: confirmation that a customer has started a subscription. The same pattern applies to other Recharge webhook topics, including subscription updates, cancellations, and charge-related events; only the trigger-specific mapping and business rules change.

The central rule is simple: do not make a browser, storefront theme, or client-side Recharge integration call the email API. The webhook arrives server-to-server, and the Volanea request must stay server-to-server too.

What Recharge actually sends when a subscription is created

Recharge webhooks notify an external HTTPS endpoint after an event in Recharge. For a subscription-created workflow, configure a webhook subscription for the subscription/created topic in Recharge’s webhook configuration for the store/API version you use.

A subscription webhook represents the subscription resource. The exact fields can evolve with Recharge API versions and store configuration, so treat the payload as event data rather than as a complete customer profile. A representative subscription-created payload has the following shape:

{
  "id": 84200123,
  "address_id": 7100456,
  "customer_id": 3500789,
  "created_at": "2026-10-12T14:31:09",
  "updated_at": "2026-10-12T14:31:09",
  "status": "ACTIVE",
  "product_title": "Monthly Coffee Subscription",
  "variant_title": "Whole Bean",
  "sku": "COFFEE-WB-MONTHLY",
  "quantity": 1,
  "charge_interval_frequency": "30",
  "order_interval_frequency": "1",
  "order_interval_unit": "month",
  "next_charge_scheduled_at": "2026-11-11",
  "properties": []
}

The important field for this example is customer_id, not an assumed email property. A subscription event can identify the customer without carrying every customer attribute your template needs. That is why the relay below retrieves the customer record through Recharge before it sends mail.

Decide what the event means before writing code

A subscription/created event is not automatically permission to send any type of message. It is usually appropriate for an operational confirmation about the subscription the customer just created. It is not a substitute for marketing consent.

Before enabling the webhook, decide the message’s category and its sending rules:

  • Transactional confirmation: state that a subscription was created, identify the product, and provide account or support information.
  • Service notification: tell the customer about a failed charge, skipped order, cancellation, or upcoming renewal when that is necessary to operate the service.
  • Marketing campaign: only send when your consent, suppression, and jurisdictional requirements allow it; do not infer consent from subscription creation alone.
  • Internal alert: send an operations email to your team for exceptions, high-value subscriptions, or manual-review conditions.

This separation prevents a technically successful webhook integration from becoming a deliverability or compliance problem. It also makes template design clearer: the customer confirmation should describe the action that caused the email, not attempt to be a generic promotional blast.

Why a middleware relay is required

Recharge webhooks are outbound event notifications. They are not a general-purpose request composer for another vendor’s API. In particular, the email request needs an Authorization header containing the Volanea API key and a JSON schema that differs from Recharge’s subscription schema.

A relay can be a Cloudflare Worker, AWS Lambda, Vercel function, container endpoint, or conventional application route. It needs only a few responsibilities, but each one is important:

  • receive Recharge’s POST quickly over HTTPS;
  • authenticate or verify the incoming webhook according to Recharge’s configured verification method and current documentation;
  • deduplicate the delivery before sending email;
  • look up customer data if the event lacks the recipient address;
  • build the Volanea request from a strict allowlist of fields;
  • return a successful response only after the event has been safely recorded or queued.

You can also build the relay in Zapier or Make when the workflow is simple. Those tools can receive a Recharge trigger and make an HTTP request, but they still need secure credential storage, deduplication logic, and a plan for incomplete event fields. For production transactional mail, code or a workflow platform with durable storage is generally easier to audit.

Do not put the Volanea key in Recharge or the storefront

The Volanea API key does not belong in client-visible JavaScript, a theme setting, a checkout extension, a public automation URL, or a Recharge custom field. Anyone who can inspect that value could send mail through your account.

In the direct webhook architecture, Recharge stores the destination webhook URL; the Volanea key lives only in the relay’s encrypted server-side secret store. For example, use Worker secrets, Lambda environment secrets backed by a secret manager, or Vercel encrypted environment variables. Store the Recharge API access token there as well if the relay must fetch customer data.

Rotate keys on a schedule and whenever an administrator or deployment credential may have been exposed. Give the Recharge token only the scopes required to read the customer information needed by the notification. The least-privilege decision is not just a security preference: it reduces what an email-sending integration can expose if its runtime is compromised.

Build the subscription-created email flow

The following example uses a Worker-style JavaScript handler because it is compact and illustrates the full server-side hop. The design is portable: replace env.EVENTS with a database or queue, and replace the request/response wrapper with your framework’s equivalent.

The example assumes these protected environment variables:

Secret or variablePurpose
VOLANEA_API_KEYAuthorizes the Volanea REST email request.
VOLANEA_SEND_URLThe Volanea email-send endpoint from your account’s API documentation.
RECHARGE_API_TOKENReads the Recharge customer record when email is not in the event.
RECHARGE_API_VERSIONPins the Recharge API version used for customer lookup.
MAIL_FROMA verified Volanea sender, such as subscriptions@example.com.
MAIL_REPLY_TOA monitored support or subscription-help inbox.
WEBHOOK_PATH_SECRETA high-entropy secret embedded only in the webhook URL, used as an additional gate.

Use the endpoint, authorization scheme, and message fields documented in the Volanea email API reference and setup guides for your account. In the code, VOLANEA_SEND_URL is deliberately an environment variable so the deployed service is pinned to Volanea’s current documented endpoint rather than a copied URL hidden in application code.

// Example Worker-style webhook relay.
// Route this only at: POST /recharge/<WEBHOOK_PATH_SECRET>
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (request.method !== "POST" ||
        url.pathname !== `/recharge/${env.WEBHOOK_PATH_SECRET}`) {
      return new Response("Not found", { status: 404 });
    }

    // Verify Recharge's current webhook signature/header here, using the
    // verification mechanism documented for your Recharge webhook setup.
    // A secret path is an extra control, not a replacement for signature validation.
    const subscription = await request.json();

    if (!subscription?.id || !subscription?.customer_id) {
      return Response.json({ error: "Missing subscription id or customer id" }, {
        status: 400
      });
    }

    // A durable unique key is essential: Recharge can retry a webhook.
    // The storage layer must make `eventKey` unique atomically.
    const eventKey = `subscription-created:${subscription.id}`;
    const inserted = await env.EVENTS.insertIfAbsent({
      key: eventKey,
      subscriptionId: String(subscription.id),
      receivedAt: new Date().toISOString(),
      status: "processing"
    });

    if (!inserted) {
      // We already accepted or processed this business event. Do not resend.
      return Response.json({ ok: true, duplicate: true }, { status: 200 });
    }

    // Subscription webhook payloads should not be assumed to include email.
    const customerResponse = await fetch(
      `https://api.rechargeapps.com/customers/${subscription.customer_id}`,
      {
        headers: {
          "X-Recharge-Access-Token": env.RECHARGE_API_TOKEN,
          "X-Recharge-Version": env.RECHARGE_API_VERSION,
          "Accept": "application/json"
        }
      }
    );

    if (!customerResponse.ok) {
      await env.EVENTS.markFailed(eventKey, "Recharge customer lookup failed");
      return new Response("Retry later", { status: 503 });
    }

    const customerEnvelope = await customerResponse.json();
    const customer = customerEnvelope.customer ?? customerEnvelope;
    const recipient = customer.email;

    if (!recipient) {
      await env.EVENTS.markFailed(eventKey, "Customer has no email address");
      return Response.json({ ok: true, suppressed: "no-recipient" }, { status: 200 });
    }

    const product = escapeHtml(subscription.product_title || "your subscription");
    const frequency = escapeHtml(
      `${subscription.order_interval_frequency || ""} ${subscription.order_interval_unit || ""}`.trim()
    );

    // Field mapping: Recharge customer/subscription -> Volanea message JSON.
    const volaneaPayload = {
      from: env.MAIL_FROM,
      to: [recipient],
      reply_to: env.MAIL_REPLY_TO,
      subject: `Your subscription is active: ${subscription.product_title || "Subscription"}`,
      html: `
        <p>Hi ${escapeHtml(customer.first_name || "there")},</p>
        <p>Your subscription for <strong>${product}</strong> is now active.</p>
        <ul>
          <li>Subscription ID: ${escapeHtml(String(subscription.id))}</li>
          <li>Quantity: ${escapeHtml(String(subscription.quantity || 1))}</li>
          <li>Delivery frequency: ${frequency || "See your account for details"}</li>
          <li>Next charge date: ${escapeHtml(subscription.next_charge_scheduled_at || "See your account")}</li>
        </ul>
        <p>If you need help, reply to this email.</p>
      `.trim(),
      text: [
        `Hi ${customer.first_name || "there"},`,
        "",
        `Your subscription for ${subscription.product_title || "your subscription"} is now active.`,
        `Subscription ID: ${subscription.id}`,
        `Quantity: ${subscription.quantity || 1}`,
        `Delivery frequency: ${frequency || "See your account for details"}`,
        `Next charge date: ${subscription.next_charge_scheduled_at || "See your account"}`
      ].join("\n"),
      tags: [
        { name: "source", value: "recharge" },
        { name: "event", value: "subscription_created" }
      ]
    };

    const sendResponse = await fetch(env.VOLANEA_SEND_URL, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${env.VOLANEA_API_KEY}`,
        "Content-Type": "application/json",
        "Accept": "application/json"
      },
      body: JSON.stringify(volaneaPayload)
    });

    const sendBody = await sendResponse.text();
    if (!sendResponse.ok) {
      await env.EVENTS.markFailed(eventKey, `Volanea: ${sendResponse.status} ${sendBody}`);
      return new Response("Retry later", { status: 503 });
    }

    await env.EVENTS.markSent(eventKey, sendBody);
    return Response.json({ ok: true }, { status: 200 });
  }
};

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

The mapping is intentionally explicit. customer.email becomes to; a verified sender becomes from; subscription.product_title becomes part of the subject and body; and the subscription ID is included as a customer-support reference. Do not spread the raw Recharge object directly into an email payload. Raw event objects may carry fields you do not want to expose, and they do not necessarily match the API’s expected types.

Set up the Recharge side

In Recharge, create a webhook destination that points to your relay’s HTTPS URL and subscribe it to the subscription-created event/topic available in your account’s webhook configuration. Use the exact topic name shown by Recharge for your API version rather than guessing from an older integration.

Keep the endpoint narrow. A production endpoint should accept only POST requests, accept only the intended event type, reject invalid content types or bodies, and log a correlation ID without logging the entire customer record. If Recharge supports webhook signing for your configuration, verify it before parsing or acting on the request. A URL secret can reduce random scanning, but it cannot establish that the sender is Recharge.

Test with a development store or a safely designated test customer. Confirm all of the following before enabling the workflow for live customers:

  1. Recharge can reach the HTTPS endpoint and receives a prompt 2xx response.
  2. The subscription ID is stored as an idempotency key before an email is sent.
  3. The customer lookup returns an address for the intended test record.
  4. The Volanea request is accepted and has the expected tags.
  5. The received email contains correct dates, product names, and support details.
  6. A replay of the same webhook does not generate a second email.

Field mapping, template safety, and data minimization

A reliable email is more than a successful API call. It is a controlled transformation from an operational event into a customer-facing statement.

For the subscription-created example, use a small mapping contract:

Recharge dataEmail useValidation rule
customer_idCustomer lookup keyRequired; never use it as the recipient address.
Customer emailto recipientRequired; validate format and suppression status before sending.
Customer first nameGreetingOptional; fall back to “there.”
subscription.idSupport reference and dedupe keyRequired; treat as a string in templates.
product_titleSubject and bodyOptional; escape HTML and use a safe fallback.
quantityBody detailOptional; default carefully.
next_charge_scheduled_atBody detailOptional; format for the recipient’s locale if you know it.

Escape values inserted into HTML. Product titles, custom properties, and customer-entered values should be treated as untrusted text even when they originate in a commerce platform. This is especially important when you add subscription properties or address details later: a useful operational field can still contain characters that break markup or create misleading rendered content.

Minimize what you place in the email. A subscription confirmation rarely needs a street address, internal IDs other than a support reference, payment details, or all custom properties. Sending less sensitive information reduces both privacy exposure and the chance that a forwarding customer sees data you did not intend to disclose.

Reliability rules for sending email from Recharge

Webhook delivery is normally at-least-once, not exactly-once. In practical terms, your endpoint can receive the same Recharge event more than once when an earlier delivery timed out, returned an error, or could not be confirmed. If your handler sends an email every time it receives a request, a temporary network problem becomes a duplicate customer message.

Deduplicate before the email API call

For subscription/created, subscription.id plus the event type is usually a sensible business idempotency key: subscription-created:<subscription-id>. Store it with a unique constraint. The insert must be atomic; a read-then-write sequence can race when two retries arrive at once.

Do not use the product title, recipient email, or timestamp as the dedupe key. A customer can create two legitimate subscriptions for the same product, and timestamps can differ across deliveries. The resource ID is the stable business identifier for this one-time confirmation.

For events that can happen repeatedly, such as updates, choose a different rule. You may want a unique event delivery ID when available, a resource version/timestamp, or a business-specific transition such as “ACTIVE to CANCELLED.” Do not suppress legitimate lifecycle messages merely because they concern the same subscription.

Respond quickly, then do slow work safely

Customer lookup and email delivery add latency and can fail independently. The strongest design is to acknowledge a validated webhook after persisting it to a durable queue, then let a worker perform the lookup and Volanea call. That lowers the chance that Recharge retries because your endpoint was waiting on another service.

A smaller implementation can process synchronously as the sample does, but it should use tight outbound timeouts and a clear retry policy. If the email API outcome is uncertain because the network broke after the request left your service, do not blindly retry without consulting your own event record and any provider-supported idempotency capability. The key operational question is whether the email was accepted, not simply whether your HTTP client saw a response.

Keep an audit trail that is useful but safe

Record event type, subscription ID, customer ID, received time, state transitions, Volanea response identifier when available, and failure reason. Avoid storing raw request bodies indefinitely, API keys, Authorization headers, or complete email contents in application logs.

Tags such as source=recharge and event=subscription_created make it easier to segment delivery reporting from other traffic. They also make it possible to investigate a support case without searching through every message sent by your application.

When this breaks

Every integration has failure modes. The important difference between a demo and a production workflow is whether those cases lead to duplicate email, missing email, delayed email, or a contained operational alert.

Recharge retries cause duplicate sends

If your endpoint returns a non-2xx result or takes too long to respond, Recharge may retry delivery. A retry can arrive after the first invocation has already sent the email but before it saved success, or while the first invocation is still running.

Fix this with a durable, atomic idempotency record created before the send. Mark the record as processing, sent, suppressed, or failed; do not delete it immediately after success. If a duplicate sees sent or processing, return a safe success response or let the job system coordinate the existing work rather than calling Volanea again.

The webhook times out

A webhook can time out because the customer lookup is slow, the email provider is slow, your function cold-started, or your database is unavailable. Do not solve this by raising timeouts indefinitely. Move delivery to a queue after durable acceptance, and monitor queue age as well as error rate.

If you keep synchronous processing, set lower client timeouts than the webhook sender’s total delivery window, leave enough time to write state, and return an error only when you truly want Recharge to retry. A fast 200 response without durable storage is worse than a retry: it can silently lose the event.

Fields are missing, renamed, or unavailable in your setup

A subscription event may not include the customer email or every value your template expects. API versions, permissions, store features, deleted customer records, and data quality all affect what you can retrieve. Do not construct to from a missing field or substitute an arbitrary address.

Use explicit fallbacks for optional display fields and suppress the send when the recipient is absent. Alert your team when suppression happens unexpectedly. If a field requires an additional Recharge API read or a scope not present in the webhook payload, document that dependency and test it in the same environment as the webhook.

The API request is rejected

A Volanea request can be rejected because the key is wrong or revoked, the sender is not verified, the JSON is invalid, the recipient is invalid, or the account has a sending restriction. Capture the response status and a safe response fragment in the event record, then classify it.

Retry transient failures such as timeouts and temporary 5xx responses with bounded backoff. Do not retry permanent validation failures forever. For recipient-quality issues before sending, use an address-validation step such as the email address verification tool where that fits your workflow, while remembering that verification does not replace consent or suppression management.

Direct code, Zapier, and Make: choosing the right route

The best route depends on volume, customization, and how much operational control you need.

Server-side relay

Choose a custom relay when the email is transactional, the content needs a Recharge customer lookup, you need durable deduplication, or email volume makes per-task automation pricing unpredictable. It gives you control over API versioning, queueing, retries, logs, and customer-data handling.

The tradeoff is engineering ownership. You must maintain the endpoint, verify webhooks, rotate secrets, and observe failures. For a subscription business, those are usually appropriate responsibilities because the messages are part of the customer experience.

Zapier or Make workflow

Choose an automation platform for a low-volume workflow that can be expressed with its Recharge trigger and an HTTP request action. Store the Volanea key in the automation platform’s protected connection or encrypted credential field, not in mapped data, notes, or a public webhook URL. Map the recipient and content fields explicitly, just as you would in code.

Check whether the specific Recharge trigger provides the email address you need. If it does not, the automation must add a Recharge customer lookup step, or you need a small API endpoint that performs that lookup. Also test replay behavior: a task retry can create a second send unless the workflow stores or checks an idempotency key.

A useful decision rule

Start with an automation tool only if an occasional failure can be reviewed manually and the data mapping is small. Use a queue-backed relay when emails are operationally significant, repeated events are expected, or you need a reliable record of exactly why a customer did or did not receive a message.

Deliverability considerations for Recharge-triggered mail

Recharge events can be highly timely: a subscription change, upcoming charge, or payment problem has immediate relevance. That relevance helps engagement only if the sender identity and content are consistent.

Send from a domain you control and have authenticated for Volanea. Keep the visible From name stable, make Reply-To a monitored inbox, and ensure the message body matches the event that triggered it. A subscription-created confirmation should not look like a bulk campaign, and a failed-payment notice should explain the next action without obscure links or surprise attachments.

Separate lifecycle email from marketing at the template, tagging, and policy level. That makes customer expectations clearer and lets your team diagnose performance by message class. If a particular Recharge-triggered template receives complaints or low engagement, inspect its timing, consent basis, sender identity, and content before assuming the infrastructure is the cause.

A production checklist

Before going live, review this list with the person responsible for Recharge operations and the person responsible for email delivery:

  • The Recharge webhook uses the exact event topic intended for the notification.
  • The endpoint is HTTPS, restricted to POST, and verifies the configured webhook authenticity mechanism.
  • The Volanea key and Recharge token are encrypted server-side secrets.
  • The Volanea sender domain is verified and the Reply-To mailbox is monitored.
  • The integration uses an atomic idempotency key before it sends.
  • Missing recipient email results in an explicit suppression record, not a malformed request.
  • Optional text fields are escaped before being inserted into HTML.
  • Transient failures retry with backoff; permanent failures are surfaced for review.
  • Logs contain safe identifiers and outcomes, not API keys or raw personal data.
  • Test events prove that a replay does not send a second confirmation.

Conclusion

To send email from Recharge with Volanea, use Recharge as the source of the business event and Volanea as the email-delivery layer. A webhook for subscription/created, routed through a small secure relay, provides the necessary control over customer lookup, authentication, message construction, and duplicate prevention.

The relay is not unnecessary complexity. It is the boundary that keeps an email API key out of the browser, turns a subscription record into a clear customer message, and makes retries safe. Once that foundation is in place, you can add further Recharge lifecycle notifications with the same pattern and predictable operational behavior.

FAQ

Can I install a Volanea app from the Recharge marketplace?

No. There is no native Volanea Recharge app or marketplace installation flow. Use a Recharge webhook and a server-side relay, or an automation platform that supports both your Recharge trigger and an authenticated HTTP request.

What Recharge trigger should I use for a new subscription email?

Use the subscription/created webhook topic available in your Recharge webhook configuration. Treat it as an operational event, map its customer_id and subscription fields deliberately, and retrieve the customer record when the event does not contain an email address.

Where should the Volanea API key be stored?

Store it only in an encrypted server-side secret store used by your relay or in the protected credential storage of an automation platform. Never place it in storefront JavaScript, a theme configuration, a public webhook URL, or a Recharge custom field.

How do I prevent duplicate emails when Recharge retries a webhook?

Create an atomic, durable idempotency record before sending. For a one-time subscription-created confirmation, use a key such as subscription-created:<subscription-id>, retain the result, and treat subsequent deliveries of that key as duplicates.

What if the Recharge webhook does not contain the customer email?

Use the customer_id from the subscription event to retrieve the customer through the Recharge API with a server-side token. If no email is present after lookup, record a suppression or failure for review rather than sending to an invented or fallback address.