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

# Attachments

> Send files with your emails: inline as base64, uploaded once with the Files API, or embedded images.

You can attach files to an email in three ways. Pick the one that matches how often you send the file.

| Source | When to use it |
| - | - |
| `content` (base64) in the JSON body | A file generated for one email, such as an invoice you just rendered. |
| `file_id` from the Files API | A file you send again and again, such as your terms or a fixed brochure. |
| `inline[content_id]` (multipart) | An image shown inside the HTML with `cid:`, such as a logo. |

## Attach a file inline

Send the file encoded in base64 with its `filename`. The `filename` must include an extension, and the content must match it: a file named `receipt.pdf` must actually be a PDF.

```bash theme={"dark"}
curl https://pulse-send.jiordiviera.me/api/v1/emails \
  -H "Authorization: Bearer $PULSESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <billing@acme.com>",
    "to": ["client@example.com"],
    "subject": "Your receipt",
    "html": "<p>Thanks for your order. The receipt is attached.</p>",
    "attachments": [
      {
        "filename": "receipt-8812.pdf",
        "content": "JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoK..."
      }
    ]
  }'
```

You can also send a multipart request, with each file in an `attachments[]` field. Use the same `filename` rules.

```bash theme={"dark"}
curl https://pulse-send.jiordiviera.me/api/v1/emails \
  -H "Authorization: Bearer $PULSESEND_API_KEY" \
  -F "from=Acme <billing@acme.com>" \
  -F "to[]=client@example.com" \
  -F "subject=Your receipt" \
  -F "html=<p>The receipt is attached.</p>" \
  -F "attachments[]=@receipt-8812.pdf"
```

## Reuse a file with the Files API

Upload a file once, then reference it by its `file_id` in as many emails as you like.

```bash theme={"dark"}
curl https://pulse-send.jiordiviera.me/api/v1/files \
  -H "Authorization: Bearer $PULSESEND_API_KEY" \
  -F "file=@terms-2026.pdf"
```

The response includes an `id` starting with `file_`. Use it in `attachments`:

```json theme={"dark"}
{
    "attachments": [{ "file_id": "file_01J..." }]
}
```

Uploading the same content again returns the existing file, so it is safe to upload before each send. `GET /api/v1/files` lists your files and `GET /api/v1/files/{id}` returns one of them.

## Embed an image inline

To show an image inside the HTML, give it a `content_id` and point the `src` at `cid:` followed by that id. In multipart, send the file in `inline[<content_id>]`.

```bash theme={"dark"}
curl https://pulse-send.jiordiviera.me/api/v1/emails \
  -H "Authorization: Bearer $PULSESEND_API_KEY" \
  -F "from=Acme <hello@acme.com>" \
  -F "to[]=client@example.com" \
  -F "subject=Welcome" \
  -F 'html=<img src="cid:logo" alt="Acme"><p>Welcome aboard.</p>' \
  -F "inline[logo]=@logo.png"
```

Each `content_id` must be unique within the email.

## Limits

| Limit | Value |
| - | - |
| Attachments per email | 20 |
| Total size of the message (subject, body, headers and attachments) | 25 MB |
| Size included in the price of one email | 1 MB. Beyond that, 1 credit per recipient for each MB started. |
| Files kept in your library | 100 MB on the free plan, 1 GB on paid plans |

File types that mail providers block are refused with `attachment_type_not_allowed`. This covers executables and scripts, such as `.exe`, `.bat`, `.js`, `.vbs`, `.ps1`, `.msi` and `.mdb`. For these, zip the file or share a link instead.

For formats with a known signature (PDF, PNG, JPEG, GIF, WebP, ZIP, DOCX, XLSX, PPTX, ODT, ODS), the content must match the extension. Otherwise the request fails with `attachment_content_mismatch`.

## Storage and retention

By default, PulseSend keeps a copy of each attachment so you can download it from the dashboard or the API. Set `store` to `false` to delete the bytes as soon as the email is handed to the provider. The email keeps the file name, type and size.

Stored attachments follow the same retention as the email content: they are deleted after 30 days, and the name, type and size remain.

## Download an attachment

```bash theme={"dark"}
curl https://pulse-send.jiordiviera.me/api/v1/emails/em_01J.../attachments \
  -H "Authorization: Bearer $PULSESEND_API_KEY"
```

Each attachment comes with a `download_url`, valid for 5 minutes. Request the list again when you need a fresh link.

## Errors

| Code | What to do |
| - | - |
| `attachment_content_mismatch` | The content does not match the extension. Check that you sent the right file, encoded once in base64. |
| `attachment_type_not_allowed` | The file type is blocked by mail providers. Zip it or share a link. |
| `resource_missing` | The `file_id` does not exist in your team. |
| `invalid_parameter` | Check the field named in `param`: a filename without extension, a duplicate `content_id`, more than 20 attachments, and so on. |
| `message_too_large` | The whole message is over 25 MB. Send a link to the file instead. |


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