Skip to content

Sending with attachments

You can attach files when sending with a template API or sending without a template API by adding an array of attachment objects to the attachments property of the API call. Each object includes:

PropertyDescription
nameThe filename shown to the receiver. eg. invoice-352.pdf
contentBlobBase64-encoded string of the file content. Most languages have built-in tools for this (Ruby, .NET, Java, PHP).
attachmentIdWaypoint Attachment ID when attaching large files.
contentTypeMIME Type for the file attachment. eg. application/pdf
cidA Content ID turns the attachment into an inline attachment. The CID is the reference used to embed it in the email body.

Standard attachments are files sent alongside an email — not embedded in the body. PDFs and spreadsheets are typical examples; recipients have to open or download them separately.

To attach files, add an attachments array to your API call.

Emails using standard attachments must stay under 5 MB total (including the email body). See how to attach larger files.

const fs = require('fs');
// Read and encode the file to base64
const filePath = './order-receipt.pdf';
const fileContent = fs.readFileSync(filePath);
const base64Content = fileContent.toString('base64');
// Send the email with attachment
const authHeader =
'Basic ' + Buffer.from(`${API_KEY_USERNAME}:${API_KEY_PASSWORD}`).toString('base64');
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: authHeader,
},
body: JSON.stringify({
templateId: 'wptemplate_ABc123XYZ',
to: 'jordan@usewaypoint.com',
variables: {
user: {
displayName: 'Jordan',
},
product: {
title: 'Beechers Mac & Cheese',
id: '02934203942',
},
},
attachments: [
{
name: 'order-receipt.pdf',
contentBlob: base64Content,
contentType: 'application/pdf',
},
],
}),
};
fetch('https://live.waypointapi.com/v1/email_messages', options)
.then((res) => res.json())
.then((res) => console.log(res))
.catch((err) => console.error(err));

The 5 MB cap on standard attachments can be tight for files like custom reports, presentations, detailed invoices, or other high-quality assets.

For files over 5 MB, use the large attachment flow below instead. Growth plans support up to 10 MB, Pro plans up to 20 MB.

How it works:

  1. POST to v1/attachments API to create an attachment record. The response includes an uploadUrl and an id.
  2. PUT your file to the uploadUrl.
  3. POST to v1/email_messages API to send your email, referencing the id in the attachments array.

See the code example below.

import fs from 'fs';
// File to upload
const FILE_PATH = './reports/report-00000001.pdf';
async function executeUpload() {
const file = fs.createReadStream(FILE_PATH);
const stats = fs.statSync(FILE_PATH);
const authHeader =
'Basic ' + Buffer.from(`${API_KEY_USERNAME}:${API_KEY_PASSWORD}`).toString('base64');
// Create attachment URL
const createRes = await fetch('https://live.waypointapi.com/v1/attachments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: authHeader,
},
});
const createJson = await createRes.json();
const presignedUrl = createJson.data.uploadUrl;
const attachmentId = createJson.data.id;
console.log('Attachment created:', { attachmentId, presignedUrl });
// Upload file to the upload URL with file content type and file size
await fetch(presignedUrl, {
method: 'PUT',
headers: {
'Content-Type': 'application/pdf',
'Content-Length': stats.size.toString(),
Authorization: authHeader,
},
body: file,
duplex: 'half',
});
// Send email with attachment ID, name, and file content type
const emailMessageRes = await fetch('https://live.waypointapi.com/v1/email_messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: authHeader,
},
body: JSON.stringify({
to: 'jordan@usewaypoint.com',
from: 'support@usewaypoint.com',
bodyHtml: '<p>Your report is attached.</p>',
subject: 'Your Report',
attachments: [
{
attachmentId: attachmentId,
name: 'report-00000001.pdf',
contentType: 'application/pdf',
},
],
}),
});
const emailData = await emailMessageRes.json();
console.log('Email message created:', emailData);
}
executeUpload();

Large attachments require a Growth or Pro plan.

File size limits by plan:

  • Free and Starter: Unavailable
  • Growth: 10 MB
  • Pro: 20 MB

Inline attachments, usually images, are embedded directly in the email body so they render as part of the message.

The setup is the same as a standard attachment, with one addition: each attachment includes a cid (Content-ID), which you reference from the bodyHtml to embed it.

In the example below, note "cid": "emoji" referenced by <img src=\"cid:emoji\" />.

const authHeader =
'Basic ' + Buffer.from(`${API_KEY_USERNAME}:${API_KEY_PASSWORD}`).toString('base64');
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: authHeader,
},
body: JSON.stringify({
to: 'Jordan Tester <jordan@usewaypoint.com>',
from: 'Waypoint Support <support@usewaypoint.com>',
bodyHtml: '<h1>Hello from Waypoint <img src="cid:emoji" /></h1>',
subject: 'Hello from Waypoint',
attachments: [
{
name: 'emoji.png',
cid: 'emoji',
contentType: 'image/png',
contentBlob: 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=',
},
],
}),
});

On a message log in your Activity, any attachments on that send show up as filenames beneath the message preview.

Logs only show filenames (even for inline attachments) — Waypoint doesn’t store the file contents.

Waypoint Attachment

  • Total message size is capped per plan: 2 MB on Free and Starter, 5 MB on Growth and Pro, including attachments.
  • Attachments aren’t currently supported for batch sending.
  • The following file extensions aren’t supported and will block the email from being sent: .ade, .adp, .app, .asp, .bas, .bat, .cer, .chm, .cmd, .com, .cpl, .crt, .csh, .der, .exe, .fxp, .gadget, .hlp, .hta, .inf, .ins, .isp, .its, .js, .jse, .ksh, .lib, .lnk, .mad, .maf, .mag, .mam, .maq, .mar, .mas, .mat, .mau, .mav, .maw, .mda, .mdb, .mde, .mdt, .mdw, .mdz, .msc, .msh, .msh1, .msh2, .mshxml, .msh1xml, .msh2xml, .msi, .msp, .mst, .ops, .pcd, .pif, .plg, .prf, .prg, .reg, .scf, .scr, .sct, .shb, .shs, .sys, .ps1, .ps1xml, .ps2, .ps2xml, .psc1, .psc2, .tmp, .url, .vb, .vbe, .vbs, .vps, .vsmacros, .vss, .vst, .vsw, .vxd, .ws, .wsc, .wsf, .wsh, .xnk.