Send with attachments
Three of the four send endpoints accept an attachments[] array —
/send, /send-template, and /send-bulk. Each attachment carries
the file bytes inline as base64; we build the multipart/mixed
MIME structure for you, DKIM-sign it, and ship it to the recipient
through the same pipeline as plain-body emails.
/send-raw always supported attachments because partners build the
MIME themselves — see Send raw for
that path.
Attachment object
Each entry in attachments[] is shaped like this:
{
"filename": "invoice-2026-04.pdf",
"content_type": "application/pdf",
"content_base64": "<base64-encoded file bytes>",
"content_id": "logo-header",
"inline": false
}| Field | Type | Required | Meaning |
|---|---|---|---|
filename | string | yes | Displayed by the recipient’s mail client. Auto-sanitized — directory separators + control chars stripped. |
content_type | string | optional | MIME type (e.g. application/pdf). When omitted, we infer from the filename extension. Falls back to application/octet-stream. |
content_base64 | string | yes | Standard base64 encoding of the file bytes. Not URL-safe base64 — use the standard alphabet. |
content_id | string | optional | Sets Content-ID so HTML can reference the attachment as <img src="cid:logo-header">. Pair with inline: true. |
inline | boolean | optional | When true, sets Content-Disposition: inline (image renders in the body). When false (default), sets attachment (file appears in the recipient’s attachments list). |
Limits
| Cap | Value | What happens when exceeded |
|---|---|---|
| Files per message | 20 | Returns 400 INVALID_ATTACHMENT with "max 20 attachments per message" |
| Total decoded bytes | 10 MiB | Returns 400 INVALID_ATTACHMENT with the bytes-cap message. Sum runs across all attachments — a single 10.1 MiB PDF is rejected just like 11 × 1 MiB files. |
| Filename length | 256 chars | Rejected at validation. |
| Content-Type length | 256 chars | Rejected at validation. |
Blocked file types
Executable + script extensions are refused at the API layer because recipient mail providers (Gmail, Outlook, corporate gateways) block them outright — sending one would cost a wallet deduction for a guaranteed bounce. Blocked extensions:
.exe .bat .cmd .com .scr .msi .vbs .vbe .js .jse
.wsf .wsh .ps1 .dll .jar .app .sh .pl .py .lnk
Workaround: bundle them inside a .zip. ZIPs are allowed.
Example — single PDF
ATT=$(base64 -i invoice.pdf | tr -d '\n')
curl https://apis.splashifypro.com/api/v1/partner/email/send \
-H "Authorization: Bearer pk_live_…" \
-H "Content-Type: application/json" \
-d "{
\"from\": \"billing@yourcompany.com\",
\"to\": [\"customer@example.com\"],
\"subject\": \"Invoice for March\",
\"html_body\": \"<p>Hi! Your invoice for March is attached.</p>\",
\"attachments\": [
{
\"filename\": \"invoice-march-2026.pdf\",
\"content_type\": \"application/pdf\",
\"content_base64\": \"$ATT\"
}
]
}"Example — Node.js (multiple files)
import { readFileSync } from 'node:fs'
const toAtt = (path, contentType) => ({
filename: path.split('/').pop(),
content_type: contentType,
content_base64: readFileSync(path).toString('base64'),
})
const r = await fetch('https://apis.splashifypro.com/api/v1/partner/email/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SPLASHIFY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'billing@yourcompany.com',
to: ['customer@example.com'],
subject: 'Your March documents',
html_body: '<p>Attached: invoice + receipt + signed contract.</p>',
attachments: [
toAtt('./invoice.pdf', 'application/pdf'),
toAtt('./receipt.pdf', 'application/pdf'),
toAtt('./contract.pdf', 'application/pdf'),
],
}),
})
console.log(await r.json())Example — Python
import base64, requests, os
def att(path, ct):
with open(path, 'rb') as f:
return {
'filename': os.path.basename(path),
'content_type': ct,
'content_base64': base64.b64encode(f.read()).decode(),
}
r = requests.post(
'https://apis.splashifypro.com/api/v1/partner/email/send',
headers={'Authorization': f"Bearer {os.environ['SPLASHIFY_API_KEY']}"},
json={
'from': 'support@yourcompany.com',
'to': ['customer@example.com'],
'subject': 'Attached photo',
'html_body': '<p>Here\'s the photo from your visit.</p>',
'attachments': [att('./photo.jpg', 'image/jpeg')],
},
)
print(r.json())Example — Inline image (CID reference)
When you want the image to render inside the email body instead
of as a separate downloadable file, use inline: true + content_id,
then reference it from your HTML with cid::
{
"from": "newsletter@yourcompany.com",
"to": ["customer@example.com"],
"subject": "Today's newsletter",
"html_body": "<p>Welcome!</p><img src=\"cid:hero-banner\" />",
"attachments": [
{
"filename": "banner.png",
"content_type": "image/png",
"content_base64": "iVBORw0KGgo…",
"content_id": "hero-banner",
"inline": true
}
]
}Most modern mail clients (Gmail web + mobile, Outlook, Apple Mail) render inline images correctly. A few hardened corporate gateways strip them — the file falls back to a regular attachment in those.
Errors
| Status | Code | Reason |
|---|---|---|
| 400 | INVALID_ATTACHMENT | Too many files, total size exceeded, blocked extension, invalid base64, or empty content |
| 400 | FROM_NOT_VERIFIED | From-address not on a verified identity (same as plain send) |
| 402 | INSUFFICIENT_BALANCE | Wallet too low to cover the per-recipient send cost |
Pricing
Attachments do not incur a per-byte charge. You’re billed at the per-recipient rate (₹0.01 transactional / your tier rate for marketing) regardless of attachment size. The only practical cost is the 10 MiB total cap which limits how big each individual message can be.
Best practices
- Compress where you can. A PDF with images compressed to 200 dpi vs 600 dpi can be 5× smaller and still look perfect at on-screen resolution. Smaller messages deliver faster + use less of your 10 MiB budget.
- Use links for files > 5 MiB. Recipient mail providers throttle large messages and some flag them as suspicious. For anything bigger, host on object storage and put a download link in the body.
- Set
content_typeexplicitly when you can — saves us a filename-extension guess. The mail client’s “open with” picker uses this header. - Prefer real filenames. Generic
attachment.pdfis allowed but hurts deliverability slightly (Gmail’s spam filter weights template-shaped filenames).invoice-march-2026.pdfis better.
Send-bulk semantics
When you call /send-bulk with attachments[], the same files are
attached to every destination’s email — there’s no per-recipient
attachment override. If you need different attachments per
recipient, call /send-template once per recipient instead.