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

Make Django email part of the product lifecycle. Not a fire-and-forget call from a view.

Queue transactional messages from Django, publish the events that drive follow-up flows, and trace both against one contact record.

Use it beside or instead of send_mail when product email needs lifecycle context and delivery evidence.

Server quickstart
Django

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

Keep Django requests fast without losing the message trail.

Use views, signals, and background tasks

Call directly when an accepted response is enough, or use Celery or django-q when local work must survive the request.

Publish product events

Publish lifecycle events from an application service after the database change succeeds, rather than hiding network work in a signal.

Verify the webhook

A csrf_exempt view reading request.body before anything parses it.

[ 02 / 03 ]Server quickstart

Queue a Django email and keep the message ID.

A stable idempotency key makes a task retry safe; the returned ID links the application action to delivery.

Use an async HTTP client when this runs inside an async framework.

send_welcome.py
response = requests.post(
    "https://sendandretain.com/api/v1/emails",
    headers={"Authorization": f"Bearer {os.environ['AEM_KEY']}",
             "Idempotency-Key": f"welcome-{user.id}"},
    json={"to": user.email, "template": "welcome"}, timeout=10,
)
response.raise_for_status()

Accepted response

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

Questions people ask us

Connect your next Django event to a delivered email.

Queue the message from a service or task, then follow its ID through delivery.