Skip to main content
Drafts let you save incomplete email before sending it. Recipients, subject, and body are optional while drafting. A saved draft belongs to one mailbox, counts toward that mailbox’s storage, and does not appear in message, thread, or search results until it is sent. All draft routes are under:
The examples use X-API-Key; supported user and identity tokens can also access these routes. Content mutations use optimistic concurrency: read the current generation, include it in the next mutation, and replace your local value with the generation returned by the API.

Create draft

Create an empty, incomplete, or send-ready draft. Returns a DraftDetailResponse with status 201 and generation 1. The optional Idempotency-Key header makes an initial create safe to retry with the exact same request. If the created draft still exists, a matching retry returns it instead of creating a duplicate. Reusing the key with different content, or after the draft was sent or deleted, returns 409 idempotency_key_reused; use a new key for a new logical create.

Request body

Forward drafts use forward_note_text and forward_note_html instead of the generic body fields. Reply fields and forward fields cannot be combined.

Example

bash
To start a reply draft, pass the thread context you already hold. The create and update request field is named in_reply_to_message_id; detail responses expose the resolved header as in_reply_to.

List drafts

Returns drafts newest-update first in the standard cursor page shape.
JSON

Get draft

Returns the current DraftDetailResponse, including bodies and attachment descriptors. A draft may be read in any send state.

Update draft

Partially update the expected revision. generation is required. Omitted fields are preserved; an explicit null clears a nullable field. Attachments are preserved and are changed through the attachment endpoints.
bash
A semantic change increments the generation. A request that changes nothing may return the existing generation.

Duplicate draft

Copy an exact revision into a new editable draft. The copy receives a new draft ID, generation 1, and a new Message-ID. It uses storage independently from the source.
JSON
This is the safe way to continue from a draft whose delivery status is uncertain: review the copy before deciding whether to send it.

Delete draft

Permanently delete the expected revision and free its storage. Returns 204 No Content. An uncertain draft can be deleted; a draft currently being sent cannot.

Add attachments

Add one or more attachments to the expected generation. Returns the updated DraftDetailResponse and a new generation.
JSON
AttachmentUpload has filename, content_type, and content_base64, with filename and content type limited to 255 characters. A request can add up to 50 attachments, and decoded attachment input cannot exceed 25 MB. Requests may be rejected for policy reasons. The complete encoded draft must remain below 9.5 MiB. The optional content_id marks an inline image referenced from HTML as cid:<content_id>. Content IDs must be unique, use an image/* content type, and require the draft to have an HTML body. Forward drafts do not accept inline attachments.

Remove attachment

Remove the attachment identified by its current part_index. Returns the updated detail and generation. Part indexes belong to a specific generation, so always use a descriptor from the revision you are mutating. For a wrapped forward, the message/rfc822 part containing the original message cannot be removed. Other attachments remain removable.

Download attachment

Streams the decoded attachment body with its content type and download filename. The generation is required because an edit can change part indexes.
bash

Send draft

Validate and send the exact revision. The mailbox’s current enabled custom signature is applied at send time, not when saving the draft. The final draft must contain at least one recipient and satisfy the ordinary outbound mail requirements.
JSON
A successful request returns the canonical MessageResponse and removes that draft. Repeating the same request after a lost successful response may return the same sent message rather than sending again. A validation, policy, quota, storage, or other rejection before delivery is attempted leaves the draft editable at the same generation. Use the returned structured error to decide whether to edit or retry.

Response objects

DraftSummaryResponse

DraftDetailResponse

Includes every summary field plus: in_reply_to_message_id is the create/update request field; in_reply_to is the detail response field.

DraftAttachmentResponse

Conflicts and delivery state

Draft conflicts use 409 Conflict. Branch on detail.error, not on status alone. An uncertain draft is readable and deletable but cannot be edited or sent.

Storage behavior

Draft bytes count toward mailbox storage as soon as the draft is saved. Attachments and duplicate drafts count independently. A successful send replaces the draft’s storage usage with the final sent message’s usage rather than keeping both indefinitely. Rejected sends preserve the draft and its existing storage.

Mail-app interoperability

The Inkbox Console, REST API, and connected mail apps share the same Drafts mailbox. An edit from another surface may appear in a mail app as the old draft being replaced by a new revision. Mail apps save drafts through IMAP and send through SMTP. After SMTP reports success, the mail app is responsible for removing its own saved draft. An unrelated SMTP submission is not matched to a draft automatically. IMAP APPEND accepts drafts up to 10 MB. Final send preparation can require additional headroom, so a draft saved near that limit may be rejected when sent. The failed send leaves the draft intact for editing or deletion. See Email drafts for user workflows and Use a mail app for connection setup.