CarlyEmail docs

Attachments

Files on messages and drafts.

Attachments arrive on inbound mail automatically and can be added to messages and drafts before sending. Maximum 25 MB.

Every message and draft carries an attachments array with the filename, content type and size. Content is fetched separately:

curl "https://api.carlyemail.com/v0/messages/$MESSAGE_ID/attachments/$ATTACHMENT_ID" \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY"

Listing a page of messages names every attachment on every message on that page, so you can decide what to fetch without a round trip per message.

Reading documents through MCP

The get_attachment tool returns extracted_text for PDF and DOCX files alongside the original download_url. Claude and other MCP clients can read this text directly without opening the download link. Pass the message's message_id, the attachment_id from its attachments array, and its inbox_id.

Check text_status, text_truncated, and text_warning before treating the result as complete. Extraction is limited to 10 MB files, 50 PDF pages, 60,000 characters, and eight seconds of parsing. DOCX extraction includes the main document's paragraphs and tables. PDF extraction reads embedded text; images and scanned pages are not transcribed, and password-protected PDFs must be unlocked separately. The download link is still returned when extraction is unsupported, empty, truncated, or fails. REST attachment responses remain download metadata.

Sending a file with a message, a reply, a forward or a draft takes content: the file's bytes, base64 encoded. Padding, line breaks and the URL-safe alphabet are all accepted, as is a data:application/pdf;base64, prefix. Anything that is not base64 comes back as invalid_attachment_content, naming the file.

curl -X POST "https://api.carlyemail.com/v0/inboxes/$INBOX_ID/messages/send" \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"to\": [\"maria@hollowayplumbing.com\"], \"subject\": \"Invoice\",
       \"text\": \"Attached.\",
       \"attachments\": [{\"filename\": \"invoice.pdf\", \"content\": \"$(base64 < invoice.pdf)\"}]}"

A request can be at most 6 MB, and base64 makes a file a third bigger, so content works for files up to about 4 MB. A bigger request is refused with 413 Request Entity Too Large.

Files over 4 MB

Upload the file first, then attach it by its upload_id. This works for any file up to 25 MB.

# 1. Get somewhere to put the file
curl -X POST https://api.carlyemail.com/v0/uploads \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY"
# {"upload_id": "upload_...", "upload_url": "https://...", "expires_at": "...", "max_size": 26214400}

# 2. PUT the file there
curl -T plans.pdf "$UPLOAD_URL"

# 3. Attach it wherever an attachment goes
curl -X POST "https://api.carlyemail.com/v0/inboxes/$INBOX_ID/messages/send" \
  -H "Authorization: Bearer $CARLYEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": ["maria@hollowayplumbing.com"], "subject": "Plans", "text": "Attached.",
       "attachments": [{"filename": "plans.pdf", "upload_id": "upload_..."}]}'

The upload_url works for an hour. An uploaded file can be attached as many times as you like for a day, and is then deleted. Messages and drafts keep their own copy, so deleting the upload never removes an attachment.

The MCP tools take upload_id in the same place.