Docs

Frameworks and agents · Updated 2026-09-22

Send email from Express

A POST route on an app you can mount anywhere, returning the message id or the code and fix of a refusal.

To send email from an Express app, add one POST route that calls AgentiSend and returns the message id. The app below is exported without calling listen, so it can be mounted, tested, or started from a separate entry point. It is executed against a real API on every build of this site's repository.

Install

pnpm add express agentisend

Environment

VariableRequiredWhat it is
AGENTISEND_API_KEYyesA key with sending_access.
MAIL_FROMyesThe From address, on a domain you have verified.
AGENTISEND_BASE_URLnoDefaults to https://api.agentisend.com.

The route

/**
 * Express — a POST route that sends a transactional email.
 *
 * The app is exported without calling `listen`, so it can be mounted, tested,
 * or started from a separate entry point.
 */
import express, { type Express } from 'express';
import { AgentiSend, AgentiSendError } from 'agentisend';

const agentisend = new AgentiSend();

function mailFrom(): string {
  const from = process.env.MAIL_FROM;
  if (!from) throw new Error('Set MAIL_FROM to an address on a domain you have verified.');
  return from;
}

export const app: Express = express();
app.use(express.json());

app.post('/send', (req, res) => {
  void (async () => {
    const { email, subject } = req.body as { email?: string; subject?: string };
    if (!email) {
      res.status(400).json({ error: 'email is required' });
      return;
    }

    try {
      const { id } = await agentisend.emails.send(
        {
          from: mailFrom(),
          to: email,
          subject: subject ?? 'Your order shipped',
          text: 'Tracking details are in your account.',
        },
        { idempotencyKey: `shipped/${email}` },
      );
      res.json({ id });
    } catch (err) {
      if (err instanceof AgentiSendError) {
        res.status(err.status).json({ code: err.code, fix: err.fix });
        return;
      }
      res.status(500).json({ error: 'send failed' });
    }
  })();
});

export default app;
examples/express/server.ts, executed against the live API on every build

Start it

import app from './server';

app.listen(3000);
index.ts
curl -X POST localhost:3000/send \
  -H 'content-type: application/json' \
  -d '{"email":"you@example.com"}'

What comes back when it goes wrong

Every refused request carries code, message, fix and docs_url. The route answers with the same status and forwards code and fix. The error catalogue lists every code.

Next