Every dashboard action is an MCP tool your agent can call.Read the docs

Send emails with Express

Transactional and marketing email from an Express route. One fetch call returns an id you can follow to the inbox.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Express

One request, complete trace

Request

POST /api/v1/emails

Authorization: Bearer aem_…

Idempotency-Key: welcome-8f21

{ "to": "[email protected]", "template": "welcome" }

202 Accepted

{ "id": "msg_7ca31", "status": "queued" }

RuntimeServer process
RequestPOST /api/v1/emails
Result202 · queued
Credentials stay server-side

[ 01 / 05 ]Quickstart

How do I send email from Express?

Create a key, keep it on the server, and call one endpoint from an Express route.

  1. Get an API key

    Open Settings → API & MCP and create a key with the Send + manage permission (the default). It starts with aem_ and is shown once.

  2. Store it as a server-side environment variable

    Set AEM_KEY=aem_… in your server environment, then build the headers in one place. The app in the next step imports these two helpers.

    src/email.ts
    export const EMAIL_URL = "https://sendandretain.com/api/v1/emails";
    
    export const authHeaders = (idempotencyKey: string) => ({
      Authorization: `Bearer ${process.env.AEM_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": idempotencyKey,
    });
  3. Send the email

    The route posts to the email API and passes the result back. A retry with the same Idempotency-Key won't send a second email.

    src/app.ts
    import express from "express";
    import { EMAIL_URL, authHeaders } from "./email";
    
    const app = express();
    app.use(express.json());
    
    app.post("/welcome", async (req, res) => {
      const result = await fetch(EMAIL_URL, { method: "POST",
        headers: authHeaders(`welcome-${req.body.userId}`),
        body: JSON.stringify({ to: req.body.email, template: "welcome" }) });
      res.status(result.status).json(await result.json());
    });
  4. Check the response

    A 202 means queued, not delivered. Keep the id, then follow delivery in the message log or through a signed webhook.

    202 Accepted
    { "id": "msg_7ca31", "status": "queued" }

[ 02 / 05 ]Where it goes

Where should email code live in your Express app?

A route or a service module

Return the 202 straight away. Add your own queue only if your app's work needs to survive a restart.

Events after the write

Send events after your app saves the change, so automations follow what happened, not what a browser clicked.

A raw body for webhooks

Mount express.raw on the webhook route only, so the signature still verifies.

[ 03 / 05 ]Marketing email

Can I send marketing emails from Express too?

Yes. Send an event from the same Express route when a user signs up, starts a trial, or goes quiet, and an automation sends the right email. Automations start paused, and every email goes to one person: no newsletter blasts.

  • Transactional and marketing email share one contact record and one unsubscribe list.
  • Unsubscribes, bounces, and complaints are suppressed for you before every send.
  • Templates are react.email components; published versions never change under you.

[ 04 / 05 ]Example prompts

What can you ask your coding agent to do in Express?

Claude Code, Cursor, and Codex can do these over the Send & Retain MCP server, with your repo open. Automations they build stay paused until you turn them on.

  • Welcome email

    “Add a welcome email to our Express signup route using Send & Retain, with an idempotency key.”

  • Password reset

    “Write a password reset email in our brand, send me a test, then send it from our /forgot-password route.”

  • Webhook

    “Add an Express route that verifies Send & Retain delivery webhooks with express.raw and marks bounced users.”

  • Trial automation

    “Send a trial_started event from our Express app and build a paused trial-conversion automation for it.”

Questions people ask us

Send your first email from Express today.

Create a key, paste the code into an Express route, and watch the email land in the message log.