Send with attachments, CC & BCC
Extend the basic send request with additional recipients (cc, bcc), a replyTo address, and file attachments. All fields are part of the same POST /transactional-email payload.
PrerequisiteThis builds on Send your first email (HTTP API). You need a Bearer token and a verified authorized sender.
CC, BCC & Reply-To
to, cc, and bcc are each arrays of address objects (address required, name optional). replyTo is a single address applied when a recipient hits Reply.
curl -X POST 'https://connect.routee.net/transactional-email' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"from": { "name": "Acme Support", "address": "[email protected]" },
"replyTo": { "address": "[email protected]" },
"to": [{ "address": "[email protected]" }],
"cc": [{ "name": "Team", "address": "[email protected]" }],
"bcc": [{ "address": "[email protected]" }],
"subject": "Your invoice is attached",
"content": { "html": "<p>Please find your invoice attached.</p>" }
}'Attachments
attachments is an array of objects. Each attachment needs:
| Field | Description |
|---|---|
content | Base64-encoded file content |
type | MIME type, e.g. application/pdf |
filename | Display name (max 128 chars) |
Base64-encode the file, then include it in the request. A quick way to encode on the CLI:
base64 -i invoice.pdf | tr -d '\n'Full example — attachment + CC/BCC
import base64, requests
with open("invoice.pdf", "rb") as f:
encoded = base64.b64encode(f.read()).decode()
payload = {
"from": {"name": "Acme Support", "address": "[email protected]"},
"replyTo": {"address": "[email protected]"},
"to": [{"name": "Jane Customer", "address": "[email protected]"}],
"cc": [{"address": "[email protected]"}],
"bcc": [{"address": "[email protected]"}],
"subject": "Your invoice is attached",
"content": {
"html": "<p>Please find your invoice attached.</p>",
"text": "Please find your invoice attached.",
},
"attachments": [
{
"content": encoded,
"type": "application/pdf",
"filename": "invoice.pdf",
}
],
}
resp = requests.post(
"https://connect.routee.net/transactional-email",
headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN", "Content-Type": "application/json"},
json=payload,
)
print(resp.status_code, resp.json())import { readFile } from "node:fs/promises";
const encoded = (await readFile("invoice.pdf")).toString("base64");
const res = await fetch("https://connect.routee.net/transactional-email", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
from: { name: "Acme Support", address: "[email protected]" },
replyTo: { address: "[email protected]" },
to: [{ name: "Jane Customer", address: "[email protected]" }],
cc: [{ address: "[email protected]" }],
bcc: [{ address: "[email protected]" }],
subject: "Your invoice is attached",
content: {
html: "<p>Please find your invoice attached.</p>",
text: "Please find your invoice attached.",
},
attachments: [
{ content: encoded, type: "application/pdf", filename: "invoice.pdf" },
],
}),
});
console.log(res.status, await res.json());
Keep messages within size limitsBase64 encoding adds ~33% overhead. Oversized messages are rejected with
400error code000003(message size limit exceeded). For large files, link to a hosted download instead of attaching. See Email Error Codes.
Field reference
Next steps
- Track delivery & receive callbacks
- Full reference: Send a transactional email

