# Edit a draft

PATCH /v1/drafts/{draft_id}

Source: https://cherami.to/docs/api/drafts/update-draft



{/* Generated from apps/web/openapi. Edit the contract, not this file. */}

`PATCH /v1/drafts/{draft_id}`

Requires a [Claim-issued API key](https://cherami.to/docs/api#authentication): `Authorization: Bearer YOUR_CREDENTIAL`.

Supply at least one editable creation field, excluding `source` and `idempotency_key`. Only supplied fields change. Recipient arrays, attachments and labels replace their entire respective lists. When revising `text`, revise or clear `html` separately if needed; Cherami does not synchronize the alternatives. New attachment inputs use the ordinary three-field format, not service-generated inline metadata.

Successful edits return `200` with draft metadata. Concurrent edits to different fields preserve both changes; the last saved value wins for the same field. No version parameter or review lock is supported. Repeated contention can return `409 draft_busy`; retrieve current content before editing again. After an uncertain acknowledgement, also retrieve before repeating an edit that might overwrite another agent's work.

Submitted drafts return `409 draft_submitted` and cannot be edited or returned to draft.

## Parameters [#parameters]

| Parameter  | Location | Required | Type   | Meaning                                        |
| ---------- | -------- | -------- | ------ | ---------------------------------------------- |
| `draft_id` | path     | Yes      | string | Owned Cherami resource ID returned by the API. |

## Request body [#request-body]

JSON object. Total UTF-8 request body limit: 8388608 bytes.

### Schema: UpdateDraft [#schema-updatedraft]

Only supplied fields change; arrays replace their entire lists. No source, version, review lock or idempotency key. Submitted drafts cannot be edited.

| Field         | Required | Type                                                        | Meaning and constraints                                                              |
| ------------- | -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `to`          | No       | array of [Mailbox](#schema-mailbox)                         | `maxItems`: `50`                                                                     |
| `cc`          | No       | array of [Mailbox](#schema-mailbox)                         | `maxItems`: `50`                                                                     |
| `bcc`         | No       | array of [Mailbox](#schema-mailbox)                         | `maxItems`: `50`                                                                     |
| `subject`     | No       | string                                                      | No control characters; at most 998 UTF-8 bytes. `x-max-utf8-bytes`: `998`            |
| `text`        | No       | string                                                      | Plain-text body.                                                                     |
| `html`        | No       | string or null                                              |                                                                                      |
| `attachments` | No       | array of [AttachmentInput](#schema-attachmentinput) or null | Omitted or null means no attachments; an empty array also clears draft attachments.  |
| `in_reply_to` | No       | string or null                                              |                                                                                      |
| `labels`      | No       | array of [Label](#schema-label)                             | Trimmed, deduplicated and case-sensitive. Order is not significant. `maxItems`: `32` |

Unknown fields are rejected.

At least 1 field must be supplied.

## curl example [#curl-example]

Replace resource-ID placeholders with returned IDs. Supply `CHERAMI_API_KEY` through your private shell environment.

Save the intended payload as a private `request.json` file and replace illustrative values. For an uncertain response, follow the [operation-specific recovery rules](https://cherami.to/docs/api/errors#retry-by-operation).

```json
{
  "text": "Revised proposal.",
  "html": null
}
```

```sh
curl --silent --show-error --include --request PATCH \
  "https://cherami.to/v1/drafts/DRAFT_ID" \
  --header "Authorization: Bearer $CHERAMI_API_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary @request.json
```

## Responses [#responses]

### HTTP 200 [#http-200]

Successful operation; inspect resource state and outcome fields.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[DraftMetadata](#schema-draftmetadata)

```json
{
  "id": "11111111-1111-4111-8111-111111111111",
  "inbox_id": "11111111-1111-4111-8111-111111111111",
  "state": "draft",
  "subject": "Example",
  "created_at": "2026-10-01T00:00:00.000Z",
  "updated_at": "2026-10-01T00:00:00.000Z",
  "sent_message_id": null
}
```

### HTTP 400 [#http-400]

`invalid_json`: Send a valid UTF-8 JSON object, not an array or scalar.

`invalid_draft`: Use supported draft fields, source preparation or listing parameters. Draft cursors that are malformed or do not match the inbox/state also use this code.

`invalid_message`: Correct the send fields, recipients, reply ID, or attachments using the message's guidance.

`invalid_name`: Correct the inbox, sender or recipient display name using the returned guidance.

`invalid_labels`: Correct label names, changes, filter groups, or discovery prefix.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

### HTTP 401 [#http-401]

`unauthorized`: Provide a valid bearer credential. Use [human-approved recovery](https://cherami.to/docs/guides/recovery) if access is lost.

* `X-Request-ID`: Support correlation ID, not an idempotency key.
* `WWW-Authenticate`: `"Bearer"`

Content type: `application/json`.

[Error](#schema-error)

### HTTP 404 [#http-404]

`not_found`: Resource is absent or inaccessible to this account. Reply targets must be in the sending inbox.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

### HTTP 409 [#http-409]

`draft_busy`: An edit/send raced other changes. Retrieve current content before trying again.

`draft_submitted`: Submitted drafts cannot be edited or returned to draft. Retrieve the linked sent message.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

### HTTP 413 [#http-413]

`body_too_large`: Reduce the JSON request to the endpoint's body limit.

`message_too_large`: Reduce message content and attachments. Passing local checks does not guarantee generated MIME fits the provider limit.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

### HTTP 415 [#http-415]

`unsupported_media_type`: Send `Content-Type: application/json`.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

### HTTP 503 [#http-503]

`content_unavailable`: Expected stored content is unavailable. Retry the read later.

`draft_unavailable`: Draft operation is uncertain. Follow [draft-specific recovery](https://cherami.to/docs/api/drafts); do not blindly create a replacement.

* `X-Request-ID`: Support correlation ID, not an idempotency key.

Content type: `application/json`.

[Error](#schema-error)

## Schema: DraftMetadata [#schema-draftmetadata]

| Field             | Required | Type                       | Meaning and constraints                                                                                                              |
| ----------------- | -------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `id`              | Yes      | string                     | Cherami resource ID, distinct from the RFC Message-ID. Use the returned value.                                                       |
| `inbox_id`        | Yes      | string                     | Cherami resource ID, distinct from the RFC Message-ID. Use the returned value.                                                       |
| `state`           | Yes      | `"draft"` or `"submitted"` |                                                                                                                                      |
| `subject`         | Yes      | string                     |                                                                                                                                      |
| `created_at`      | Yes      | string                     | UTC service instant with milliseconds and Z suffix. `format`: `date-time` `pattern`: `^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$` |
| `updated_at`      | Yes      | string                     | UTC service instant with milliseconds and Z suffix. `format`: `date-time` `pattern`: `^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$` |
| `sent_message_id` | Yes      | string or null             |                                                                                                                                      |

## Schema: Error [#schema-error]

| Field   | Required | Type   | Meaning and constraints |
| ------- | -------- | ------ | ----------------------- |
| `error` | Yes      | object |                         |

### `error` fields [#error-fields]

| Field     | Required | Type   | Meaning and constraints                                                                       |
| --------- | -------- | ------ | --------------------------------------------------------------------------------------------- |
| `code`    | Yes      | string | Programmatic error code. Handle unrecognized codes by status and operation-specific recovery. |
| `message` | Yes      | string | Human-readable context, not a stable string to match.                                         |

## Schema: Mailbox [#schema-mailbox]

| Field     | Required | Type   | Meaning and constraints                                                                                                              |
| --------- | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `address` | Yes      | string | Bare ASCII address, at most 254 characters, local part at most 64. No display-name header syntax. `maxLength`: `254`                 |
| `name`    | No       | string | Unicode name, trimmed; blank means unnamed. No control characters. At most 256 UTF-8 bytes after trimming. `x-max-utf8-bytes`: `256` |

Unknown fields are rejected.

## Schema: AttachmentInput [#schema-attachmentinput]

| Field      | Required | Type   | Meaning and constraints                                                                                                                                                           |
| ---------- | -------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `filename` | Yes      | string | Nonempty, no control characters, slash or backslash. At most 255 UTF-8 bytes. `minLength`: `1` `x-max-utf8-bytes`: `255`                                                          |
| `type`     | Yes      | string | MIME type without parameters. `maxLength`: `127` `pattern`: `^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$`                                                                       |
| `content`  | Yes      | string | Padded base64 original bytes, no whitespace; encoded length must be a multiple of four. Empty files are accepted. `contentEncoding`: `base64` `pattern`: `^[A-Za-z0-9+/]*={0,2}$` |

Unknown fields are rejected.

## Schema: Label [#schema-label]

1–128 UTF-8 bytes after trimming. Well-formed Unicode without control characters; case-sensitive.

string. `x-max-utf8-bytes`: `128`

[HTTP conventions, errors and pagination](https://cherami.to/docs/api/errors) · [Download OpenAPI 3.1](https://cherami.to/openapi.json)
