The official TrackPost Node.js SDK provides a type-safe, promise-based interface for sending emails and managing your account.
Table of Contents
Installation
npm
npm install trackpost
yarn
yarn add trackpost
pnpm
pnpm add trackpost
Quick Start
import { TrackPostClient } from 'trackpost';
const client = new TrackPostClient({
apiKey: 'tp_live_your_api_key'
});
async function sendWelcomeEmail() {
const response = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Welcome!',
html: '<h1>Welcome to our app!</h1>'
});
console.log('Email sent:', response.id);
}
sendWelcomeEmail();
Configuration
Basic Configuration
const client = new TrackPostClient({
apiKey: 'tp_live_your_api_key',
baseURL: 'https://api.trackpost.de/v1', // optional
timeout: 30000, // 30 seconds (optional)
retries: 3 // number of retries on failure (optional)
});
Environment Variables
// .env
TRACKPOST_API_KEY=tp_live_your_api_key
// client.ts
const client = new TrackPostClient({
apiKey: process.env.TRACKPOST_API_KEY!
});
Sending Emails
Basic Email
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Welcome!',
html: '<h1>Welcome!</h1>',
text: 'Welcome!' // optional, auto-generated if not provided
});
console.log(email.id); // msg_abc123
console.log(email.status); // 'sent'
Multiple Recipients
const email = await client.emails.send({
to: ['[email protected]', '[email protected]'],
from: '[email protected]',
subject: 'Team Update',
html: '<h1>Weekly Update</h1>'
});
CC and BCC
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
cc: ['[email protected]'],
bcc: ['[email protected]'],
subject: 'Important Update',
html: '<h1>Update</h1>'
});
Reply-To
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
reply_to: '[email protected]',
subject: 'Your Order',
html: '<h1>Order Confirmation</h1>'
});
Attachments
import * as fs from 'fs';
const pdfBuffer = fs.readFileSync('./invoice.pdf');
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Your Invoice',
html: '<p>Please find your invoice attached.</p>',
attachments: [
{
filename: 'invoice.pdf',
content: pdfBuffer.toString('base64'),
contentType: 'application/pdf'
}
]
});
Using Templates
Send with Template
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
template_id: 'welcome_email',
variables: {
user_name: 'John Doe',
company: 'Acme Inc',
activation_link: 'https://yourapp.com/activate?token=abc123'
}
});
Template with Subject
Templates can include dynamic subjects:
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
template_id: 'order_confirmation',
variables: {
order_id: 'ORD-12345',
total: '$99.99'
}
});
Managing Templates
Create Template
const template = await client.templates.create({
name: 'welcome_email',
subject: 'Welcome to {{company}}, {{user_name}}!',
html: `
<h1>Welcome, {{user_name}}!</h1>
<p>We're excited to have you at {{company}}.</p>
<a href="{{activation_link}}">Activate your account</a>
`,
text: 'Welcome {{user_name}}! Activate your account: {{activation_link}}'
});
console.log(template.id); // tpl_abc123
List Templates
const templates = await client.templates.list();
templates.forEach(template => {
console.log(`${template.id}: ${template.name}`);
});
Get Template
const template = await client.templates.get('tpl_abc123');
console.log(template.html);
Update Template
const template = await client.templates.update('tpl_abc123', {
subject: 'Welcome to {{company}}!',
html: '<h1>Welcome!</h1><p>New content here.</p>'
});
Delete Template
await client.templates.delete('tpl_abc123');
Render Template (Preview)
const preview = await client.templates.render('tpl_abc123', {
user_name: 'Test User',
company: 'Test Company',
activation_link: 'https://example.com/activate'
});
console.log(preview.html);
console.log(preview.text);
console.log(preview.subject);
Managing Emails
List Emails
const emails = await client.emails.list({
limit: 10,
status: 'delivered',
from_date: '2025-01-01',
to_date: '2025-01-31'
});
Get Email
const email = await client.emails.get('msg_abc123');
console.log(email.status);
console.log(email.delivered_at);
Cancel Scheduled Email
await client.emails.cancel('msg_abc123');
Error Handling
Try-Catch Pattern
import { TrackPostError } from 'trackpost';
try {
const email = await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Hello',
html: '<h1>Hi!</h1>'
});
} catch (error) {
if (error instanceof TrackPostError) {
console.log('Status:', error.status); // 400, 401, 429, etc.
console.log('Code:', error.code); // 'rate_limit_exceeded'
console.log('Message:', error.message);
console.log('Request ID:', error.requestId);
}
}
Error Types
| Status | Code | Description |
|---|---|---|
| 400 | validation_error | Invalid request parameters |
| 401 | authentication_error | Invalid API key |
| 403 | authorization_error | Insufficient permissions |
| 404 | not_found | Resource not found |
| 429 | rate_limit_exceeded | Rate limit hit |
| 500 | internal_error | Server error |
Retry Logic
The SDK automatically retries on network errors:
const client = new TrackPostClient({
apiKey: 'tp_live_...',
retries: 3,
retryDelay: 1000 // ms between retries
});
TypeScript Support
Type Definitions
import {
Email,
Template,
SendEmailOptions,
CreateTemplateOptions
} from 'trackpost';
async function sendEmail(options: SendEmailOptions): Promise<Email> {
return await client.emails.send(options);
}
Custom Types
interface User {
email: string;
name: string;
}
async function sendWelcomeEmail(user: User): Promise<void> {
await client.emails.send({
to: user.email,
from: '[email protected]',
template_id: 'welcome',
variables: {
user_name: user.name
}
});
}
Advanced Usage
Rate Limit Handling
import { TrackPostError } from 'trackpost';
async function sendWithRetry(emailData: SendEmailOptions, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await client.emails.send(emailData);
} catch (error) {
if (error instanceof TrackPostError && error.status === 429) {
// Rate limit hit, wait and retry
const delay = Math.pow(2, i) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
Batch Sending
async function sendBatchEmails(users: User[]) {
const batchSize = 10;
for (let i = 0; i < users.length; i += batchSize) {
const batch = users.slice(i, i + batchSize);
await Promise.all(
batch.map(user =>
client.emails.send({
to: user.email,
from: '[email protected]',
template_id: 'welcome',
variables: { user_name: user.name }
}).catch(error => {
console.error(`Failed to send to ${user.email}:`, error);
})
)
);
// Rate limit protection
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
Webhook Verification
import { verifyWebhookSignature } from 'trackpost';
import * as crypto from 'crypto';
app.post('/webhooks/trackpost', (req, res) => {
const signature = req.headers['x-trackpost-signature'];
const payload = req.body;
const isValid = verifyWebhookSignature(
payload,
signature,
process.env.WEBHOOK_SECRET!
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook
console.log('Event:', payload.type);
res.status(200).send('OK');
});
Common Patterns
User Registration Flow
app.post('/register', async (req, res) => {
try {
const user = await createUser(req.body);
// Send welcome email
await client.emails.send({
to: user.email,
from: '[email protected]',
template_id: 'welcome_email',
variables: {
user_name: user.name,
activation_link: generateActivationLink(user)
}
});
res.json({ success: true, user });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Password Reset
app.post('/forgot-password', async (req, res) => {
const user = await findUserByEmail(req.body.email);
if (user) {
const token = generateResetToken(user);
await client.emails.send({
to: user.email,
from: '[email protected]',
template_id: 'password_reset',
variables: {
reset_link: `https://yourapp.com/reset?token=${token}`,
expiry: '1 hour'
}
});
}
// Always return success to prevent email enumeration
res.json({ success: true });
});
Testing
Using Test Keys
// Use test keys in development
const client = new TrackPostClient({
apiKey: process.env.NODE_ENV === 'production'
? process.env.TRACKPOST_LIVE_KEY!
: process.env.TRACKPOST_TEST_KEY!
});
Mocking for Tests
// test/mocks/trackpost.ts
export const mockTrackPostClient = {
emails: {
send: jest.fn().mockResolvedValue({
id: 'msg_test123',
status: 'sent'
})
}
};
// In your test
jest.mock('trackpost', () => ({
TrackPostClient: jest.fn().mockImplementation(() => mockTrackPostClient)
}));
Migration from Other Services
From SendGrid
// SendGrid
await sgMail.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Hello',
html: '<h1>Hi!</h1>'
});
// TrackPost
await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Hello',
html: '<h1>Hi!</h1>'
});
From Nodemailer
// Nodemailer
await transporter.sendMail({
to: '[email protected]',
from: '[email protected]',
subject: 'Hello',
html: '<h1>Hi!</h1>'
});
// TrackPost
await client.emails.send({
to: '[email protected]',
from: '[email protected]',
subject: 'Hello',
html: '<h1>Hi!</h1>'
});
Next Steps
- CLI Tool - Command-line interface
- Templates - Email templating
- Webhooks - Event handling
- API Reference - Full REST API docs