> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wazobiamail.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Attachments

> Send a message and files together using multipart form data.

# Send email with attachments

Use `POST /sending/messages/with-attachments` with your API key as `X-API-Key`. The `message` field contains the same JSON message used in [Sending email](/docs/guides/sending). Add each file using a repeated `files` field.

```bash theme={null}
curl -X POST https://app.wazobiamail.com/api/v1/sending/messages/with-attachments \
  -H "X-API-Key: YOUR_API_KEY" \
  -F 'message={"envelopeSender":"hello@mail.example.com","to":["customer@example.com"],"content":{"from":"Example Store <hello@mail.example.com>","subject":"Your invoice","textBody":"Your invoice is attached."}}' \
  -F 'files=@invoice.pdf'
```

Replace the sender with an address on your verified domain. Files must be non-empty, and their combined size must not exceed 5 MB. Your account's attachment and sending allowances still apply. A successful response means accepted for sending; review [delivery activity](/docs/guides/tracking) afterward.

## Upload a file separately

The upload endpoint stores one file, up to 10 MB, when attachment storage is configured:

```bash theme={null}
curl -X POST https://app.wazobiamail.com/api/v1/sending/attachments/upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"
```

The response returns `data.file` with `key`, `fileName`, `contentType`, `sizeBytes` and `publicUrl`. A separate upload does not send an email. To attach a file to a message, use the multipart sending example above.

## Include multiple files

Repeat `files` for every attachment. Paths refer to files on the machine running your request. The message can contain plain text, HTML or both.

```bash theme={null}
curl -X POST https://app.wazobiamail.com/api/v1/sending/messages/with-attachments \
  -H "X-API-Key: $WAZOBIA_API_KEY" \
  -F 'message={"envelopeSender":"hello@mail.example.com","to":["customer@example.com"],"content":{"from":"Example Store <hello@mail.example.com>","replyTo":"noreply@mail.example.com","subject":"Your documents","textBody":"Your invoice and delivery note are attached."}}' \
  -F 'files=@./invoice.pdf;type=application/pdf' \
  -F 'files=@./delivery-note.txt;type=text/plain'
```

## Node.js: send local files

Node.js 22+ provides `fetch`, `FormData` and `Blob`. Run this on your server, with your sending key in the `WAZOBIA_API_KEY` environment variable.

```javascript theme={null}
import { readFile } from 'node:fs/promises';

const key = process.env.WAZOBIA_API_KEY;
if (!key) throw new Error('Set WAZOBIA_API_KEY');
const form = new FormData();
form.append('message', JSON.stringify({
  envelopeSender: 'hello@mail.example.com',
  to: ['customer@example.com'],
  content: {
    from: 'Example Store <hello@mail.example.com>',
    replyTo: 'noreply@mail.example.com',
    subject: 'Your documents',
    textBody: 'Your invoice and delivery note are attached.',
  },
}));
form.append('files', new Blob([await readFile('./invoice.pdf')], {
  type: 'application/pdf',
}), 'invoice.pdf');
form.append('files', new Blob([await readFile('./delivery-note.txt')], {
  type: 'text/plain',
}), 'delivery-note.txt');

const response = await fetch(
  'https://app.wazobiamail.com/api/v1/sending/messages/with-attachments',
  { method: 'POST', headers: { 'X-API-Key': key }, body: form },
);
const result = await response.json();
if (!response.ok || result.success !== true) {
  throw new Error(result.message || 'Send failed');
}
console.log(result);
```

Let `fetch` set the multipart `Content-Type` and boundary. Setting `Content-Type: application/json` or a boundary manually will break file uploads. The combined 5 MB attachment limit applies to all files together.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.