diff --git a/changelog.mdx b/changelog.mdx
index b43a845..aecf4f1 100644
--- a/changelog.mdx
+++ b/changelog.mdx
@@ -4,6 +4,13 @@ description: "New features, improvements, and fixes across the Sendmux platform.
rss: true
---
+
+ ## Sending API
+
+Binary attachment uploads now require the exact `Content-Length` header in the OpenAPI spec, Postman collection, SDKs, CLI, and MCP guidance. Sendmux file helpers calculate it from local files, so agents can upload attachments without placing file bytes in prompts.
+
+
+
## Sending API
diff --git a/guides/attachments.mdx b/guides/attachments.mdx
index da1b6ba..81cc44f 100644
--- a/guides/attachments.mdx
+++ b/guides/attachments.mdx
@@ -4,7 +4,7 @@ description: "Send, upload, and download attachments with Sendmux."
keywords: ["attachments", "file uploads", "file downloads", "base64", "MIME types", "size limits"]
---
-For the Sending API, upload file bytes first and send by `attachment_id`. Inline base64 attachments remain supported for small generated content and older integrations, but uploaded refs are the preferred path for normal files.
+For the Sending API, upload file bytes first and send by `attachment_id`. Inline base64 attachments remain supported for small generated content and older integrations, but uploaded refs are the preferred path for normal files. Direct and delegated binary uploads require the exact `Content-Length`; Sendmux SDK and CLI file helpers calculate it from the local file.
## Limits
@@ -66,7 +66,7 @@ curl -X POST https://smtp.sendmux.ai/api/v1/emails/attachment-uploads \
}"
```
-The response includes an `upload_url` and required `headers`. Send a `PUT` request to that URL with the exact file bytes and returned headers. The upload token can write only that attachment, expires quickly, and does not grant send access.
+The response includes an `upload_url` and required `headers`, including `Content-Type` and exact `Content-Length`. Send a `PUT` request to that URL with the exact file bytes and returned headers. The upload token can write only that attachment, expires quickly, and does not grant send access.
## Agent and MCP workflows
diff --git a/openapi-sending.json b/openapi-sending.json
index 758c042..fa2138b 100644
--- a/openapi-sending.json
+++ b/openapi-sending.json
@@ -818,6 +818,18 @@
"type": "string"
}
},
+ {
+ "description": "Exact number of bytes in the binary request body.",
+ "example": 20480,
+ "in": "header",
+ "name": "Content-Length",
+ "required": true,
+ "schema": {
+ "format": "int64",
+ "minimum": 1,
+ "type": "integer"
+ }
+ },
{
"description": "Upload intent ID returned by POST /emails/attachment-uploads.",
"in": "path",
@@ -953,6 +965,18 @@
"type": "string"
}
},
+ {
+ "description": "Exact number of bytes in the binary request body.",
+ "example": 20480,
+ "in": "header",
+ "name": "Content-Length",
+ "required": true,
+ "schema": {
+ "format": "int64",
+ "minimum": 1,
+ "type": "integer"
+ }
+ },
{
"description": "Filename to associate with the uploaded attachment.",
"example": "analysis.pdf",
diff --git a/postman/sendmux-sending.postman_collection.json b/postman/sendmux-sending.postman_collection.json
index 3b68210..969d2f0 100644
--- a/postman/sendmux-sending.postman_collection.json
+++ b/postman/sendmux-sending.postman_collection.json
@@ -233,6 +233,12 @@
"key": "X-Sendmux-Upload-Token",
"value": ""
},
+ {
+ "description": "(Required) Exact number of bytes in the binary request body.",
+ "disabled": false,
+ "key": "Content-Length",
+ "value": ""
+ },
{
"key": "Content-Type",
"value": "application/octet-stream"
@@ -408,6 +414,12 @@
"key": "Idempotency-Key",
"value": ""
},
+ {
+ "description": "(Required) Exact number of bytes in the binary request body.",
+ "disabled": false,
+ "key": "Content-Length",
+ "value": ""
+ },
{
"key": "Content-Type",
"value": "application/octet-stream"
diff --git a/sending-api/introduction.mdx b/sending-api/introduction.mdx
index f8c8a7d..e57332e 100644
--- a/sending-api/introduction.mdx
+++ b/sending-api/introduction.mdx
@@ -140,7 +140,7 @@ Single-resource `GET` responses return a weak `ETag`. Send it back in an `If-Non
- **Public IDs only**. Private numeric IDs are never exposed.
- **`Cache-Control: no-store`** on all authenticated responses (the OpenAPI spec endpoint uses `public, max-age=3600`)
- JSON endpoints use `Content-Type: application/json`.
-- Binary attachment upload endpoints use `Content-Type` for the file MIME type and send raw bytes with `application/octet-stream` or the file's MIME type.
+- Binary attachment upload endpoints use `Content-Type` for the file MIME type and require the exact `Content-Length` for the raw byte body.
## OpenAPI specification