postmark
Reliable transactional email delivery service
$ npx docs2skills add postmark-emailPostmark
Fast, reliable transactional email delivery service with industry-leading deliverability and speed.
What this skill does
Postmark is an email delivery service specifically designed for transactional emails - the one-to-one messages triggered by user actions like password resets, welcome emails, receipts, and notifications. Unlike generic email providers, Postmark separates transactional and promotional traffic using different infrastructures to maintain optimal deliverability rates.
The service provides both REST API and SMTP interfaces, allowing you to send emails through your application with minimal setup while ensuring messages reach the inbox quickly (often under 1 second to Gmail). Postmark handles all the complex infrastructure like IP reputation management, bounce handling, and authentication protocols.
Prerequisites
- Postmark account with verified sender signature or domain
- Server API token from Postmark dashboard
- Node.js 12+ (for JavaScript library) or equivalent runtime for other languages
- Verified email address or domain for sending (required before first send)
Quick start
npm install postmark
const postmark = require("postmark");
const client = new postmark.ServerClient("YOUR-SERVER-TOKEN");
// Send a simple email
client.sendEmail({
"From": "sender@example.com",
"To": "user@example.com",
"Subject": "Welcome to our app",
"TextBody": "Thanks for signing up!",
"MessageStream": "outbound"
});
# Via cURL
curl "https://api.postmarkapp.com/email" \
-X POST \
-H "Content-Type: application/json" \
-H "X-Postmark-Server-Token: YOUR-SERVER-TOKEN" \
-d '{"From":"sender@example.com","To":"user@example.com","Subject":"Test","TextBody":"Hello"}'
Core concepts
Servers - Organizational units that group your email sending. Each server has its own API token and settings. Use separate servers for different environments (dev/staging/prod) or clients.
Message Streams - Route different email types through optimized infrastructure. Transactional streams handle user-triggered emails while Broadcast streams handle bulk messages like newsletters.
Sender Signatures vs Domain Verification - Verify individual email addresses with signatures, or verify entire domains to send from any address on that domain.
Templates - Reusable email layouts with variable substitution using Mustachio templating engine. Store templates in Postmark and send by template ID with dynamic data.
Key API surface
// Core sending methods
client.sendEmail(message) // Send single email
client.sendEmailBatch(messages) // Send up to 500 emails
client.sendEmailWithTemplate(templateModel) // Send using template
// Template management
client.createTemplate(template) // Create new template
client.editTemplate(templateId, updates) // Update existing template
client.getTemplate(templateId) // Get template details
// Message tracking
client.getOutboundMessages(filters) // Get sent message history
client.getMessageDetails(messageId) // Get specific message details
// Bounce management
client.getBounces(filters) // Get bounce reports
client.activateBounce(bounceId) // Reactivate bounced email
// Server configuration
client.getServer() // Get server details
client.editServer(updates) // Update server settings
Common patterns
Password reset emails:
client.sendEmailWithTemplate({
"TemplateId": 123456,
"To": "user@example.com",
"From": "noreply@yourapp.com",
"TemplateModel": {
"user_name": "John",
"reset_url": "https://yourapp.com/reset?token=abc123",
"company_name": "Your App"
}
});
Batch welcome emails:
const welcomeEmails = users.map(user => ({
"From": "welcome@yourapp.com",
"To": user.email,
"Subject": `Welcome ${user.name}!`,
"HtmlBody": `<h1>Hi ${user.name}</h1><p>Welcome to our platform!</p>`,
"MessageStream": "outbound",
"TrackOpens": true
}));
client.sendEmailBatch(welcomeEmails);
Notification with metadata:
client.sendEmail({
"From": "notify@yourapp.com",
"To": "user@example.com",
"Subject": "New comment on your post",
"HtmlBody": "Someone commented on your post...",
"Tag": "comment-notification",
"Metadata": {
"post_id": "123",
"user_id": "456"
},
"TrackOpens": true
});
SMTP configuration (Rails):
# config/application.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.postmarkapp.com',
port: 587,
user_name: 'YOUR-SERVER-TOKEN',
password: 'YOUR-SERVER-TOKEN',
authentication: :plain,
enable_starttls_auto: true
}
Configuration
Environment variables:
POSTMARK_SERVER_TOKEN=your-server-token-here
POSTMARK_ACCOUNT_TOKEN=your-account-token-here # For account-level operations
Client configuration:
const client = new postmark.ServerClient("server-token", {
requestHost: "api.postmarkapp.com", // Default host
timeout: 180 // Request timeout in seconds
});
const accountClient = new postmark.AccountClient("account-token");
Message Stream selection:
// For transactional emails (default)
"MessageStream": "outbound"
// For broadcast/bulk emails
"MessageStream": "broadcasts"
Best practices
- Separate transactional and broadcast: Use different Message Streams to prevent bulk email from affecting transactional deliverability
- Verify domains, not just signatures: Domain verification allows sending from any address on your domain without individual confirmations
- Use templates for repeated emails: Store password resets, welcome emails, etc. as templates rather than inline HTML
- Add metadata for tracking: Include user IDs, order numbers, or other identifiers in metadata for easier message lookup
- Enable open/click tracking selectively: Only track opens for emails where engagement data is useful
- Use tags for categorization: Tag emails by type (welcome, notification, receipt) for better analytics
- Handle bounces proactively: Set up bounce webhooks and automatically suppress hard-bounced addresses
- Test in sandbox mode: Use sandbox for integration testing without sending real emails
- Batch when possible: Use sendEmailBatch for multiple emails to the same recipients for better performance
For detailed bounce handling, read the api-reference.md file in this skill directory.
For webhook setup and event processing, read the webhooks-guide.md file in this skill directory.
Gotchas and common mistakes
- Message Stream required: All API calls must include MessageStream parameter or will default to "outbound"
- 50 recipient limit: Maximum 50 total recipients (To + CC + BCC) per email, each recipient counts as one email
- 10MB size limit: Total email size including attachments cannot exceed 10MB
- Sender must be verified: Cannot send from unverified email addresses or domains - verification required before first send
- Template variables are case-sensitive: {{User_Name}} ≠ {{user_name}} in template substitution
- Bounce webhook timing: Bounces may arrive minutes to hours after sending, not immediately
- SMTP vs API feature gaps: SMTP doesn't support templates, batch sending, or full response codes
- Sandbox emails aren't delivered: Emails sent in sandbox mode are processed but never actually delivered
- Server tokens are server-specific: Each server has its own token - using wrong token fails silently in some libraries
- Metadata values must be strings: Numeric or boolean metadata values must be converted to strings
- Click tracking modifies URLs: Link tracking rewrites URLs, may break some complex query parameters
- Webhook endpoint must be HTTPS: Postmark only delivers webhooks to secure endpoints
- Rate limits apply: API has rate limits (300 requests/minute for sending), batch requests count as one
- Suppression list affects all streams: Bounced/complained addresses are suppressed across all Message Streams on the server
- Template inheritance: Layout templates cascade to child templates, changes affect all dependent templates
For template creation and management details, read the templates-and-layouts.md file in this skill directory.
For Message Stream configuration and best practices, read the message-streams-setup.md file in this skill directory.