Drafts
Compose now, send later.
A draft is a message that has not been sent. Useful when a human approves what an agent wrote before it goes out.
curl -X POST https://api.carlyemail.com/v0/inboxes/$INBOX_ID/drafts \
-H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
-H 'content-type: application/json' \
-d '{
"to": ["customer@example.org"],
"subject": "Following up",
"text": "Draft body"
}'
Update it, attach files, then send:
curl -X POST https://api.carlyemail.com/v0/inboxes/$INBOX_ID/drafts/$DRAFT_ID/send \
-H "Authorization: Bearer $CARLYEMAIL_API_KEY"
Sending a draft applies the same quota, suppression and verification checks as a direct send — a draft is not a way around them.
Reply and forward drafts
Pass in_reply_to to build a reply from an existing message. CarlyEmail derives
the recipients, Re: subject and threading headers, so the saved draft is ready
for human review rather than merely tagged as a reply. Set reply_all: true to
include the other original recipients; do not also supply to, cc or bcc.
Pass forward_of to build a forward. CarlyEmail derives the Fwd: subject and
merges the original body and attachments when the draft is sent, while keeping
the editable draft body as your preface. in_reply_to and forward_of are
mutually exclusive, and both require message_read permission.
Schedule a send
Set send_at when creating or updating a draft. It must be a future ISO-8601
timestamp with a timezone:
curl -X POST https://api.carlyemail.com/v0/inboxes/$INBOX_ID/drafts \
-H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
-H 'content-type: application/json' \
-d '{
"to": ["customer@example.org"],
"subject": "Checking in tomorrow",
"text": "How did the launch go?",
"send_at": "2026-08-04T14:00:00Z"
}'
The worker checks once a minute, so delivery starts within roughly a minute of
send_at; it is not a second-precision timer. While waiting, send_status is
scheduled. The draft is consumed after a successful send. If sending fails,
the draft stays readable with send_status: "failed" instead of retrying
forever or disappearing.
Cancel a pending schedule without deleting the draft:
curl -X PATCH https://api.carlyemail.com/v0/inboxes/$INBOX_ID/drafts/$DRAFT_ID \
-H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
-H 'content-type: application/json' \
-d '{"send_at": null}'
Scheduled delivery is at-least-once. The worker atomically claims a draft to prevent concurrent sends, but no email provider can make “SES accepted the message” and “our database recorded success” one transaction. A process crash in that narrow gap can produce a duplicate, so recipients of automated mail should tolerate one.