Skip to Content
Build with AICommon Recipes

Common Recipes

Production-grade patterns that save you reinventing the wheel.

Idempotent transactional sends

Replays of the same logical send (e.g. payment-receipt for the same charge ID) shouldn’t trigger duplicate emails. Stamp a stable X-Idempotency-Key header derived from your business key, and de-dup on your side before calling /send:

const sentKey = await redis.get(`email:sent:${chargeId}`); if (sentKey) return; // already emailed const res = await client.emails.send({...}); await redis.set(`email:sent:${chargeId}`, res.results[0].messageId, { EX: 86400 });

We don’t currently honor an Idempotency-Key header server-side (roadmap), so the dedup happens at your layer.

Per-recipient personalization at scale

For bulk sends with per-recipient variables, use /send-bulk:

await client.emails.sendBulk({ from: "hello@yourcompany.com", templateName: "newsletter-june", defaultTemplateData: { campaign: "june-2026" }, destinations: users.map(u => ({ to: [u.email], replacementData: { first_name: u.firstName, unsubscribe_url: `https://yoursite.com/u/${u.token}`, }, })), });

50 destinations × 50 recipients × 500 total per request. For larger volumes, chunk into multiple calls — there’s no per-account rate limit on bulk-send concurrency, only the per-account per-second peak rate.

Dynamic from-name

Set the from field as "Display Name <hello@yourcompany.com>" and recipients see “Display Name” in their inbox:

{ "from": "Sarah from Acme <sarah@acme.com>", ... }

Domain still has to be verified. Display name is unverified — recipients see whatever you put there.

Custom MAIL FROM domain (return-path)

Sets the bounce return-path to a custom subdomain so DMARC alignment includes both DKIM and SPF. Lands on roadmap. Until then, the return-path is bounces@mail.splashifypro.com and DMARC alignment relies on DKIM only (p=quarantine is fine; p=reject may need DMARC relaxed alignment).

Per-customer attribution

If you’re sending on behalf of multiple downstream customers, create a configuration set per customer and reference it on every send:

await client.emails.send({ from: "alerts@yourcompany.com", to: ["customer@example.com"], configurationSetName: "customer_acme_corp", ... });

Stats roll up per config set — GET /stats?config_set_id=.... Each config set can also have its own webhook destination so events for Acme go to one URL and events for Globex go to another.

Hard-bounce auto-list-cleaning

Hard bounces are added to your suppression list automatically. To keep your application’s email list in sync, listen for the Bounce webhook event:

app.post("/webhooks/splashify", async (req, res) => { const sig = req.header("x-splashify-signature"); if (!verifyHMAC(req.rawBody, sig, process.env.SPLASHIFY_WEBHOOK_SECRET)) { return res.status(401).end(); } if (req.body.eventType === "Bounce" && req.body.bounce.bounceType === "Permanent") { const email = req.body.bounce.bouncedRecipients[0].emailAddress; await db.users.updateOne({ email }, { $set: { emailBouncedHard: true } }); } res.status(200).end(); });

Now your signup form / re-engagement campaigns can skip these addresses up-front instead of burning send quota.

Retry on 5xx

Network blips and brief upstream issues should retry; auth/quota errors shouldn’t. Pseudocode:

async function sendWithRetry(payload, attempts = 3) { for (let i = 0; i < attempts; i++) { const res = await client.emails.send(payload); if (res.success) return res; const code = res.error; // Don't retry these — won't get better with time. if (["INVALID_REQUEST", "FROM_NOT_VERIFIED", "INSUFFICIENT_BALANCE", "MISSING_AUTH"].includes(code)) { throw new Error(`${code}: ${res.message}`); } // Backoff on the rest. await sleep(1000 * Math.pow(2, i)); } throw new Error("send_failed_after_retries"); }

Webhooks that survive your deploys

Stamp every event in your local DB before processing — duplicate webhook deliveries (which happen on retries) are idempotent:

const eventID = req.header("x-splashify-delivery-id"); const inserted = await db.events.insertOne({ _id: eventID, ...req.body, }, { ignoreDuplicates: true }); if (!inserted.insertedCount) return res.status(200).end(); // dedup // ... process

X-Splashify-Delivery-ID is a fresh UUID per delivery attempt — even a retried event keeps the same ID.

Cold-start IP warm-up

New production accounts inherit warm sending infrastructure with established reputation across major mailbox providers. You don’t need to manually warm up.

Dedicated IPs (roadmap) require warm-up — typically 2 weeks of gradually increasing volume. We’ll publish a warm-up calculator when dedicated IPs ship.