Developer documentation

Send email from Node.js and Express

Install the SendPanda SDK, send email from Node.js with ESM or CommonJS, add it to an Express route and handle timeouts, retries and errors.

The SendPanda SDK is a server-side package for Node.js 22 or newer. It ships ESM and CommonJS builds, TypeScript declarations and has no runtime dependencies.

1. Install and send

npm install @sendpanda/sdk

Create a Send emails key in your project and keep it in your server environment as SENDPANDA_API_KEY. Never put it in browser code or a NEXT_PUBLIC_ variable. You also need a verified sending domain: see the domain setup guide.

import { SendPanda } from "@sendpanda/sdk";

const panda = new SendPanda(process.env.SENDPANDA_API_KEY!);

const email = await panda.emails.send(
  {
    from: "Your app <hello@your-verified-domain.com>",
    to: ["customer@example.com"],
    subject: "Your receipt",
    html: "<p>Thanks for your order.</p>",
    text: "Thanks for your order.",
  },
  { idempotencyKey: "receipt-order-1042" },
);
console.log(email.id, email.status);

With CommonJS:

const { SendPanda } = require("@sendpanda/sdk");
const panda = new SendPanda(process.env.SENDPANDA_API_KEY);

2. Use it in an Express route

import express from "express";
import { SendPanda, SendPandaError } from "@sendpanda/sdk";

const app = express();
const panda = new SendPanda(process.env.SENDPANDA_API_KEY!);

app.post("/orders/:id/receipt", async (req, res) => {
  const order = await loadOrder(req.params.id); // your own lookup
  try {
    const email = await panda.emails.send(
      {
        from: "Shop <orders@your-verified-domain.com>",
        to: [order.customerEmail],
        subject: `Receipt for order ${order.id}`,
        html: order.receiptHtml,
        text: order.receiptText,
      },
      { idempotencyKey: `receipt-${order.id}` },
    );
    res.status(202).json({ id: email.id });
  } catch (error) {
    if (error instanceof SendPandaError) {
      res.status(502).json({ code: error.code, requestId: error.requestId });
      return;
    }
    throw error;
  }
});

Timeouts, retries and errors

The client has a request timeout and a retry budget you can set when you create it:

const panda = new SendPanda(process.env.SENDPANDA_API_KEY!, {
  timeout: 10_000, // milliseconds
  maxRetries: 2, // additional attempts, capped at 5
});

The SDK retries GET requests, and POST requests that carry an idempotency key, after network failures, HTTP 429 and HTTP 5xx. It never automatically retries a send without a key, because a timeout can happen after the API has already accepted the email. Errors are SendPandaError instances with code, status and requestId; a network error has status 0.

Next steps