Skip to content
Docs

How-to

Attach files to API emails as base64 content or from a URL, embed inline images with Content-ID, and stay within allowed file types and size limits.

Updated Oct 1, 2026

This page shows how to attach files to emails you send with POST /emails, either as base64-encoded content or by letting Emailit download them from a URL. It also covers inline images, allowed file types and size limits.

Attachment fields

Pass an attachments array. Each item is an object with these fields:

filenamestringrequired
File name shown to the recipient. It must end in an allowed extension.
contentstring
The file encoded as base64. Use either content or url, not both.
urlstring
An http:// or https:// URL that Emailit downloads the file from. Use either content or url, not both.
content_typestring
The MIME type, such as application/pdf. Required with content. With url, it defaults to the Content-Type the server returns.
content_idstring
A Content-ID. Setting it makes the attachment inline, so your HTML can show it with cid:.
encodingstringdefault: base64
How content is encoded. Leave it as base64 unless you have a reason to change it.

Attach a file as base64

Read the file, encode it as base64, and send it with its MIME type.

Terminal
curl https://api.emailit.com/v2/emails \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"from\": \"Acme Billing <billing@acme.com>\",
    \"to\": \"ada@example.com\",
    \"subject\": \"Invoice INV-1042\",
    \"text\": \"Your invoice is attached.\",
    \"attachments\": [{
      \"filename\": \"INV-1042.pdf\",
      \"content\": \"$(base64 < INV-1042.pdf | tr -d '\n')\",
      \"content_type\": \"application/pdf\"
    }]
  }"

Attach a file from a URL

Instead of encoding the file yourself, give Emailit a url. Emailit downloads the file while it builds the message, so the request takes as long as the download.

JSON
{
  "from": "Acme Billing <billing@acme.com>",
  "to": "ada@example.com",
  "subject": "Invoice INV-1042",
  "text": "Your invoice is attached.",
  "attachments": [
    {
      "filename": "INV-1042.pdf",
      "url": "https://files.acme.com/invoices/INV-1042.pdf"
    }
  ]
}

The URL has to meet these rules, or the request fails with 422 and Attachment error:

  • It uses http or https and points to a public host. Private and internal addresses are refused.
  • It returns the file directly with a 2xx status. Redirects aren’t followed.
  • The download finishes within 30 seconds.
  • The file is no larger than 25 MB, as reported by its Content-Length header.

Emailit builds a separate copy of the message for each recipient and downloads URL attachments for each copy. Make sure signed or expiring URLs stay valid for the whole request, and that the file host can handle one download per recipient.

Embed inline images

To show an image inside the HTML body instead of as a separate attachment, give it a content_id and reference that ID with cid: in an img tag.

JSON
{
  "from": "Acme <hello@acme.com>",
  "to": "ada@example.com",
  "subject": "Your weekly report",
  "html": "<p><img src=\"cid:chart-week-40\" alt=\"Weekly signups\" width=\"600\"></p>",
  "attachments": [
    {
      "filename": "chart.png",
      "content": "iVBORw0KGgoAAAANSUhEUgAA...",
      "content_type": "image/png",
      "content_id": "chart-week-40"
    }
  ]
}

The content_id in the attachment and the value after cid: must match exactly. Inline images make the message larger for every recipient, so for logos and other shared images, a hosted image URL in the HTML is usually the better choice.

Size limits

Limit Value
Whole message, after encoding 40 MB. Larger messages fail with 413 Message too large.
One attachment downloaded from url 25 MB
Download timeout for url 30 seconds
JSON request body 50 MB

Base64 encoding makes files about a third larger, and the 40 MB limit applies to the encoded message. In practice, keep the combined size of your files under about 29 MB. For anything bigger, upload the file to your own storage and send a link.

Allowed file types

filename must end in one of these extensions. Any other extension, or a name without an extension, fails validation with 400.

Category Extensions
Text .txt, .csv, .log, .css, .ics, .xml
Images .jpg, .jpe, .jpeg, .gif, .png, .bmp, .psd, .tif, .tiff, .svg, .indd, .ai, .eps
Documents .doc, .docx, .rtf, .odt, .ott, .pdf, .pub, .pages, .mobi, .epub
Audio .mp3, .m4a, .m4v, .wma, .ogg, .flac, .wav, .aif, .aifc, .aiff
Video .mp4, .mov, .avi, .mkv, .mpeg, .mpg, .wmv
Spreadsheets .xls, .xlsx, .ods, .numbers
Presentations .odp, .ppt, .pptx, .pps, .key
Archives and contacts .zip, .vcf
Email .eml
Signatures and encryption .p7c, .p7m, .p7s, .pgp, .asc, .sig

Executable files and scripts aren’t on the list and can’t be attached.

Read the attachments of a sent email

List attachments (GET /emails/{id}/attachments) returns each attachment with its filename, content_type, size, content_id, content_disposition (attachment or inline) and base64 content. It needs a Full Access key. Attachments are deleted together with the message contents when your data retention period ends.

Troubleshooting

Error What to check
Attachment at index 0 missing content_type (required when using 'content') Add content_type to every base64 attachment.
Attachment 'report.exe' has unsupported file type '.exe' Use an allowed extension, or put the file in a .zip.
Attachment at index 0 cannot have both 'content' and 'url' Send one of the two.
Attachment error with Failed to fetch attachment The URL returned an error status, redirected, timed out or isn’t public. Open it from a server outside your network to check.
Attachment error with Attachment too large (max 25MB) Host the file and send a link instead.
413 Message too large Reduce the total size of attachments.

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.