Drafts
A draft is an email written in Carom and not yet sent: a new message, or a reply to a thread. It records the mailbox it will go out from, its recipients, and its body. Use this resource to prepare messages for a person to review and send.
Drafts are private to their author. Your key sees and edits only the drafts of your key’s user. Sending happens in the Carom app; the API can write drafts but not send them. After sending, status changes as delivery progresses, and the draft stays readable here as a record of what went out.
#The draft object
Returned by every draft endpoint.
Attributes
-
idstring · uuidUnique identifier for the draft.
-
statusstringThe draft’s delivery status. Only
draftandfaileddrafts can be edited or deleted.queued: accepted for sending.sending: being handed to the provider.sent: the provider accepted it.failed: delivery failed, andlast_errorsays why; editing it returns it todraft.cancelled: its mailbox was deleted before delivery began.delivery_unknown: its mailbox was deleted during delivery, so it may or may not have gone out.draftqueuedsendingsentfailedcancelleddelivery_unknown -
draft_typestring · nullableA new message, or a reply in an existing thread.
composereply -
mailbox_idstring · uuid · nullableThe mailbox the draft will be sent from. Null after that mailbox has been deleted.
-
thread_idstring · uuid · nullableThe thread a reply belongs to. Null for
composedrafts. -
to_email_addressesarray of strings -
cc_email_addressesarray of strings -
bcc_email_addressesarray of strings -
subjectstring · nullable -
bodystring · nullableThe plain-text body.
-
body_htmlstring · nullableThe HTML body, as Carom stored it after sanitizing. When it is set, the message is sent with both bodies, and
bodyis the plain-text version. -
content_statestring · nullableAn opaque string your client can store with the draft. Carom returns it unchanged; it has no effect on the message sent.
-
last_errorobject · nullableWhy the most recent delivery attempt failed. Null when no attempt has failed.
Show 2 child attributesHide child attributes
-
codestringA stable code for the failure.
delivery_failedis the general case.outbound_disabledsend_permission_lostmailbox_not_authorizedrate_limitedprovider_rejecteddelivery_setup_failedlocal_delivery_failedenqueue_faileddelivery_never_starteddelivery_admission_failedmailbox_deletedmailbox_deleted_during_deliverydelivery_failed -
messagestringA sentence describing the failure that is safe to show the user. The provider’s own error isn’t returned.
-
-
rfc_idstring · nullableThe
Message-IDCarom assigned when delivery began, without angle brackets. Null until then. -
created_atstring · date-time · nullable -
updated_atstring · date-time · nullable -
queued_atstring · date-time · nullableWhen your key’s user sent the draft.
-
sending_atstring · date-time · nullableWhen Carom began handing it to the provider.
-
sent_atstring · date-time · nullableWhen the provider accepted it.
-
last_failed_atstring · date-time · nullable
{
"id": "8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31",
"status": "draft",
"draft_type": "reply",
"mailbox_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70",
"thread_id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"to_email_addresses": ["priya@wildgrove.example"],
"cc_email_addresses": [],
"bcc_email_addresses": [],
"subject": "Re: Q4 renewal terms",
"body": "Hi Priya, confirmed: the per-site rate stays the same for the 12-month term. Paperwork to follow by the 15th.",
"body_html": "<p>Hi Priya, confirmed: the per-site rate stays the same for the 12-month term. Paperwork to follow by the 15th.</p>",
"content_state": null,
"last_error": null,
"rfc_id": null,
"created_at": "2026-09-05T14:08:51.133Z",
"updated_at": "2026-09-05T14:12:03.538Z",
"queued_at": null,
"sending_at": null,
"sent_at": null,
"last_failed_at": null
}
#List drafts
Returns every draft your key’s user has written, in any status, most recently updated first. Pass thread_id to get only the drafts for one thread. Returns every draft in one response; the list isn’t paginated.
Query parameters
-
thread_idstring · uuidOnly drafts replying to this thread.
Returns
-
draftsarray of drafts
Errors
- 400
invalid_requestthread_idis present but empty.
curl "https://api.carom.io/drafts?thread_id=7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57" \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"drafts": [
{
"id": "8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31",
"status": "draft",
"draft_type": "reply",
"subject": "Re: Q4 renewal terms",
"updated_at": "2026-09-05T14:12:03.538Z",
…
},
{
"id": "c5e9b2d7-1a4f-4c8e-9b3d-6e0a8f2c5d19",
"status": "sent",
"draft_type": "reply",
"subject": "Re: Q4 renewal terms",
"updated_at": "2026-09-01T16:20:14.313Z",
…
}
]
}
#Create a draft
Creates a draft for your key’s user, with status draft. Give a mailbox visible to your key. For a reply, also give the thread; if you leave out the subject, Carom uses the thread’s subject with Re: in front.
Carom doesn’t check recipients or sending permission until the draft is sent, so a draft can be saved incomplete.
Request body application/json
-
draftobjectrequiredShow 10 child attributesHide child attributes
-
mailbox_idstring · uuidrequiredThe mailbox to send from.
-
draft_typestringdefaultcomposecomposereply -
thread_idstring · uuidRequired when
draft_typeisreply. Ignored forcompose. -
to_email_addressesarray of strings -
cc_email_addressesarray of strings -
bcc_email_addressesarray of strings -
subjectstring · nullable -
bodystring · nullablePlain text. Sent as the whole message when
body_htmlis empty, and as the plain-text version otherwise. -
body_htmlstring · nullableHTML. Carom sanitizes it before storing: formatting, links, tables, inline styles, and images are kept, and scripts, event handlers, and
javascript:URLs are removed. -
content_statestring · nullableAn opaque string to store with the draft, such as your editor’s state.
-
Returns
The new draft object, wrapped in draft, with status 201.
Errors
- 400
invalid_requestA field failed validation, for example a missingmailbox_idor an unknowndraft_type.error.fieldssays which. - 400
missing_thread_idA reply was requested without athread_id. - 404
record_not_foundThe mailbox or thread isn’t visible to your key.
curl https://api.carom.io/drafts \
-H "Authorization: Bearer $CAROM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"draft": {
"draft_type": "reply",
"mailbox_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70",
"thread_id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"to_email_addresses": ["priya@wildgrove.example"],
"body": "Hi Priya, confirmed: the per-site rate stays the same for the 12-month term."
}
}'
{
"draft": {
"id": "8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31",
"status": "draft",
"draft_type": "reply",
"mailbox_id": "d4e5f6a7-b8c9-4d0e-9f1a-2b3c4d5e6f70",
"thread_id": "7c2e9a14-5b3d-4f8e-9a61-3d0b8e2f4c57",
"to_email_addresses": ["priya@wildgrove.example"],
"subject": "Re: Q4 renewal terms",
"body": "Hi Priya, confirmed: the per-site rate stays the same for the 12-month term.",
"body_html": null,
"created_at": "2026-09-05T14:08:51.133Z",
…
}
}
#Retrieve a draft
Returns a single draft. After your key’s user sends it, poll this endpoint to follow status through delivery.
Path parameters
-
idstring · uuidrequiredThe draft’s id.
Returns
The draft object, wrapped in draft.
Errors
- 404
record_not_foundNo draft with that id belongs to your key’s user.
curl https://api.carom.io/drafts/c5e9b2d7-1a4f-4c8e-9b3d-6e0a8f2c5d19 \
-H "Authorization: Bearer $CAROM_API_KEY"
{
"draft": {
"id": "c5e9b2d7-1a4f-4c8e-9b3d-6e0a8f2c5d19",
"status": "sent",
"draft_type": "reply",
"subject": "Re: Q4 renewal terms",
"rfc_id": "4b7e2c9a-6d1f-4a3e-8c5b-0e9d7f2a1c64@carom.io",
"queued_at": "2026-09-01T16:20:09.128Z",
"sending_at": "2026-09-01T16:20:11.336Z",
"sent_at": "2026-09-01T16:20:14.313Z",
"last_error": null,
…
}
}
#Update a draft
Changes the fields you send and leaves the rest alone. Recipient lists are replaced whole, not merged. The thread and type can’t be changed after creation.
To change the mailbox the draft is sent from, send a different mailbox_id. Your key’s user must be able to send from the new mailbox now, the same check Carom makes when a draft is sent. Sending the draft’s current mailbox_id changes nothing and isn’t checked.
Only drafts with status draft or failed can be edited. Editing a failed draft sets it back to draft so your key’s user can send it again.
Path parameters
-
idstring · uuidrequired
Request body application/json
-
draftobjectrequiredAny of
mailbox_id,to_email_addresses,cc_email_addresses,bcc_email_addresses,subject,body,body_html, andcontent_state, as on Create a draft. Sendnullto clear a text field.
Returns
The updated draft object, wrapped in draft.
Errors
- 400
invalid_requestA field failed validation.error.fieldssays which. - 403
permission_deniedYour key’s user isn’t allowed to send from the new mailbox. - 404
record_not_foundNo draft with that id belongs to your key’s user, or the new mailbox isn’t visible to your key. - 409
not_editable_statusThe draft’s status isn’tdraftorfailed. - 422
mailbox_not_authorizedThe new mailbox has no working connection. Its owner must reconnect it in the Carom app. - 422
capability_not_grantedThe new mailbox’s owner didn’t grant Carom permission to send from it. The owner must reconnect it in the Carom app.
curl -X PATCH https://api.carom.io/drafts/8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31 \
-H "Authorization: Bearer $CAROM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"draft": {
"cc_email_addresses": ["owen@harborline.example"],
"body": "Hi Priya, confirmed: the per-site rate stays the same for the 12-month term. Paperwork to follow by the 15th."
}
}'
{
"draft": {
"id": "8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31",
"status": "draft",
"cc_email_addresses": ["owen@harborline.example"],
"body": "Hi Priya, confirmed: the per-site rate stays the same for the 12-month term. Paperwork to follow by the 15th.",
"updated_at": "2026-09-05T14:12:03.538Z",
…
}
}
#Delete a draft
Permanently deletes a draft with status draft or failed. Drafts in any other status can’t be deleted.
Path parameters
-
idstring · uuidrequired
Returns
An empty response with status 204.
Errors
- 404
record_not_foundNo draft with that id belongs to your key’s user. - 409
not_editable_statusThe draft’s status isn’tdraftorfailed.
curl -X DELETE https://api.carom.io/drafts/8a3f1c6e-7d2b-4e9a-b5c8-4f0e2d7a9b31 \
-H "Authorization: Bearer $CAROM_API_KEY"
No content