chub-dev 0.1.0 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1168 @@
1
+ ---
2
+ name: transactional-email
3
+ description: "Postmark API coding guidelines for transactional email sending using the official Node.js library"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "4.0.5"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "postmark,email,transactional,delivery,smtp"
10
+ ---
11
+
12
+ # Postmark API Coding Guidelines (JavaScript/TypeScript)
13
+
14
+ You are a Postmark API coding expert. Help me with writing code using the official Postmark Node.js library for transactional email sending and API interactions.
15
+
16
+ You can find the official documentation and code samples here: https://postmarkapp.com/developer
17
+
18
+ ## Golden Rule: Use the Correct and Current Package
19
+
20
+ Always use the official Postmark Node.js library, which provides complete support for the entire Postmark REST API.
21
+
22
+ - **Library Name:** Postmark Node.js Library
23
+ - **NPM Package:** `postmark`
24
+ - **Minimum Node.js Version:** v14.0.0
25
+ - **Repository:** https://github.com/ActiveCampaign/postmark.js
26
+ - **Documentation:** https://activecampaign.github.io/postmark.js/
27
+
28
+ **Installation:**
29
+
30
+ - **Correct:** `npm install postmark`
31
+
32
+ **APIs and Usage:**
33
+
34
+ - **Correct:** `const postmark = require('postmark')`
35
+ - **Correct:** `const client = new postmark.ServerClient(serverToken)`
36
+ - **Correct:** `const accountClient = new postmark.AccountClient(accountToken)`
37
+ - **Correct:** `await client.sendEmail(...)`
38
+ - **Correct:** `await client.sendEmailWithTemplate(...)`
39
+ - **Correct:** `await client.sendEmailBatch(...)`
40
+ - **Incorrect:** Using unofficial packages or legacy libraries
41
+
42
+ ## API Keys and Authentication
43
+
44
+ Postmark uses two types of API tokens for different purposes:
45
+
46
+ ### Server API Token
47
+
48
+ Used for sending emails and accessing server-specific endpoints. Set the `X-Postmark-Server-Token` header for API requests.
49
+
50
+ ```javascript
51
+ const postmark = require('postmark');
52
+ const serverToken = process.env.POSTMARK_SERVER_TOKEN;
53
+ const client = new postmark.ServerClient(serverToken);
54
+ ```
55
+
56
+ ### Account API Token
57
+
58
+ Used for managing servers and account-level operations. Set the `X-Postmark-Account-Token` header for API requests.
59
+
60
+ ```javascript
61
+ const postmark = require('postmark');
62
+ const accountToken = process.env.POSTMARK_ACCOUNT_TOKEN;
63
+ const accountClient = new postmark.AccountClient(accountToken);
64
+ ```
65
+
66
+ ### Environment Variable Configuration
67
+
68
+ Never hardcode API keys. Always use environment variables:
69
+
70
+ ```bash
71
+ echo "export POSTMARK_SERVER_TOKEN='YOUR_SERVER_TOKEN'" > postmark.env
72
+ echo "export POSTMARK_ACCOUNT_TOKEN='YOUR_ACCOUNT_TOKEN'" >> postmark.env
73
+ echo "postmark.env" >> .gitignore
74
+ source ./postmark.env
75
+ ```
76
+
77
+ ```javascript
78
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
79
+ ```
80
+
81
+ ## Prerequisites
82
+
83
+ Before sending emails with Postmark:
84
+
85
+ - Sign up for a Postmark account (free tier: 100 emails/month)
86
+ - Create a server in your Postmark account
87
+ - Verify your sender signature or domain
88
+ - Obtain your Server API token from the API Tokens tab
89
+
90
+ ## Basic Email Sending
91
+
92
+ ### Simple Email
93
+
94
+ Send a basic email with HTML and text body:
95
+
96
+ ```javascript
97
+ const postmark = require('postmark');
98
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
99
+
100
+ client.sendEmail({
101
+ From: 'sender@example.com',
102
+ To: 'recipient@example.com',
103
+ Subject: 'Hello from Postmark',
104
+ HtmlBody: '<strong>Hello!</strong> This is a test email.',
105
+ TextBody: 'Hello! This is a test email.'
106
+ }).then(response => {
107
+ console.log('Email sent successfully');
108
+ console.log('Message ID:', response.MessageID);
109
+ console.log('To:', response.To);
110
+ console.log('Submitted at:', response.SubmittedAt);
111
+ });
112
+ ```
113
+
114
+ ### Using async/await
115
+
116
+ ```javascript
117
+ const postmark = require('postmark');
118
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
119
+
120
+ async function sendEmail() {
121
+ try {
122
+ const response = await client.sendEmail({
123
+ From: 'sender@example.com',
124
+ To: 'recipient@example.com',
125
+ Subject: 'Hello from Postmark',
126
+ HtmlBody: '<h1>Welcome!</h1><p>This is a test email.</p>',
127
+ TextBody: 'Welcome! This is a test email.'
128
+ });
129
+
130
+ console.log('Email sent:', response.MessageID);
131
+ } catch (error) {
132
+ console.error('Error sending email:', error);
133
+ }
134
+ }
135
+
136
+ sendEmail();
137
+ ```
138
+
139
+ ### Multiple Recipients
140
+
141
+ Send to multiple recipients in the To, Cc, or Bcc fields:
142
+
143
+ ```javascript
144
+ client.sendEmail({
145
+ From: 'sender@example.com',
146
+ To: 'recipient1@example.com, recipient2@example.com',
147
+ Cc: 'cc1@example.com, cc2@example.com',
148
+ Bcc: 'bcc1@example.com, bcc2@example.com',
149
+ Subject: 'Multiple recipients',
150
+ HtmlBody: '<p>This email goes to multiple people.</p>',
151
+ TextBody: 'This email goes to multiple people.'
152
+ });
153
+ ```
154
+
155
+ **Note:** Maximum 50 recipients per field (To, Cc, Bcc).
156
+
157
+ ### With Reply-To Address
158
+
159
+ Override the reply address:
160
+
161
+ ```javascript
162
+ client.sendEmail({
163
+ From: 'noreply@example.com',
164
+ To: 'customer@example.com',
165
+ ReplyTo: 'support@example.com',
166
+ Subject: 'Customer Support',
167
+ HtmlBody: '<p>Reply to this email for support.</p>',
168
+ TextBody: 'Reply to this email for support.'
169
+ });
170
+ ```
171
+
172
+ ## Batch Email Sending
173
+
174
+ Send up to 500 emails in a single API call (maximum 50 MB payload):
175
+
176
+ ```javascript
177
+ const postmark = require('postmark');
178
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
179
+
180
+ client.sendEmailBatch([
181
+ {
182
+ From: 'sender@example.com',
183
+ To: 'user1@example.com',
184
+ Subject: 'Welcome User 1',
185
+ HtmlBody: '<p>Welcome to our service!</p>',
186
+ TextBody: 'Welcome to our service!'
187
+ },
188
+ {
189
+ From: 'sender@example.com',
190
+ To: 'user2@example.com',
191
+ Subject: 'Welcome User 2',
192
+ HtmlBody: '<p>Welcome to our service!</p>',
193
+ TextBody: 'Welcome to our service!'
194
+ },
195
+ {
196
+ From: 'sender@example.com',
197
+ To: 'user3@example.com',
198
+ Subject: 'Welcome User 3',
199
+ HtmlBody: '<p>Welcome to our service!</p>',
200
+ TextBody: 'Welcome to our service!'
201
+ }
202
+ ]).then(responses => {
203
+ responses.forEach((response, index) => {
204
+ console.log(`Email ${index + 1}:`, response.Message);
205
+ console.log('Message ID:', response.MessageID);
206
+ });
207
+ });
208
+ ```
209
+
210
+ **Important:** Batch requests return HTTP 200 even if individual messages fail validation. Always check each response for error codes.
211
+
212
+ ## Template Emails
213
+
214
+ ### Send Email with Template ID
215
+
216
+ Send an email using a pre-created template:
217
+
218
+ ```javascript
219
+ const postmark = require('postmark');
220
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
221
+
222
+ client.sendEmailWithTemplate({
223
+ From: 'sender@example.com',
224
+ To: 'recipient@example.com',
225
+ TemplateId: 123456,
226
+ TemplateModel: {
227
+ name: 'John Doe',
228
+ product_name: 'Awesome App',
229
+ action_url: 'https://example.com/verify',
230
+ company_name: 'My Company'
231
+ }
232
+ }).then(response => {
233
+ console.log('Template email sent:', response.MessageID);
234
+ });
235
+ ```
236
+
237
+ ### Send Email with Template Alias
238
+
239
+ Use a template alias instead of numeric ID:
240
+
241
+ ```javascript
242
+ client.sendEmailWithTemplate({
243
+ From: 'sender@example.com',
244
+ To: 'recipient@example.com',
245
+ TemplateAlias: 'welcome-email',
246
+ TemplateModel: {
247
+ user_name: 'Jane Smith',
248
+ login_url: 'https://example.com/login'
249
+ }
250
+ });
251
+ ```
252
+
253
+ ### Batch Template Emails
254
+
255
+ Send multiple template-based emails:
256
+
257
+ ```javascript
258
+ client.sendEmailBatchWithTemplates([
259
+ {
260
+ From: 'sender@example.com',
261
+ To: 'user1@example.com',
262
+ TemplateId: 123456,
263
+ TemplateModel: {
264
+ name: 'User One',
265
+ code: 'ABC123'
266
+ }
267
+ },
268
+ {
269
+ From: 'sender@example.com',
270
+ To: 'user2@example.com',
271
+ TemplateAlias: 'welcome-email',
272
+ TemplateModel: {
273
+ name: 'User Two',
274
+ code: 'DEF456'
275
+ }
276
+ }
277
+ ]).then(responses => {
278
+ responses.forEach((response, index) => {
279
+ console.log(`Template email ${index + 1}:`, response.Message);
280
+ });
281
+ });
282
+ ```
283
+
284
+ ## Advanced Email Features
285
+
286
+ ### Tags and Metadata
287
+
288
+ Add tags for categorization and metadata for custom tracking:
289
+
290
+ ```javascript
291
+ client.sendEmail({
292
+ From: 'sender@example.com',
293
+ To: 'recipient@example.com',
294
+ Subject: 'Order Confirmation',
295
+ HtmlBody: '<p>Your order has been confirmed.</p>',
296
+ TextBody: 'Your order has been confirmed.',
297
+ Tag: 'order-confirmation',
298
+ Metadata: {
299
+ order_id: '12345',
300
+ customer_id: '67890',
301
+ total_amount: '99.99'
302
+ }
303
+ });
304
+ ```
305
+
306
+ **Metadata notes:**
307
+ - Maximum 1000 characters per tag
308
+ - Metadata appears in webhooks and API responses
309
+ - Useful for tracking and filtering messages
310
+
311
+ ### Tracking Opens
312
+
313
+ Enable open tracking to know when recipients open emails:
314
+
315
+ ```javascript
316
+ client.sendEmail({
317
+ From: 'sender@example.com',
318
+ To: 'recipient@example.com',
319
+ Subject: 'Track opens',
320
+ HtmlBody: '<p>This email tracks opens.</p>',
321
+ TextBody: 'This email tracks opens.',
322
+ TrackOpens: true
323
+ });
324
+ ```
325
+
326
+ ### Tracking Links
327
+
328
+ Track clicks on links in your emails:
329
+
330
+ ```javascript
331
+ client.sendEmail({
332
+ From: 'sender@example.com',
333
+ To: 'recipient@example.com',
334
+ Subject: 'Track links',
335
+ HtmlBody: '<p>Click <a href="https://example.com">here</a>.</p>',
336
+ TextBody: 'Click here: https://example.com',
337
+ TrackLinks: 'HtmlAndText'
338
+ });
339
+ ```
340
+
341
+ **TrackLinks options:**
342
+ - `'None'` - No link tracking
343
+ - `'HtmlOnly'` - Track links in HTML body only
344
+ - `'TextOnly'` - Track links in text body only
345
+ - `'HtmlAndText'` - Track links in both bodies
346
+
347
+ ### Message Streams
348
+
349
+ Organize emails by type using message streams:
350
+
351
+ ```javascript
352
+ client.sendEmail({
353
+ From: 'sender@example.com',
354
+ To: 'recipient@example.com',
355
+ Subject: 'Newsletter',
356
+ HtmlBody: '<p>Monthly newsletter content.</p>',
357
+ TextBody: 'Monthly newsletter content.',
358
+ MessageStream: 'broadcasts'
359
+ });
360
+ ```
361
+
362
+ **Default streams:**
363
+ - `'outbound'` - Transactional emails (default)
364
+ - `'broadcasts'` - Marketing/bulk emails
365
+ - Custom streams can be created in your Postmark account
366
+
367
+ ## Attachments
368
+
369
+ ### Basic Attachments
370
+
371
+ Attach files using Base64 encoding:
372
+
373
+ ```javascript
374
+ const fs = require('fs');
375
+ const postmark = require('postmark');
376
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
377
+
378
+ const fileContent = fs.readFileSync('/path/to/document.pdf');
379
+ const base64Content = fileContent.toString('base64');
380
+
381
+ client.sendEmail({
382
+ From: 'sender@example.com',
383
+ To: 'recipient@example.com',
384
+ Subject: 'Document attached',
385
+ HtmlBody: '<p>Please see the attached document.</p>',
386
+ TextBody: 'Please see the attached document.',
387
+ Attachments: [
388
+ {
389
+ Name: 'document.pdf',
390
+ Content: base64Content,
391
+ ContentType: 'application/pdf'
392
+ }
393
+ ]
394
+ });
395
+ ```
396
+
397
+ ### Using Postmark Models
398
+
399
+ Use the built-in `Attachment` model for cleaner code:
400
+
401
+ ```javascript
402
+ const fs = require('fs');
403
+ const postmark = require('postmark');
404
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
405
+
406
+ const message = new postmark.Models.Message(
407
+ 'sender@example.com',
408
+ 'Document attached',
409
+ '<p>Please see the attached files.</p>',
410
+ 'Please see the attached files.',
411
+ 'recipient@example.com'
412
+ );
413
+
414
+ const attachment1 = new postmark.Models.Attachment(
415
+ 'report.txt',
416
+ Buffer.from('Report content here').toString('base64'),
417
+ 'text/plain'
418
+ );
419
+
420
+ const attachment2 = new postmark.Models.Attachment(
421
+ 'invoice.pdf',
422
+ fs.readFileSync('/path/to/invoice.pdf').toString('base64'),
423
+ 'application/pdf'
424
+ );
425
+
426
+ message.Attachments = [attachment1, attachment2];
427
+
428
+ client.sendEmail(message);
429
+ ```
430
+
431
+ ### Multiple Attachments
432
+
433
+ ```javascript
434
+ const attachments = [
435
+ {
436
+ Name: 'image.jpg',
437
+ Content: fs.readFileSync('/path/to/image.jpg').toString('base64'),
438
+ ContentType: 'image/jpeg'
439
+ },
440
+ {
441
+ Name: 'spreadsheet.xlsx',
442
+ Content: fs.readFileSync('/path/to/data.xlsx').toString('base64'),
443
+ ContentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
444
+ },
445
+ {
446
+ Name: 'notes.txt',
447
+ Content: Buffer.from('Meeting notes...').toString('base64'),
448
+ ContentType: 'text/plain'
449
+ }
450
+ ];
451
+
452
+ client.sendEmail({
453
+ From: 'sender@example.com',
454
+ To: 'recipient@example.com',
455
+ Subject: 'Multiple attachments',
456
+ HtmlBody: '<p>Three files attached.</p>',
457
+ TextBody: 'Three files attached.',
458
+ Attachments: attachments
459
+ });
460
+ ```
461
+
462
+ ### Inline Images
463
+
464
+ Embed images directly in HTML emails using Content ID (CID):
465
+
466
+ ```javascript
467
+ const fs = require('fs');
468
+ const postmark = require('postmark');
469
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
470
+
471
+ const message = new postmark.Models.Message(
472
+ 'sender@example.com',
473
+ 'Inline image example',
474
+ '<!DOCTYPE html><html><body><h1>Logo</h1><img src="cid:logo.png"/></body></html>',
475
+ 'Logo image included.',
476
+ 'recipient@example.com'
477
+ );
478
+
479
+ const inlineImage = new postmark.Models.Attachment(
480
+ 'logo.png',
481
+ fs.readFileSync('/path/to/logo.png').toString('base64'),
482
+ 'image/png',
483
+ 'cid:logo.png'
484
+ );
485
+
486
+ message.Attachments = [inlineImage];
487
+
488
+ client.sendEmail(message);
489
+ ```
490
+
491
+ ## Custom Headers
492
+
493
+ Add custom email headers:
494
+
495
+ ```javascript
496
+ const postmark = require('postmark');
497
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
498
+
499
+ const message = new postmark.Models.Message(
500
+ 'sender@example.com',
501
+ 'Custom headers',
502
+ '<p>Email with custom headers.</p>',
503
+ 'Email with custom headers.',
504
+ 'recipient@example.com'
505
+ );
506
+
507
+ message.Headers = [
508
+ { Name: 'X-Custom-Header', Value: 'custom-value' },
509
+ { Name: 'X-Priority', Value: '1' },
510
+ { Name: 'X-Campaign-ID', Value: 'summer-2025' }
511
+ ];
512
+
513
+ client.sendEmail(message);
514
+ ```
515
+
516
+ ## Template Management
517
+
518
+ ### Get Template
519
+
520
+ Retrieve a template by ID or alias:
521
+
522
+ ```javascript
523
+ // By template ID
524
+ client.getTemplate(123456).then(template => {
525
+ console.log('Template name:', template.Name);
526
+ console.log('Template alias:', template.Alias);
527
+ console.log('HTML body:', template.HtmlBody);
528
+ });
529
+
530
+ // By template alias
531
+ client.getTemplate('welcome-email').then(template => {
532
+ console.log('Template:', template);
533
+ });
534
+ ```
535
+
536
+ ### Create Template
537
+
538
+ ```javascript
539
+ client.createTemplate({
540
+ Name: 'Welcome Email',
541
+ Alias: 'welcome-email',
542
+ Subject: 'Welcome to {{company_name}}!',
543
+ HtmlBody: '<h1>Welcome {{user_name}}!</h1><p>Thanks for joining.</p>',
544
+ TextBody: 'Welcome {{user_name}}! Thanks for joining.'
545
+ }).then(template => {
546
+ console.log('Created template ID:', template.TemplateId);
547
+ });
548
+ ```
549
+
550
+ ### Edit Template
551
+
552
+ ```javascript
553
+ client.editTemplate(123456, {
554
+ Name: 'Updated Welcome Email',
555
+ Subject: 'Welcome to {{company_name}}, {{user_name}}!',
556
+ HtmlBody: '<h1>Hi {{user_name}}!</h1><p>Welcome to {{company_name}}.</p>',
557
+ TextBody: 'Hi {{user_name}}! Welcome to {{company_name}}.'
558
+ }).then(template => {
559
+ console.log('Updated template:', template.Name);
560
+ });
561
+ ```
562
+
563
+ ### Delete Template
564
+
565
+ ```javascript
566
+ // By template ID
567
+ client.deleteTemplate(123456).then(response => {
568
+ console.log('Template deleted:', response.Message);
569
+ });
570
+
571
+ // By template alias
572
+ client.deleteTemplate('old-template').then(response => {
573
+ console.log('Template deleted:', response.Message);
574
+ });
575
+ ```
576
+
577
+ ### List Templates
578
+
579
+ ```javascript
580
+ client.getTemplates({
581
+ Count: 10,
582
+ Offset: 0
583
+ }).then(result => {
584
+ console.log('Total templates:', result.TotalCount);
585
+ result.Templates.forEach(template => {
586
+ console.log('Template:', template.Name, '(ID:', template.TemplateId + ')');
587
+ });
588
+ });
589
+ ```
590
+
591
+ ### Validate Template
592
+
593
+ Test template rendering before sending:
594
+
595
+ ```javascript
596
+ client.validateTemplate({
597
+ Subject: 'Hello {{name}}',
598
+ HtmlBody: '<p>Welcome {{name}} to {{company}}!</p>',
599
+ TextBody: 'Welcome {{name}} to {{company}}!',
600
+ TestRenderModel: {
601
+ name: 'John',
602
+ company: 'Acme Corp'
603
+ }
604
+ }).then(result => {
605
+ console.log('Rendered subject:', result.Subject.RenderedContent);
606
+ console.log('Rendered HTML:', result.HtmlBody.RenderedContent);
607
+ console.log('Suggested template model:', result.SuggestedTemplateModel);
608
+ });
609
+ ```
610
+
611
+ ## Messages API
612
+
613
+ ### Get Outbound Messages
614
+
615
+ Retrieve sent messages with filtering:
616
+
617
+ ```javascript
618
+ client.getOutboundMessages({
619
+ Count: 50,
620
+ Offset: 0,
621
+ Recipient: 'user@example.com',
622
+ FromEmail: 'sender@example.com',
623
+ Tag: 'order-confirmation',
624
+ Status: 'sent'
625
+ }).then(result => {
626
+ console.log('Total messages:', result.TotalCount);
627
+ result.Messages.forEach(message => {
628
+ console.log('Message ID:', message.MessageID);
629
+ console.log('Subject:', message.Subject);
630
+ console.log('Status:', message.Status);
631
+ });
632
+ });
633
+ ```
634
+
635
+ ### Get Message Details
636
+
637
+ ```javascript
638
+ client.getOutboundMessageDetails('message-id-here').then(details => {
639
+ console.log('From:', details.From);
640
+ console.log('To:', details.To);
641
+ console.log('Subject:', details.Subject);
642
+ console.log('Status:', details.Status);
643
+ console.log('Received at:', details.ReceivedAt);
644
+ console.log('Message events:', details.MessageEvents);
645
+ });
646
+ ```
647
+
648
+ ### Get Message Dump
649
+
650
+ Retrieve full message content including headers:
651
+
652
+ ```javascript
653
+ client.getOutboundMessageDump('message-id-here').then(dump => {
654
+ console.log('Raw message:', dump.Body);
655
+ });
656
+ ```
657
+
658
+ ### Get Message Clicks
659
+
660
+ Track which links were clicked:
661
+
662
+ ```javascript
663
+ client.getMessageClicks('message-id-here').then(result => {
664
+ result.Clicks.forEach(click => {
665
+ console.log('Link:', click.OriginalLink);
666
+ console.log('Clicked at:', click.RecordedAt);
667
+ console.log('Platform:', click.Platform);
668
+ });
669
+ });
670
+ ```
671
+
672
+ ### Get Message Opens
673
+
674
+ Track when messages were opened:
675
+
676
+ ```javascript
677
+ client.getMessageOpens('message-id-here').then(result => {
678
+ result.Opens.forEach(open => {
679
+ console.log('Opened at:', open.RecordedAt);
680
+ console.log('Platform:', open.Platform);
681
+ console.log('Client:', open.Client);
682
+ });
683
+ });
684
+ ```
685
+
686
+ ## Inbound Email Processing
687
+
688
+ ### Get Inbound Messages
689
+
690
+ Retrieve inbound emails sent to your Postmark inbox:
691
+
692
+ ```javascript
693
+ client.getInboundMessages({
694
+ Count: 50,
695
+ Offset: 0,
696
+ Recipient: 'inbox@inbound.example.com',
697
+ FromEmail: 'sender@example.com'
698
+ }).then(result => {
699
+ console.log('Total inbound messages:', result.TotalCount);
700
+ result.InboundMessages.forEach(message => {
701
+ console.log('From:', message.From);
702
+ console.log('Subject:', message.Subject);
703
+ console.log('Received:', message.ReceivedAt);
704
+ });
705
+ });
706
+ ```
707
+
708
+ ### Get Inbound Message Details
709
+
710
+ ```javascript
711
+ client.getInboundMessageDetails('inbound-message-id').then(message => {
712
+ console.log('From:', message.From);
713
+ console.log('To:', message.To);
714
+ console.log('Subject:', message.Subject);
715
+ console.log('HTML body:', message.HtmlBody);
716
+ console.log('Text body:', message.TextBody);
717
+ console.log('Attachments:', message.Attachments);
718
+ });
719
+ ```
720
+
721
+ ### Bypass Blocked Inbound Message
722
+
723
+ Allow specific blocked inbound messages:
724
+
725
+ ```javascript
726
+ client.bypassBlockedInboundMessage('inbound-message-id').then(response => {
727
+ console.log('Message unblocked:', response.Message);
728
+ });
729
+ ```
730
+
731
+ ### Retry Inbound Hook
732
+
733
+ Manually retry webhook delivery for an inbound message:
734
+
735
+ ```javascript
736
+ client.retryInboundHookForMessage('inbound-message-id').then(response => {
737
+ console.log('Hook retried:', response.Message);
738
+ });
739
+ ```
740
+
741
+ ## Bounce Management
742
+
743
+ ### Get Bounces
744
+
745
+ Retrieve bounced emails:
746
+
747
+ ```javascript
748
+ client.getBounces({
749
+ Count: 50,
750
+ Offset: 0,
751
+ Type: 'HardBounce',
752
+ EmailFilter: 'user@example.com',
753
+ Tag: 'newsletter'
754
+ }).then(result => {
755
+ console.log('Total bounces:', result.TotalCount);
756
+ result.Bounces.forEach(bounce => {
757
+ console.log('Email:', bounce.Email);
758
+ console.log('Type:', bounce.Type);
759
+ console.log('Bounced at:', bounce.BouncedAt);
760
+ });
761
+ });
762
+ ```
763
+
764
+ ### Get Bounce Details
765
+
766
+ ```javascript
767
+ client.getBounce('bounce-id').then(bounce => {
768
+ console.log('Email:', bounce.Email);
769
+ console.log('Type:', bounce.Type);
770
+ console.log('Description:', bounce.Description);
771
+ console.log('Details:', bounce.Details);
772
+ });
773
+ ```
774
+
775
+ ### Get Bounce Dump
776
+
777
+ Retrieve raw bounce message:
778
+
779
+ ```javascript
780
+ client.getBounceDump('bounce-id').then(dump => {
781
+ console.log('Raw bounce:', dump.Body);
782
+ });
783
+ ```
784
+
785
+ ### Activate Bounced Email
786
+
787
+ Reactivate a bounced email address:
788
+
789
+ ```javascript
790
+ client.activateBounce('bounce-id').then(response => {
791
+ console.log('Bounce activated:', response.Message);
792
+ });
793
+ ```
794
+
795
+ ## Suppressions Management
796
+
797
+ ### Get Suppressions
798
+
799
+ Retrieve suppressed email addresses:
800
+
801
+ ```javascript
802
+ client.getSuppressions('outbound', {
803
+ Count: 50,
804
+ Offset: 0,
805
+ EmailFilter: 'user@example.com'
806
+ }).then(result => {
807
+ console.log('Total suppressions:', result.Suppressions.length);
808
+ result.Suppressions.forEach(suppression => {
809
+ console.log('Email:', suppression.EmailAddress);
810
+ console.log('Reason:', suppression.SuppressionReason);
811
+ console.log('Created at:', suppression.CreatedAt);
812
+ });
813
+ });
814
+ ```
815
+
816
+ ### Create Suppressions
817
+
818
+ Manually suppress email addresses:
819
+
820
+ ```javascript
821
+ client.createSuppressions('outbound', [
822
+ { EmailAddress: 'user1@example.com' },
823
+ { EmailAddress: 'user2@example.com' }
824
+ ]).then(result => {
825
+ console.log('Suppressions created:', result.Suppressions.length);
826
+ });
827
+ ```
828
+
829
+ ### Delete Suppressions
830
+
831
+ Remove email addresses from suppression list:
832
+
833
+ ```javascript
834
+ client.deleteSuppressions('outbound', [
835
+ { EmailAddress: 'user1@example.com' },
836
+ { EmailAddress: 'user2@example.com' }
837
+ ]).then(result => {
838
+ console.log('Suppressions deleted:', result.Suppressions.length);
839
+ });
840
+ ```
841
+
842
+ ## Webhooks
843
+
844
+ ### Get Webhooks
845
+
846
+ Retrieve configured webhooks:
847
+
848
+ ```javascript
849
+ client.getWebhooks().then(webhooks => {
850
+ webhooks.Webhooks.forEach(webhook => {
851
+ console.log('Webhook ID:', webhook.ID);
852
+ console.log('URL:', webhook.Url);
853
+ console.log('Message stream:', webhook.MessageStream);
854
+ console.log('Triggers:', webhook.Triggers);
855
+ });
856
+ });
857
+ ```
858
+
859
+ ### Create Webhook
860
+
861
+ ```javascript
862
+ client.createWebhook({
863
+ Url: 'https://example.com/webhooks/postmark',
864
+ MessageStream: 'outbound',
865
+ HttpAuth: {
866
+ Username: 'webhook_user',
867
+ Password: 'webhook_pass'
868
+ },
869
+ HttpHeaders: [
870
+ { Name: 'X-Custom-Header', Value: 'value' }
871
+ ],
872
+ Triggers: {
873
+ Open: { Enabled: true },
874
+ Click: { Enabled: true },
875
+ Delivery: { Enabled: true },
876
+ Bounce: { Enabled: true },
877
+ SpamComplaint: { Enabled: true }
878
+ }
879
+ }).then(webhook => {
880
+ console.log('Webhook created:', webhook.ID);
881
+ });
882
+ ```
883
+
884
+ ### Edit Webhook
885
+
886
+ ```javascript
887
+ client.editWebhook(123456, {
888
+ Url: 'https://example.com/webhooks/postmark-updated',
889
+ Triggers: {
890
+ Open: { Enabled: true },
891
+ Click: { Enabled: true },
892
+ Delivery: { Enabled: false }
893
+ }
894
+ }).then(webhook => {
895
+ console.log('Webhook updated:', webhook.ID);
896
+ });
897
+ ```
898
+
899
+ ### Delete Webhook
900
+
901
+ ```javascript
902
+ client.deleteWebhook(123456).then(response => {
903
+ console.log('Webhook deleted:', response.Message);
904
+ });
905
+ ```
906
+
907
+ ## Server Management (Account Client)
908
+
909
+ ### Get Server
910
+
911
+ ```javascript
912
+ const postmark = require('postmark');
913
+ const accountClient = new postmark.AccountClient(process.env.POSTMARK_ACCOUNT_TOKEN);
914
+
915
+ accountClient.getServer(123456).then(server => {
916
+ console.log('Server name:', server.Name);
917
+ console.log('Server ID:', server.ID);
918
+ console.log('Color:', server.Color);
919
+ });
920
+ ```
921
+
922
+ ### Create Server
923
+
924
+ ```javascript
925
+ accountClient.createServer({
926
+ Name: 'Production Server',
927
+ Color: 'blue'
928
+ }).then(server => {
929
+ console.log('Server created:', server.ID);
930
+ console.log('Server token:', server.ApiTokens);
931
+ });
932
+ ```
933
+
934
+ ### Edit Server
935
+
936
+ ```javascript
937
+ accountClient.editServer(123456, {
938
+ Name: 'Updated Server Name',
939
+ Color: 'green'
940
+ }).then(server => {
941
+ console.log('Server updated:', server.Name);
942
+ });
943
+ ```
944
+
945
+ ### List Servers
946
+
947
+ ```javascript
948
+ accountClient.getServers({
949
+ Count: 50,
950
+ Offset: 0,
951
+ Name: 'Production'
952
+ }).then(result => {
953
+ console.log('Total servers:', result.TotalCount);
954
+ result.Servers.forEach(server => {
955
+ console.log('Server:', server.Name, '(ID:', server.ID + ')');
956
+ });
957
+ });
958
+ ```
959
+
960
+ ## Client Configuration
961
+
962
+ ### Timeout Configuration
963
+
964
+ Set custom timeout for API requests:
965
+
966
+ ```javascript
967
+ const postmark = require('postmark');
968
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
969
+
970
+ // Set timeout to 30 seconds (default is 30000ms)
971
+ client.setClientOptions({ timeout: 60000 });
972
+ ```
973
+
974
+ ### Custom Headers
975
+
976
+ Add default headers to all requests:
977
+
978
+ ```javascript
979
+ client.setClientOptions({
980
+ headers: {
981
+ 'X-Custom-Header': 'custom-value'
982
+ }
983
+ });
984
+ ```
985
+
986
+ ### Use Test Token
987
+
988
+ For testing without sending actual emails:
989
+
990
+ ```javascript
991
+ const client = new postmark.ServerClient('POSTMARK_API_TEST');
992
+
993
+ // This will validate the API call but not actually send the email
994
+ client.sendEmail({
995
+ From: 'sender@example.com',
996
+ To: 'recipient@example.com',
997
+ Subject: 'Test email',
998
+ HtmlBody: '<p>This is a test.</p>'
999
+ });
1000
+ ```
1001
+
1002
+ ## Error Handling
1003
+
1004
+ Always handle errors properly when making API calls:
1005
+
1006
+ ```javascript
1007
+ const postmark = require('postmark');
1008
+ const client = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN);
1009
+
1010
+ async function sendEmailWithErrorHandling() {
1011
+ try {
1012
+ const response = await client.sendEmail({
1013
+ From: 'sender@example.com',
1014
+ To: 'recipient@example.com',
1015
+ Subject: 'Test',
1016
+ HtmlBody: '<p>Test email</p>'
1017
+ });
1018
+
1019
+ console.log('Success:', response.MessageID);
1020
+ return response;
1021
+
1022
+ } catch (error) {
1023
+ // Handle specific error codes
1024
+ if (error.statusCode === 401) {
1025
+ console.error('Invalid API token');
1026
+ } else if (error.statusCode === 422) {
1027
+ console.error('Validation error:', error.message);
1028
+ } else if (error.statusCode === 429) {
1029
+ console.error('Rate limit exceeded');
1030
+ } else if (error.statusCode >= 500) {
1031
+ console.error('Server error:', error.message);
1032
+ } else {
1033
+ console.error('API error:', error.message);
1034
+ }
1035
+
1036
+ console.error('Error code:', error.code);
1037
+ console.error('Error details:', error.body);
1038
+
1039
+ throw error;
1040
+ }
1041
+ }
1042
+
1043
+ sendEmailWithErrorHandling();
1044
+ ```
1045
+
1046
+ ### Common Error Codes
1047
+
1048
+ | Status Code | Error Type | Description |
1049
+ |-------------|------------|-------------|
1050
+ | 401 | Unauthorized | Invalid or missing API token |
1051
+ | 403 | Forbidden | Sender signature not verified |
1052
+ | 422 | Unprocessable Entity | Validation error (invalid parameters) |
1053
+ | 429 | Too Many Requests | Rate limit exceeded |
1054
+ | 500 | Internal Server Error | Postmark server error |
1055
+ | 503 | Service Unavailable | Postmark temporarily unavailable |
1056
+
1057
+ ### Batch Error Handling
1058
+
1059
+ When sending batch emails, check each response individually:
1060
+
1061
+ ```javascript
1062
+ const responses = await client.sendEmailBatch([
1063
+ { From: 'sender@example.com', To: 'user1@example.com', Subject: 'Test 1', HtmlBody: '<p>Test</p>' },
1064
+ { From: 'sender@example.com', To: 'invalid-email', Subject: 'Test 2', HtmlBody: '<p>Test</p>' },
1065
+ { From: 'sender@example.com', To: 'user3@example.com', Subject: 'Test 3', HtmlBody: '<p>Test</p>' }
1066
+ ]);
1067
+
1068
+ responses.forEach((response, index) => {
1069
+ if (response.ErrorCode === 0) {
1070
+ console.log(`Email ${index + 1} sent successfully:`, response.MessageID);
1071
+ } else {
1072
+ console.error(`Email ${index + 1} failed:`, response.Message);
1073
+ }
1074
+ });
1075
+ ```
1076
+
1077
+ ## TypeScript Support
1078
+
1079
+ The Postmark library includes full TypeScript definitions:
1080
+
1081
+ ```typescript
1082
+ import * as postmark from 'postmark';
1083
+ import { ServerClient, Message, TemplatedMessage } from 'postmark';
1084
+
1085
+ const client: ServerClient = new postmark.ServerClient(process.env.POSTMARK_SERVER_TOKEN!);
1086
+
1087
+ interface EmailResponse {
1088
+ To: string;
1089
+ SubmittedAt: string;
1090
+ MessageID: string;
1091
+ ErrorCode: number;
1092
+ Message: string;
1093
+ }
1094
+
1095
+ async function sendTypedEmail(): Promise<EmailResponse> {
1096
+ const message: Message = new postmark.Models.Message(
1097
+ 'sender@example.com',
1098
+ 'Test email',
1099
+ '<p>HTML body</p>',
1100
+ 'Text body',
1101
+ 'recipient@example.com'
1102
+ );
1103
+
1104
+ const response = await client.sendEmail(message);
1105
+ return response;
1106
+ }
1107
+
1108
+ async function sendTemplateEmail(): Promise<EmailResponse> {
1109
+ const templateMessage: TemplatedMessage = {
1110
+ From: 'sender@example.com',
1111
+ To: 'recipient@example.com',
1112
+ TemplateId: 123456,
1113
+ TemplateModel: {
1114
+ name: 'John Doe',
1115
+ code: 'ABC123'
1116
+ }
1117
+ };
1118
+
1119
+ const response = await client.sendEmailWithTemplate(templateMessage);
1120
+ return response;
1121
+ }
1122
+ ```
1123
+
1124
+ ## ES6 Module Support
1125
+
1126
+ Use ES6 imports:
1127
+
1128
+ ```javascript
1129
+ import * as postmark from 'postmark';
1130
+
1131
+ const serverToken = process.env.POSTMARK_SERVER_TOKEN;
1132
+ const client = new postmark.ServerClient(serverToken);
1133
+
1134
+ export async function sendWelcomeEmail(recipientEmail, userName) {
1135
+ return await client.sendEmailWithTemplate({
1136
+ From: 'welcome@example.com',
1137
+ To: recipientEmail,
1138
+ TemplateAlias: 'welcome-email',
1139
+ TemplateModel: {
1140
+ user_name: userName
1141
+ }
1142
+ });
1143
+ }
1144
+ ```
1145
+
1146
+ ## Useful Links
1147
+
1148
+ - **Official Documentation:** https://postmarkapp.com/developer
1149
+ - **API Reference:** https://postmarkapp.com/developer/api/overview
1150
+ - **Node.js Library Docs:** https://activecampaign.github.io/postmark.js/
1151
+ - **GitHub Repository:** https://github.com/ActiveCampaign/postmark.js
1152
+ - **NPM Package:** https://www.npmjs.com/package/postmark
1153
+ - **Email API:** https://postmarkapp.com/developer/api/email-api
1154
+ - **Templates API:** https://postmarkapp.com/developer/api/templates-api
1155
+ - **Webhooks:** https://postmarkapp.com/developer/webhooks/webhooks-overview
1156
+ - **Support:** https://postmarkapp.com/support
1157
+
1158
+ ## Notes
1159
+
1160
+ - Always verify sender signatures or domains before sending emails
1161
+ - Use the test token `POSTMARK_API_TEST` for development
1162
+ - Batch requests can include up to 500 messages (50 MB max)
1163
+ - Open tracking requires HTML body
1164
+ - Link tracking works in both HTML and text bodies
1165
+ - Metadata is included in webhooks and API responses
1166
+ - Messages are stored for 45 days by default (configurable up to 365 days)
1167
+ - Rate limits apply based on your account plan
1168
+ - Always check individual responses in batch operations