<!-- Canonical: https://startupmail.dev/docs/attachments -->
<!-- Documentation index: https://startupmail.dev/llms.txt -->

# Attachments

> Upload files before sending and download inbound files with mailbox authorization.

## Upload before sending

Upload each file with the SDK or `POST /v1/attachments`, then include the returned IDs in `attachmentIds` when you send. Pending uploads expire if they are not consumed by a message.

```ts
const file = new Blob([csv], { type: "text/csv" });
const attachment = await mail.uploadAttachment(file, "report.csv");

await mail.sendEmail({
  mailboxId: "mbx_123",
  to: ["customer@example.com"],
  subject: "Requested report",
  text: "Attached is the report you requested.",
  attachmentIds: [attachment.id],
});
```

## Limits

- One attachment can be up to 5 MB.
- One message can reference up to ten attachments.
- Message bodies and attachments together must fit under the configured 10 MB message boundary.
- Filenames are cleaned before storage and download.

## Download a received file

Thread messages include attachment metadata and a download URL. With the SDK, call `mail.downloadAttachment(attachmentId)`. Direct HTTP clients can use `GET /v1/attachments/:id` with a key that has `mail:read` scope.

Downloads check both workspace and mailbox access. An attachment ID cannot be used to read a file from a private mailbox the key cannot access.

> **Treat attachments as untrusted**
>
> Startup Mail validates size and storage boundaries, but your application is responsible for safely
> opening or processing file contents.
