MOLTED EMAIL

Outbound

Send and reply to email from a specific mailbox using the mailbox-scoped outbound API.

The outbound API is the mailbox-scoped send surface used by agentic mailbox clients. It handles thread projection, canary token detection, deduplication, and autonomy level gating per mailbox.

Outbound vs. agent send

Molted provides two sending surfaces:

EndpointBest for
POST /v1/agent/request-sendTenant-level sends from any agent. Full policy trace and scheduled send support.
POST /v1/agent/outbound/sendMailbox-scoped sends. Thread projection, canary detection, per-mailbox autonomy enforcement.

Use /v1/agent/outbound/send when your agent acts on behalf of a specific mailbox and you want thread continuity and per-mailbox autonomy controls. Use /v1/agent/request-send for general-purpose tenant-level sends.

See Sending Email for full documentation on the agent send endpoint.

Endpoints

MethodPathDescription
POST/v1/agent/outbound/sendSend an email from a mailbox
POST/v1/agent/outbound/replyReply to an existing thread
POST/v1/agent/outbound/schedule-followupSchedule a followup if no reply is received

All endpoints require Bearer authentication and the automation API key scope.

Send

Send a new email from a mailbox. Creates a new thread if no matching thread exists.

POST https://api.molted.email/v1/agent/outbound/send
curl
curl -X POST "https://api.molted.email/v1/agent/outbound/send?tenantId=TENANT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipientEmail": "alice@example.com",
    "templateId": "welcome",
    "dedupeKey": "welcome-alice-1",
    "payload": { "name": "Alice" },
    "mailboxId": "mbx_abc123"
  }'

Request body

FieldTypeRequiredDescription
recipientEmailstringYesRecipient email address
templateIdstringYesTemplate ID to use for the send
dedupeKeystringYesUnique key to prevent duplicate sends. Same key on a second call returns the original result.
payloadobjectYesTemplate variables
mailboxIdstringNoSend from a specific mailbox. Enables per-mailbox autonomy level enforcement.
threadIdstringNoAssociate with an existing thread
subjectstringNoOverride the email subject
sendReasonstringNoReason for sending, recorded in the decision trace
idempotencyKeystringNoAlternative deduplication key

Response

Response
{
  "status": "sent",
  "requestId": "req_abc123",
  "threadId": "thr_abc123"
}

Response status values:

StatusMeaning
sentQueued for delivery
blockedBlocked by the policy engine
pending_approvalHeld by the mailbox's autonomy level
duplicateSame dedupeKey was already used

A blocked or pending_approval status is not an error - it means the policy engine or autonomy level is working correctly. Always check the status field.

CLI

molted send
# The send CLI uses /v1/agent/request-send by default
# To use the outbound endpoint, see: molted threads reply

molted send --to alice@example.com --template welcome \
  --dedupe-key "welcome-alice-1" --payload '{"name": "Alice"}' \
  --mailbox mbx_abc123

Reply

Reply to an existing thread. The reply is sent from the mailbox that owns the thread.

POST https://api.molted.email/v1/agent/outbound/reply
curl
curl -X POST "https://api.molted.email/v1/agent/outbound/reply?tenantId=TENANT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "threadId": "thr_abc123",
    "templateId": "_default",
    "dedupeKey": "reply-alice-1",
    "payload": { "body": "Thanks for reaching out - we will get back to you shortly." }
  }'

Request body

FieldTypeRequiredDescription
threadIdstringYesThread to reply to
templateIdstringYesTemplate ID. Use _default for plain-text replies.
dedupeKeystringYesUnique key to prevent duplicate replies
payloadobjectYesTemplate variables
sendReasonstringNoReason for replying
idempotencyKeystringNoAlternative deduplication key

CLI

molted threads reply
# Shorthand with plain text body
molted threads reply thr_abc123 --body "Thanks for reaching out!"

# With a specific template and payload
molted threads reply thr_abc123 \
  --template-id follow-up \
  --payload '{"name": "Alice"}' \
  --dedupe-key "reply-alice-2"

Schedule followup

Schedule a followup email that sends automatically if the contact does not reply within a specified delay.

POST https://api.molted.email/v1/agent/outbound/schedule-followup
curl
curl -X POST "https://api.molted.email/v1/agent/outbound/schedule-followup?tenantId=TENANT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactEmail": "alice@example.com",
    "threadRequestId": "req_abc123",
    "delayMinutes": 4320,
    "cancelOnReply": true
  }'

Request body

FieldTypeRequiredDescription
contactEmailstringYesContact email address
threadRequestIdstringYesThe requestId from the initial send response
delayMinutesintegerYesDelay in minutes before the followup sends (1-43200, max 30 days)
cancelOnReplybooleanNoCancel the followup automatically if the contact replies first
triggerConditionsobjectNoAdditional trigger conditions

CLI

molted threads followup
# Schedule followup 72 hours after initial send
molted threads followup req_abc123 \
  --contact-email alice@example.com \
  --delay-hours 72 \
  --cancel-on-reply

Deduplication

Every outbound send and reply requires a dedupeKey. The same key on a second call returns the original result without sending again. Use deterministic keys based on your workflow, contact, and step:

{workflow}-{contact-id}-{step}
# e.g. "onboard-alice-day1", "renewal-alice-2026q1"

If you use an auto-generated key (like the CLI does with --dedupe-key auto), each call is treated as a new send.

Autonomy levels

Outbound sends through a mailbox are subject to that mailbox's autonomy level:

  • L1 (Assisted) - Every send requires human approval. Response status: pending_approval.
  • L2 (Guarded Auto) - First message to a new contact requires approval. Subsequent messages send automatically.
  • L3 (Fully Autonomous) - All policy-approved sends execute immediately.

When a send is held for approval, use the approval queues API to review and release it.