---
title: "Edit a draft's envelope"
method: PATCH
path: "/api/v1/drafts/{id}"
tags: ["drafts"]
---

# Edit a draft's envelope

`PATCH /api/v1/drafts/{id}`

## Request

- Base URL: `https://postfleet.ai`
- URL: `https://postfleet.ai/api/v1/drafts/{id}`
- Auth: HTTP bearer

Merges `to`/`subject`/`text` over the stored draft and re-validates the recipient through the send path's single-recipient guard. Requires `can_send`. The reply context is immutable: supplying `reply_to_message_id` is rejected `400`.

## Path parameters

- `id` string, required

## Request body

- UpdateDraftRequest: Omitted fields keep the stored value. `reply_to_message_id` is immutable and rejected if supplied.
  - `to` string: New single-recipient address.
  - `subject` string
  - `text` string
  - `attachments` union[]: Replace the draft attachments. Omit to keep the stored files; pass [] to clear them. URL-backed files are stored as the URL and fetched when the draft is sent.
    - union
      - object
        - `filename` string: Basename only — no path separators. Derived from the URL path, or `attachment`, when omitted.
        - `content` string, required: File bytes, standard base64.
        - `content_type` string: MIME type. Defaults to application/octet-stream, or the URL response Content-Type.
      - object
        - `filename` string: Basename only — no path separators. Derived from the URL path, or `attachment`, when omitted.
        - `url` string, required: HTTPS URL fetched at send time. Not forwarded to the provider.
        - `content_type` string: MIME type. Defaults to application/octet-stream, or the URL response Content-Type.

## Response `200`

Updated draft.

- Draft
  - `id` string, required
  - `mailbox_id` string, required
  - `status` 'draft' | 'pending_approval' | 'sending' | 'sent' | 'rejected', required
  - `to` string, nullable
  - `subject` string, required
  - `text` string, required
  - `reply_to_message_id` string, nullable
  - `requires_human` boolean, required
  - `thread_id` string, required
  - `created_at` string, required
  - `updated_at` string, required
  - `attachments` object[]: Metadata only — file bytes are not returned.
    - `filename` string, required
    - `content_type` string, required
    - `size_bytes` integer, required
    - `url` string: Present when the draft stored a URL-backed attachment. Bytes are never returned.

## Other responses

- `400`: `reply_to_message_id` cannot be changed, or the merged `to` is not a single address.
- `401`: Missing or invalid bearer token, or a key whose scope is not permitted for this endpoint.
- `403`: Key cannot send (`code:key_scope`).
- `404`: Draft not found (missing, cross-account, cross-mailbox for a bound key, or tombstoned). Byte-identical for every case (anti-enumeration).
- `409`: Draft is no longer editable (already sending or terminal).

---

[API](https://skmtc.dev/postfleet/apis/postfleet-api.md) · [All operations](https://skmtc.dev/postfleet/apis/postfleet-api/llms.txt) · [OpenAPI document](https://skmtc.dev/postfleet/apis/postfleet-api/revisions/bae1dabfa89e?raw)
