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

Send emails from Go

Transactional and marketing email from any Go service. One net/http request, and a message ID you can follow to the inbox.

✓Free to start. Unlimited contacts on every tier.

Server quickstart
Go

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 / 04 ]Quickstart

How do I send email from Go?

Three steps from no account to a queued email. The standard library is enough.

  1. Create an API key

    In the dashboard, 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 an environment variable

    Keep the key on your server. Your code reads it with os.Getenv("AEM_KEY").

    Terminal
    export AEM_KEY="aem_..."
  3. Send the email

    POST the recipient and a published template as JSON. Anything but a 2xx returns an error, and a retry with the same Idempotency-Key won't send a second email.

    send_welcome.go
    body, _ := json.Marshal(map[string]string{"to": user.Email, "template": "welcome"})
    req, err := http.NewRequest(http.MethodPost,
        "https://sendandretain.com/api/v1/emails", bytes.NewReader(body))
    if err != nil { return err }
    req.Header.Set("Authorization", "Bearer "+os.Getenv("AEM_KEY"))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Idempotency-Key", "welcome-"+user.ID)
    res, err := http.DefaultClient.Do(req)
    if err != nil { return err }
    defer res.Body.Close()
    if res.StatusCode >= 300 { return fmt.Errorf("send failed: %s", res.Status) }
  4. Keep the message ID

    A 202 means queued, not delivered. Store the id, and read delivery, bounce, and complaint events from your signed webhook.

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

[ 02 / 04 ]In production

What does a production Go integration need?

Deadlines on every request

Pass the caller's context and set a timeout. Struct tags map cleanly onto the JSON payload.

Retries with the same key

Retry transport errors and 5xx responses with the same Idempotency-Key. Don't retry validation or auth errors; fix the request instead.

Webhooks checked on the raw body

Read the body with io.ReadAll before decoding, so the signature covers the exact bytes.

Events for marketing email

Send product events like signup or trial started. Automations you've turned on decide which email goes out.

[ 03 / 04 ]Example prompts

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

Paste these into Claude Code, Cursor, or Codex. Connect the MCP server and it can build the templates and automations too.

  • Email client

    “Write a small Send & Retain email client in Go with net/http, a context deadline, and typed errors for transport failures versus API errors.”

  • Retries

    “Add retries with backoff to our email sends. Reuse the same Idempotency-Key and never retry 4xx responses.”

  • Webhooks

    “Add an HTTP handler that verifies Send & Retain webhook signatures on the raw body and flags bounced addresses in our database.”

  • Trial automation

    “Send a trial_started event to Send & Retain when a trial begins, then build a paused trial automation for it.”

Questions people ask us

Send your first email from Go.

Create a key, make one call, and follow the message ID to the inbox.