Sending Email
Send email with policy enforcement, autonomy-level gating, and delivery tracking.
Molted Email provides multiple send endpoints depending on your use case. For most agent integrations, use the agent send endpoint which includes thread tracking, policy traces, and autonomy level gating.
Send endpoints
| Endpoint | Best for | Extra features |
|---|---|---|
POST /v1/agent/request-send | Agent integrations | Thread tracking, policy trace, scheduled sends, lease coordination |
POST /v1/outbound/send | Agentic mailbox clients | Thread projection, canary token detection, auto-thread creation |
POST /v1/send/request | Simple integrations | Basic send with policy checks |
All endpoints require Bearer authentication and enforce policy checks and autonomy levels.
Agent send (recommended)
POST https://api.molted.email/v1/agent/request-sendThis is the recommended endpoint for agent integrations. It supports thread tracking, scheduled sends, and returns a full policy decision trace.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | Yes | Your tenant identifier. |
recipientEmail | string | Yes | The recipient's email address. Must be a valid email format (e.g. user@example.com). |
templateId | string | Yes | The template slug (e.g. welcome, order-confirmation). Also accepts a template ID. |
dedupeKey | string | Yes | A unique key to prevent duplicate sends. |
payload | object | Yes | Template variables and email content. |
mailboxId | string | No | Send from a specific mailbox. Required for autonomy level enforcement. |
threadId | string | No | Associate with an existing thread. |
sendReason | string | No | Annotate why the agent is sending (for audit trails). |
idempotencyKey | string | No | Alternative deduplication key. |
scheduledAt | string | No | ISO 8601 timestamp to schedule the send (minimum 60s in the future). |
humanize | boolean | No | Apply AI humanization to the email content. |
You can also pass the X-Agent-Id header to identify which agent initiated the send.
Simple send
POST https://api.molted.email/v1/send/requestThe basic send endpoint. Use this for simple integrations that don't need thread tracking or policy traces.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | Yes | Your tenant identifier. |
recipientEmail | string | Yes | The recipient's email address. Must be a valid email format (e.g. user@example.com). |
templateId | string | Yes | The template slug (e.g. welcome, order-confirmation). Also accepts a template ID. |
dedupeKey | string | Yes | A unique key to prevent duplicate sends. The same key will be rejected as duplicate. |
payload | object | Yes | Template variables and email content. |
Payload fields
The payload object contains your email content and any template variables:
| Field | Type | Description |
|---|---|---|
subject | string | The email subject line. |
html | string | The HTML body of the email. |
text | string | Plain text fallback body. |
| custom keys | any | Any additional variables your template expects. |
Example request
curl -X POST https://api.molted.email/v1/send/request \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "tenant_abc123",
"recipientEmail": "user@example.com",
"templateId": "order-confirmation",
"dedupeKey": "order-456-user@example.com",
"payload": {
"subject": "Your order has been confirmed",
"html": "<h1>Order Confirmed</h1><p>Thank you for your purchase.</p>",
"text": "Order Confirmed. Thank you for your purchase.",
"orderId": "456",
"customerName": "Jane"
}
}'Response
Queued (success)
{
"requestId": "req_abc123",
"status": "queued"
}The email has passed all policy checks and is queued for delivery.
Blocked
{
"requestId": "req_abc123",
"status": "blocked",
"reason": "rate_limited"
}The email was rejected by the policy engine. See Errors & Policy Blocks for all possible reason values.
Email format validation
The recipientEmail field (or --to in the CLI) must be a valid email address. The server validates email format before processing the request. If the address is invalid, the request is rejected with a 400 Bad Request error:
{
"statusCode": 400,
"message": ["recipientEmail must be an email"],
"error": "Bad Request"
}Validate email addresses before sending to avoid unnecessary API round-trips. At minimum, check that the value contains @ and a domain with a dot (e.g. user@example.com). Bare strings like alice or not-an-email will be rejected.
Deduplication
The dedupeKey field prevents sending the same email twice. If you submit a request with a dedupeKey that has already been used, the request is blocked with reason duplicate.
Use a deterministic key based on the action -- for example, {templateId}-{recipientEmail} or {orderId}-{recipientEmail}.
Related reading
- How to Send Your First Policy-Checked Email -- end-to-end walkthrough from signup to first send
- What Is Agent-Native Email? -- why email infrastructure needs a policy layer for AI agents