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

Send emails with Hono

Transactional and marketing email from a Hono handler. It is one standard fetch call, so it runs wherever Hono does.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Hono

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

Create a key, keep it on the server, and call one endpoint from a Hono handler.

  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

    On Cloudflare Workers, store the key as a secret. Hono hands it to each request as c.env.AEM_KEY. On Node, use process.env.AEM_KEY instead.

    Terminal
    npx wrangler secret put AEM_KEY
  3. Add a send helper

    A Worker has no global environment, so the helper takes the key as an argument.

    src/email.ts
    export function sendEmail(apiKey: string, idempotencyKey: string, body: object) {
      return fetch("https://sendandretain.com/api/v1/emails", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
          "Idempotency-Key": idempotencyKey,
        },
        body: JSON.stringify(body),
      });
    }
  4. Send the email

    The handler passes c.env.AEM_KEY to the helper and returns the API's status and body. A retry with the same Idempotency-Key won't send a second email.

    src/index.ts
    import { Hono } from "hono";
    import { sendEmail } from "./email";
    
    const app = new Hono<{ Bindings: { AEM_KEY: string } }>();
    
    app.post("/welcome", async (c) => {
      const { email, userId } = await c.req.json();
      const res = await sendEmail(c.env.AEM_KEY, `welcome-${userId}`, {
        to: email,
        template: "welcome",
      });
      return Response.json(await res.json(), { status: res.status });
    });
    
    export default app;
  5. 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 Hono app?

A typed Hono handler

A plain fetch call keeps the send portable. Your runtime decides where the secret lives.

Events from the handler

Send product events from the handler that checks and saves the action, not from client tracking.

The raw request for webhooks

c.req.raw is the untouched Request, which is exactly what the signature check needs.

[ 03 / 05 ]Marketing email

Can I send marketing emails from Hono too?

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

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

  • Workers secret

    “Wire Send & Retain into our Hono app on Cloudflare Workers, with the API key stored as a Worker secret.”

  • Webhook

    “Add a Hono route that verifies Send & Retain delivery webhooks from c.req.raw and flags bounced users.”

  • Trial automation

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

Questions people ask us

Send your first email from Hono today.

Create a key, paste the code into a Hono handler, and watch the email land in the message log.