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

Send emails with Astro

Transactional and marketing email from an Astro API route. It needs on-demand rendering, because a static site can't keep a key secret.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Astro

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 Astro?

Create a key, keep it on the server, and call one endpoint from an Astro API 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 .env. Without a PUBLIC_ prefix, Astro keeps it on the server. API routes need an SSR adapter; a fully static build has no server to hold the key.

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

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

    src/pages/api/welcome.ts
    import type { APIRoute } from "astro";
    import { EMAIL_URL, authHeaders } from "../../lib/email";
    
    export const prerender = false;
    
    export const POST: APIRoute = async ({ request }) => {
      const input = await request.json();
      const res = await fetch(EMAIL_URL, { method: "POST",
        headers: authHeaders(`welcome-${input.userId}`),
        body: JSON.stringify({ to: input.email, template: "welcome" }) });
      return Response.json(await res.json(), { status: res.status });
    };
  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 Astro app?

API routes with an SSR adapter

API routes need on-demand rendering. A fully static deploy has no server to hold the key.

Events from the endpoint

Send signup or trial events from the endpoint that receives trusted data, not from an island in the browser.

A raw body for webhooks

An export const POST endpoint reads the raw Request body for the signature check.

[ 03 / 05 ]Marketing email

Can I send marketing emails from Astro too?

Yes. Send an event from the same API 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 Astro?

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 Astro signup API route using Send & Retain, with an idempotency key.”

  • Contact form

    “Add an SSR adapter and an API route that sends our contact-form confirmation email through Send & Retain.”

  • Webhook

    “Add an Astro endpoint that verifies Send & Retain delivery webhooks and flags bounced users.”

  • Trial automation

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

Questions people ask us

Send your first email from Astro today.

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