# Create a draft

Source: https://docs.maylee.app/api-reference/drafts/create-draft

`POST https://api.maylee.app/api/v1/drafts`

Scope: `write`.

Creates a draft in one of the workspace mailboxes without sending it. The draft shows up
immediately in the Maylee app, where a person reviews it, edits it and sends it: this is
the way to prepare an email from an integration or an agent while keeping a human in the loop.

Nothing leaves the workspace, so the `write` scope is enough: `allowOutboundSend` is not
required. Attachments cannot be added through the API.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | no | A unique value per operation, such as a UUID. Replays the stored response for 24h. Reusing a key with a different body returns 409. 0 to 255 characters. |

## Request body

`application/json`, required.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `body` | object | yes | `{ "html" }`, `{ "text" }` or both. `text` feeds the preview snippet. |
| `body.html` | string | no |  |
| `body.text` | string | no |  |
| `mailboxId` | string | yes | The mailbox the draft belongs to, and will be sent from. From `GET /mailboxes`. 1 to n characters. |
| `bcc` | array of object | no | Each entry is `{ "email", "name" }`, `name` optional. |
| `bcc[].email` | string (email) | yes |  |
| `bcc[].name` | string | no |  |
| `cc` | array of object | no | Each entry is `{ "email", "name" }`, `name` optional. |
| `cc[].email` | string (email) | yes |  |
| `cc[].name` | string | no |  |
| `inReplyTo` | string | no | `messageId` of the email you answer, to reply in the same conversation. 0 to 998 characters. |
| `references` | array of string | no | The answered email's `references` followed by its `messageId`, in that order. |
| `signature` | string | no | `default` (or omitted): the signature the user would get in the app for the sending address. `none`: no signature. Otherwise the id of a signature from `GET /signatures` (`SIGNATURE_NOT_FOUND` if it does not exist). 1 to 128 characters. |
| `subject` | string | no | Defaults to an empty subject. No line breaks. 0 to 2000 characters. Default: `""`. |
| `to` | array of object | no | Optional: the user can add recipients in the app before sending. Each entry is `{ "email", "name" }`, `name` optional. Default: `[]`. |
| `to[].email` | string (email) | yes |  |
| `to[].name` | string | no |  |

## Example request

```bash
curl -X POST "https://api.maylee.app/api/v1/drafts" \
  -H "Authorization: Bearer $MAYLEE_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "body": {
    "text": "Hello Jane, here is the quote you asked for."
  },
  "inReplyTo": "<CAF3k9x1@mail.example.com>",
  "mailboxId": "cmbx1a2b3c4d5e6f7g8h9i0j",
  "references": [
    "<CAF3k9x1@mail.example.com>"
  ],
  "subject": "Re: Quote request",
  "to": [
    {
      "email": "client@acme.com",
      "name": "Jane Client"
    }
  ]
}'
```

## Responses

### 201

Created. `draft` is the same object `GET /drafts/{draftId}` returns.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `draft` | Email | yes | One email or draft with its metadata, without its body (see `GET /emails/{emailId}/body`). Maylee labels are not included: they are the `tags` of list items. |
| `draft.attachments` | array of Attachment | no | Metadata only. |
| `draft.bcc` | array of EmailAddress | no | Present here, absent from list items. |
| `draft.cc` | array of EmailAddress | no |  |
| `draft.date` | string (date-time) | no |  |
| `draft.folderId` | string | no | Folder the email lives in. |
| `draft.from` | EmailAddress | no |  |
| `draft.hasAttachments` | boolean | no |  |
| `draft.id` | string | no | Maylee id of the email. |
| `draft.inReplyTo` | string or null | no | RFC `In-Reply-To` header. |
| `draft.isAutoForward` | boolean | no | Sent automatically by an auto-forward rule. |
| `draft.isAutoReply` | boolean | no | Sent automatically by Maylee's auto-reply. |
| `draft.isDraft` | boolean | no |  |
| `draft.isRead` | boolean | no |  |
| `draft.isStarred` | boolean | no |  |
| `draft.labels` | array of string | no | Labels as known by the provider (for example Gmail's `INBOX` or `IMPORTANT`), not Maylee labels. |
| `draft.mailboxId` | string | no | Mailbox the email lives in. |
| `draft.messageId` | string | no | RFC `Message-ID` header. Needed to reply in the thread. |
| `draft.references` | array of string | no | RFC `References` header. |
| `draft.scheduledSendAt` | string (date-time) or null | no | For a scheduled draft: when it will be sent. `null` otherwise. |
| `draft.scheduledStatus` | string or null | no | For a scheduled draft: its sending state. `null` otherwise. |
| `draft.snippet` | string | no | Short text preview. |
| `draft.subject` | string | no |  |
| `draft.threadId` | string or null | no | Provider conversation id, when the provider has one. |
| `draft.to` | array of EmailAddress | no |  |
| `draft.waitingForReply` | boolean | no | On an email you sent: Maylee estimates that it still expects an answer. |

```json
{
  "draft": {
    "attachments": [],
    "bcc": [],
    "cc": [],
    "date": "2026-08-25T14:05:40.000Z",
    "folderId": "cmfd9z8y7x6w5v4u3t2s1r0q",
    "from": {
      "email": "contact@your-company.com",
      "name": null
    },
    "hasAttachments": false,
    "id": "cmdr1a2b3c4d5e6f7g8h9i0j",
    "inReplyTo": "<CAF3k9x1@mail.example.com>",
    "isAutoForward": false,
    "isAutoReply": false,
    "isDraft": true,
    "isRead": true,
    "isStarred": false,
    "labels": [
      "\\Draft"
    ],
    "mailboxId": "cmbx1a2b3c4d5e6f7g8h9i0j",
    "messageId": "draft-5f0c2b1e-8a7d-4f3e-9c61-2d4b7a9e0f13@local",
    "references": [
      "<CAF3k9x1@mail.example.com>"
    ],
    "scheduledSendAt": null,
    "scheduledStatus": null,
    "snippet": "Hello Jane, here is the quote you asked for.",
    "subject": "Re: Quote request",
    "threadId": "18c2f5a9e7b1d3c4",
    "to": [
      {
        "email": "client@acme.com",
        "name": "Jane Client"
      }
    ],
    "waitingForReply": false
  }
}
```

### 400

Invalid payload.

### 401

Missing, malformed, revoked or expired API key.

### 403

Key lacks the required scope, or outbound sending is not enabled on it.

### 404

Mailbox not found. Call `GET /mailboxes` for valid ids.

### 409

Idempotency key reused with a different body, or original call still in flight.

### 429

Per-minute rate limit (`RATE_LIMIT_EXCEEDED`) or monthly quota (`QUOTA_EXCEEDED`) exhausted.

Errors use the format `{ "code", "error", "details" }`: see [Errors](/errors.md).
