Skip to content
Browse the docs

Frameworks and agents · Published 2026-09-22 · Updated 2026-09-29 · AgentiSend

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 run by the test suite against a local AgentiSend server'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, run by the test suite against a local AgentiSend server

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