Attachments · MachineMail Docs

Send an attachment

Add an attachments array to a send, reply, reply-all or forward. Each attachment has either content (base64) or url.

A message can carry at most 100 attachments and 10 MB of files in total (decoded), whether they come from content or url; a request body is at most 16 MB. Larger mail is refused with a 400 validation error before anything is sent: link to big files instead. content must be valid base64 (standard or URL-safe alphabet, padding and line breaks optional); anything else is a 400 whose param names it, for example attachments[0].content. Filenames can use any characters, including non-Latin scripts.

Field Meaning
filename File name shown to the recipient. With url, defaults to the last path segment.
content_type MIME type. With url, defaults to the response’s Content-Type.
content The file, base64 encoded.
url A public http or https URL that MachineMail downloads when it sends.
content_disposition attachment (default) or inline.
content_id For inline images: the ID your HTML refers to as cid:<content_id>.

Example Code

curl

curl https://api.machinemail.dev/v0/inboxes/support-agent@machinemail.dev/messages/send \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{\n    "to": ["ada@example.com"],\n    "subject": "Your report",\n    "text": "Report attached.",\n    "attachments": [\
      { "filename": "report.csv", "content_type": "text/csv", "content": "ZGF0ZSx0b3RhbAoyMDI2LTEwLTA4LDQy" },\
      { "url": "https://files.acme.dev/q3-summary.pdf" }\
    ]\n  }'

TypeScript

import { readFile } from 'node:fs/promises';

const content = (await readFile('report.csv')).toString('base64');
await fetch('https://api.machinemail.dev/v0/inboxes/support-agent@machinemail.dev/messages/send', {
  method: 'POST',
  headers: { Authorization: `Bearer \\$MACHINEMAIL_API_KEY`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    to: ['ada@example.com'],
    subject: 'Your report',
    text: 'Report attached.',
    attachments: [{ filename: 'report.csv', content_type: 'text/csv', content }],
  }),
});

Python

import base64, os, requests

with open("report.csv", "rb") as f:
    content = base64.b64encode(f.read()).decode()

requests.post(
    "https://api.machinemail.dev/v0/inboxes/support-agent@machinemail.dev/messages/send",
    headers={"Authorization": f"Bearer {os.environ['MACHINEMAIL_API_KEY']}"},
    json={
        "to": ["ada@example.com"],
        "subject": "Your report",
        "text": "Report attached.",
        "attachments": [{"filename": "report.csv", "content_type": "text/csv", "content": content}],
    },
).raise_for_status()

Attachments from a URL

With url, MachineMail fetches the file at send time. The rules:

Inline images

Give the image a content_id, set content_disposition to inline, and refer to it from the HTML body. The content_id is what makes it inline: an image with content_disposition: inline but no content_id is delivered as an ordinary attachment.

Drafts

Drafts take the same attachments as a send, base64 content or url. A url is fetched when the draft is sent (for a scheduled draft, at send_at), so its size is 0 until then and a URL that has stopped working makes the send fail.

Forwarding

A REST forward does not copy the original message’s attachments. To pass them on, download them and add them to the forward’s attachments.

Download

Get the attachment’s metadata and a download URL:

Example Code

curl https://api.machinemail.dev/v0/inboxes/support-agent@machinemail.dev/messages/msg_01m4fybrc20000ypd31v108d71/attachments/att_01m4fybrc10000qyygf5yv5thv \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response
{
  "attachment_id": "att_01m4fybrc10000qyygf5yv5thv",
  "filename": "invoice.pdf",
  "size": 13,
  "content_type": "application/pdf",
  "content_disposition": "attachment",
  "download_url": "https://...",
  "expires_at": "2026-10-09T10:02:01.949Z"
}

Check the risk first

Before an agent opens a file, read the matching entry in trust.attachments:

[
  {
    "attachment_id": "att_01m4fybrc10000qyygf5yv5thv",
    "filename": "invoice.pdf",
    "content_type": "application/pdf",
    "risk": "low",
    "reasons": []
  }
]

Warning

Never execute or render a high risk attachment, and do not hand any attachment to a tool that can run code. If an agent needs a file’s contents, prefer extracted_text.

Attachments are fetched per message.

There is no thread-level attachment download endpoint; use the message that carries the file.