Sending Emails
Sending Emails
Postscale makes it easy to send transactional emails with high deliverability. This guide covers all the options available when sending emails.
Basic Send
The simplest way to send an email:
await postscale.emails.send({
from: 'notifications@yourapp.com',
to: ['user@example.com'],
subject: 'Your order has shipped',
html_body: '<p>Your order #12345 is on its way!</p>'
});
Multiple Recipients
Send to multiple recipients at once:
await postscale.emails.send({
from: 'newsletter@yourapp.com',
to: ['user1@example.com', 'user2@example.com'],
subject: 'Weekly Update',
html_body: '<p>Here is your weekly digest...</p>'
});
Plain Text Fallback
Always include a plain text version alongside HTML for maximum deliverability. Some email clients and spam filters prefer plain text, and it's required by certain providers.
await postscale.emails.send({
from: 'notifications@yourapp.com',
to: ['user@example.com'],
subject: 'Your order has shipped',
html_body: '<p>Your order #12345 is on its way!</p>',
text_body: 'Your order #12345 is on its way!'
});
Attachments
Include file attachments by providing base64-encoded content, a filename, and the MIME content type:
import { readFileSync } from 'fs';
await postscale.emails.send({
from: 'invoices@yourapp.com',
to: ['customer@example.com'],
subject: 'Invoice #1234',
html_body: '<p>Please find your invoice attached.</p>',
text_body: 'Please find your invoice attached.',
attachments: [
{
filename: 'invoice-1234.pdf',
content: readFileSync('./invoice-1234.pdf').toString('base64'),
content_type: 'application/pdf'
},
{
filename: 'receipt.png',
content: readFileSync('./receipt.png').toString('base64'),
content_type: 'image/png'
}
]
});
Total message size (including attachments) must not exceed 50 MB. Base64 encoding increases file size by approximately 33%.
Sending with Templates
Instead of writing inline HTML, you can reference a saved template by slug or ID and pass variables:
await postscale.emails.send({
from: 'orders@yourapp.com',
to: ['customer@example.com'],
template: 'order-confirmation',
variables: {
first_name: 'Jane',
order_id: '12345',
items: [
{ name: 'Widget', price: '$29.99' },
{ name: 'Gadget', price: '$49.99' },
],
total: '79.98',
currency: '#x27;,
},
});
The template's subject, HTML body, and text body are rendered with your variables using Handlebars syntax ({{variable}}). Built-in variables like {{current_year}} and {{current_date}} are injected automatically.
You can also reference a template by UUID:
await postscale.emails.send({
from: 'orders@yourapp.com',
to: ['customer@example.com'],
template_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
variables: { first_name: 'Jane' },
});
You cannot combine template/template_id with inline subject/html_body/text_body. The API will return a 400 error if you set both.
See Templates for full documentation on creating templates, variable syntax, and the preview API.
Tags and Metadata
Add tags and metadata to organize and track your emails:
await postscale.emails.send({
from: 'notifications@yourapp.com',
to: ['user@example.com'],
subject: 'Welcome aboard!',
html_body: '<p>Welcome to the platform!</p>',
tags: ['welcome', 'onboarding'],
metadata: {
user_id: '12345',
campaign: 'welcome-series'
}
});
Tags and metadata appear in webhook payloads and the dashboard, making it easy to filter and analyze your sending activity.
Response
A successful send returns:
{
"message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890@yourapp.com",
"status": "queued",
"warming_phase": "phase_1",
"remaining_today": 1500,
"remaining_this_hour": 100
}
Use webhooks to track email delivery, opens, and clicks in real-time.