Migration guide

Migrate from Mailgun to Volanea.

Mailgun is solid transactional infrastructure, but campaigns and automation live in a different product entirely. Moving to Volanea usually means consolidating — here's the send-path swap that starts it.

Undecided? Read the honest Volanea vs Mailgun comparison first.

01

Create the project and verify your domain

Sign up (free, no card), add your sending domain, and install the DKIM/SPF records Volanea shows you — fresh records, separate from Mailgun's. Keep Mailgun live for now: nothing gaps while DNS propagates, and verification is one click once it does.

02

Swap the send call

This is the heart of it — one call replaced by one call. Grab your secret key from project settings first.

before — mailgun.js

import formData from "form-data";
import Mailgun from "mailgun.js";

const mg = new Mailgun(formData).client({
  username: "api",
  key: process.env.MAILGUN_API_KEY!,
});

await mg.messages.create("yourdomain.com", {
  from: "shop@yourdomain.com",
  to: "ada@example.com",
  subject: "Your order shipped",
  html: "<p>On its way, Ada.</p>",
});

after — volanea

// npm i @volanea/sdk   (or plain fetch — it's one POST)
import { Volanea } from "@volanea/sdk";

const volanea = new Volanea({ apiKey: process.env.VOLANEA_SECRET_KEY! });

await volanea.send(
  {
    to: "ada@example.com",
    subject: "Your order shipped",
    html: "<p>On its way, {{firstName}}.</p>",
    variables: { firstName: "Ada" },
  },
  { idempotencyKey: "order-4921" }, // retries become safe replays
);
  • No domain argument in the call — Volanea resolves the sending domain from from (or your project default).
  • JSON body instead of form-data, plain Bearer auth instead of basic auth with an api: prefix.
  • Scheduling: Mailgun's o:deliverytime becomes a sendAt field on the same request.
03

Bring your contacts

Export your list from Mailgun as CSV and import it in the Volanea dashboard (or POST /v1/contacts/import). Columns map by header, imports run as a background job with live progress, and re-runs dedupe by email — a partial import is never a disaster. Unsubscribed contacts keep their status, so nobody who opted out gets mailed by mistake.

04

Re-point your webhooks

Register your endpoint in Volanea (the response includes the whsec_… signing secret), then translate the event names your handler listens for:

MailgunVolanea
acceptedemail.sent
deliveredemail.delivered
openedemail.opened
clickedemail.clicked
failed (permanent)email.bounced
complainedemail.complained

Every delivery is HMAC-signed in the X-Volanea-Signature header and retried with backoff for ~24 hours — the docs include a drop-in verifier.

05

Test, then flip

Send through your test key (sk_test_…) first — messages render and log fully but deliver nothing, so you can assert on the whole pipeline in CI. When the domain is verified and the test sends look right, swap in the live key, watch the first real sends land in the dashboard, and retire the Mailgun credentials.

06

Watch for the gotchas

  • Mailgun signs webhooks with a token+timestamp+signature triple; Volanea uses a single X-Volanea-Signature HMAC header over the raw body — the docs have a drop-in verifier.
  • Mailgun's free log retention is 1 day, so export anything you need before switching off.
  • SMTP relay users: Volanea's SMTP endpoint is coming soon — migrate the SMTP path to the REST API (it's one POST).

An afternoon, start to finish.