> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waterr.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Drafts

> Write now, send on approval or on a schedule — the pattern for human-in-the-loop agents.

A draft is a composed message that has not been sent. It is the right primitive whenever a person should see what the agent wrote before the recipient does.

```bash theme={null}
POST /v0/inboxes/{inbox_id}/drafts
```

```json theme={null}
{
  "to": ["customer@example.com"],
  "subject": "Your refund for order 4471",
  "text": "Hi — the refund is processed.",
  "in_reply_to": "msg_4tq8rv2mzx7kd9nbhf3wpc6s",
  "client_id": "review-8821"
}
```

| Field                     | Notes                                                                 |
| ------------------------- | --------------------------------------------------------------------- |
| `to`, `cc`, `bcc`         | Recipients.                                                           |
| `subject`, `text`, `html` | Content.                                                              |
| `thread_id`               | Files the sent message onto an existing thread.                       |
| `in_reply_to`             | Parent message id. `reply_to_message_id` is accepted as an alias.     |
| `reply_to`                | Overrides the generated thread-token `Reply-To`.                      |
| `send_at`                 | ISO-8601 timestamp. Sends automatically at that time.                 |
| `client_id`               | Your own identifier — the ticket or review row this draft belongs to. |
| `labels`                  | Applied to the draft.                                                 |

## The approval loop

<Steps>
  <Step title="The agent composes">
    Your model produces the reply; you store it as a draft rather than sending it.

    ```bash theme={null}
    POST /v0/inboxes/ava@agent.waterr.ai/drafts
    ```
  </Step>

  <Step title="A human reviews">
    Show the draft in your own UI. `GET /v0/inboxes/{inbox_id}/drafts` lists what is pending.
  </Step>

  <Step title="Edit if needed">
    ```bash theme={null}
    PATCH /v0/inboxes/ava@agent.waterr.ai/drafts/dft_9k3mxz7bd2vr8ncq4twf6hps
    { "text": "Checked again — it cleared this morning." }
    ```
  </Step>

  <Step title="Send, or discard">
    ```bash theme={null}
    POST   /v0/inboxes/ava@agent.waterr.ai/drafts/dft_9k3mxz.../send
    DELETE /v0/inboxes/ava@agent.waterr.ai/drafts/dft_9k3mxz...
    ```

    Sending threads the message exactly as a direct send would — `thread_id` and `in_reply_to` are honoured, so an approved reply lands on the right conversation rather than starting a new one.
  </Step>
</Steps>

This loop is worth reaching for earlier than feels necessary. An agent that drafts is recoverable when it gets something wrong; an agent that sends is not, because email has no unsend.

## Scheduled sending

Set `send_at` and the draft sends itself at that time — no cron on your side, no process that has to stay up.

```json theme={null}
{
  "to": ["customer@example.com"],
  "text": "Following up on the refund we discussed.",
  "thread_id": "thd_9k3mxz7bd2vr8ncq4twf6hps",
  "send_at": "2026-10-02T09:00:00.000Z"
}
```

The inbox schedules an internal alarm for that timestamp. A scheduled draft is an ordinary draft until it fires, so you can still edit it, reschedule it by patching `send_at`, or delete it to cancel.

<Tip>
  `send_at` combines well with `thread_id`: a follow-up queued at the moment the agent makes the promise, on the conversation where it made it. Nothing has to remember to do it later.
</Tip>

## Idempotency

`client_id` is yours to set and is stored with the draft. Use it to tie a draft back to whatever produced it — a ticket, an approval row, a run id — so a retry in your own code can look up whether a draft already exists rather than creating a second one.
