Send Draft
Send a draft email immediately or at scheduled time
Overview
Send an email draft. If the draft has a send_at timestamp in the future, it will be scheduled for delivery at that time. Otherwise, it will be sent immediately.
Warning
Sending emails requires a paid tier (Developer or higher). Free tier accounts will receive a 402 SEND_REQUIRES_PAID error with upgrade context.
Authentication
AuthorizationstringpathrequiredInbox API Key
Path Parameters
idstringpathrequiredThe inbox ID (e.g., inb_abc123)
draftIdstringpathrequiredThe draft ID (e.g., dft_abc123)
Body Parameters
No request body required.
Request
curl -X POST https://api.daimon.email/v1/inboxes/inb_abc123/drafts/dft_abc123/send \
-H "Authorization: Bearer dm_free_7d8a9b0c1d2e3f4g5h6i7j8k9l0m1n2o"import { DaimonClient } from 'daimon-email';
const client = new DaimonClient({
apiKey: 'dm_free_7d8a9b0c1d2e3f4g5h6i7j8k9l0m1n2o'
});
try {
const result = await client.inboxes.drafts.send('inb_abc123', 'dft_abc123');
console.log(`Status: ${result.status}`);
console.log(`Message ID: ${result.message_id}`);
if (result.status === 'scheduled') {
console.log(`Will be sent at: ${result.scheduled_at}`);
} else {
console.log(`Sent at: ${result.sent_at}`);
}
} catch (error) {
if (error.code === 'SEND_REQUIRES_PAID') {
// Handle upgrade flow
console.log('Upgrade required:', error.upgradeContext.agent_script);
// Generate magic upgrade link
const upgradeLink = await client.account.createUpgradeLink();
console.log('Upgrade URL:', upgradeLink.url);
}
}from daimon_email import DaimonClient, DaimonError
client = DaimonClient(
api_key='dm_free_7d8a9b0c1d2e3f4g5h6i7j8k9l0m1n2o'
)
try:
result = client.inboxes.drafts.send('inb_abc123', 'dft_abc123')
print(f"Status: {result['status']}")
print(f"Message ID: {result['message_id']}")
if result['status'] == 'scheduled':
print(f"Will be sent at: {result['scheduled_at']}")
else:
print(f"Sent at: {result['sent_at']}")
except DaimonError as e:
if e.code == 'SEND_REQUIRES_PAID':
# Handle upgrade flow
print(f"Upgrade required: {e.upgrade_context['agent_script']}")
# Generate magic upgrade link
upgrade_link = client.account.create_upgrade_link()
print(f"Upgrade URL: {upgrade_link['url']}")Response
{
"result": {
"id": "msg_abc123",
"status": "queued",
"message_id": "<abc123@daimon.email>",
"sent_at": "2024-03-11T16:45:00Z",
"scheduled_at": null,
"note": "Email queued for delivery"
},
"next_steps": [
"Use GET /v1/inboxes/{id}/messages/{messageId} to check delivery status",
"Register a webhook to receive 'message.sent' events",
"Monitor delivery via GET /v1/inboxes/{id}/messages"
]
}{
"result": {
"id": "msg_def456",
"status": "scheduled",
"message_id": "<def456@daimon.email>",
"sent_at": null,
"scheduled_at": "2024-03-12T09:00:00Z",
"note": "Email scheduled for delivery at 2024-03-12T09:00:00Z"
},
"next_steps": [
"Use PATCH /v1/inboxes/{id}/drafts/{draftId} to reschedule before send time",
"Use DELETE /v1/inboxes/{id}/drafts/{draftId} to cancel scheduled send",
"Register a webhook to receive 'message.sent' events when delivered"
]
}{
"error": "SEND_REQUIRES_PAID",
"message": "Sending emails requires a paid tier",
"upgrade_context": {
"operator_action_url": "https://daimon.email/upgrade?token=eyJhbGc...",
"operator_action_label": "Add a payment method to enable sending",
"agent_script": "Tell your operator: I need sending access to complete the customer notification. Here's a direct upgrade link: https://daimon.email/upgrade?token=eyJhbGc..."
}
}Response Fields
Success Response
result.idstringMessage ID (converted from draft after sending)
result.statusstringDelivery status: queued (immediate send) or scheduled (future send)
result.message_idstringRFC 5322 Message-ID header value (e.g., <abc123@daimon.email>)
result.sent_atstringISO 8601 timestamp when email was sent (null if scheduled)
result.scheduled_atstringISO 8601 timestamp when email will be sent (null if sent immediately)
result.notestringHuman-readable status message
next_stepsarraySuggested actions the agent can take next
Error Response (402 Payment Required)
errorstringError code: SEND_REQUIRES_PAID
messagestringHuman-readable error message
upgrade_contextobjectInformation to help the agent request an upgrade
Upgrade context object
operator_action_urlstringMagic link for operator to upgrade account (no login required)
operator_action_labelstringButton label for the upgrade action
agent_scriptstringComplete script the agent can use to communicate the upgrade need to the operator
Handling Upgrades
When your agent hits the send limit, it should handle the upgrade flow gracefully:
class EmailAgent {
async sendDraft(inboxId: string, draftId: string) {
try {
const result = await this.client.inboxes.drafts.send(inboxId, draftId);
return result;
} catch (error) {
if (error.code === 'SEND_REQUIRES_PAID') {
// Notify operator with upgrade script
await this.notifyOperator({
message: error.upgradeContext.agent_script,
action_url: error.upgradeContext.operator_action_url,
action_label: error.upgradeContext.operator_action_label
});
// Queue the draft for retry after upgrade
await this.queueForRetry(inboxId, draftId);
return {
status: 'pending_upgrade',
draft_id: draftId
};
}
throw error;
}
}
}See the Magic Upgrade Flow guide for complete implementation patterns.
Delivery Status
After sending, you can track delivery status:
// Check delivery status
const message = await client.inboxes.messages.get('inb_abc123', 'msg_abc123');
console.log('Delivery status:', message.delivery_status);
// Possible values: queued, sent, delivered, bounced, failedInfo
Once a draft is sent, it is converted to a message and can no longer be edited. The draft is automatically deleted after successful send.