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

Send Phoenix email with retries that do not become duplicates. Oban runs the job; the message key keeps it safe.

Queue transactional messages from a context or Oban worker, reuse one logical key across retries, and trace each accepted ID through delivery.

Use it beside or instead of Swoosh when product email needs lifecycle flows and delivery history.

Server quickstart
Phoenix

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 / 03 ]Integration shape

Match BEAM reliability with an idempotent send boundary.

Use controllers, contexts, and Oban jobs

Oban owns durable local execution; a stable idempotency key keeps repeated jobs tied to one logical message.

Publish product events

Publish product events from contexts after the data change succeeds, so lifecycle behavior stays outside controllers.

Verify the webhook

A Plug with a custom body reader that caches the raw body for signature verification.

[ 02 / 03 ]Server quickstart

Queue one email from a Phoenix context or worker.

The request returns an accepted message ID while Oban remains responsible for your application's local retry policy.

Call from a context or supervised job and retain the accepted message ID.

lib/app/email.ex
Req.post!("https://sendandretain.com/api/v1/emails",
  headers: [
    authorization: "Bearer #{System.fetch_env!("AEM_KEY")}",
    idempotency_key: "welcome-#{user.id}"
  ],
  json: %{to: user.email, template: "welcome"}
)

Accepted response

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

Questions people ask us

Give your next Phoenix email a retry-safe trail.

Queue it from a context or Oban worker and follow its accepted ID to delivery.