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.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,1420 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: marketing
|
|
3
|
+
description: "Mailchimp Marketing API Node.js SDK Coding Guidelines for email marketing, audience management, and campaign management"
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "javascript"
|
|
6
|
+
versions: "3.0.80"
|
|
7
|
+
updated-on: "2026-03-02"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "mailchimp,marketing,email,campaigns,audience"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mailchimp Marketing API Node.js SDK Coding Guidelines (JavaScript/TypeScript)
|
|
13
|
+
|
|
14
|
+
You are a Mailchimp Marketing API coding expert. Help me with writing code using the official Mailchimp Marketing Node.js library for email marketing, audience management, campaign management, and e-commerce integrations. Please follow the following guidelines when generating code.
|
|
15
|
+
|
|
16
|
+
You can find the official documentation and code samples here: https://mailchimp.com/developer/marketing/
|
|
17
|
+
|
|
18
|
+
## Golden Rule: Use the Correct and Current SDK
|
|
19
|
+
|
|
20
|
+
Always use the official Mailchimp Marketing Node.js SDK, which is the standard library for all Mailchimp Marketing API interactions.
|
|
21
|
+
|
|
22
|
+
- **Primary Package:** `@mailchimp/mailchimp_marketing`
|
|
23
|
+
- **GitHub Repository:** https://github.com/mailchimp/mailchimp-marketing-node
|
|
24
|
+
- **Current Version:** 3.0.80
|
|
25
|
+
|
|
26
|
+
**Installation:**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @mailchimp/mailchimp_marketing
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**APIs and Usage:**
|
|
33
|
+
|
|
34
|
+
- **Correct:** `const mailchimp = require('@mailchimp/mailchimp_marketing')`
|
|
35
|
+
- **Correct:** `mailchimp.setConfig({ apiKey: '...', server: '...' })`
|
|
36
|
+
- **Correct:** `await mailchimp.lists.getAllLists()`
|
|
37
|
+
- **Correct:** `await mailchimp.campaigns.create({ ... })`
|
|
38
|
+
- **Incorrect:** Using legacy or unofficial packages like `mailchimp`, `mailchimp-api-v3`, or `node-mailchimp`
|
|
39
|
+
|
|
40
|
+
## Prerequisites and Setup
|
|
41
|
+
|
|
42
|
+
Before using the Mailchimp Marketing Node.js library, ensure you have:
|
|
43
|
+
|
|
44
|
+
- Node.js installed (version 12 or higher recommended)
|
|
45
|
+
- A Mailchimp account with an API key
|
|
46
|
+
- Your Mailchimp server prefix (e.g., `us19`, `us6`)
|
|
47
|
+
|
|
48
|
+
## Finding Your Server Prefix
|
|
49
|
+
|
|
50
|
+
The server prefix is required for API authentication. To find it:
|
|
51
|
+
|
|
52
|
+
1. Log into your Mailchimp account
|
|
53
|
+
2. Look at the URL in your browser: `https://us19.admin.mailchimp.com/`
|
|
54
|
+
3. The `us19` part is your server prefix
|
|
55
|
+
|
|
56
|
+
Alternatively, your API key ends with the server prefix: if your key is `abc123-us6`, then `us6` is your server prefix.
|
|
57
|
+
|
|
58
|
+
## API Key Configuration
|
|
59
|
+
|
|
60
|
+
**Never hardcode your API key.** Always use environment variables:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# .env file
|
|
64
|
+
MAILCHIMP_API_KEY=your_api_key_here
|
|
65
|
+
MAILCHIMP_SERVER_PREFIX=us19
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
require('dotenv').config();
|
|
70
|
+
|
|
71
|
+
const mailchimp = require('@mailchimp/mailchimp_marketing');
|
|
72
|
+
|
|
73
|
+
mailchimp.setConfig({
|
|
74
|
+
apiKey: process.env.MAILCHIMP_API_KEY,
|
|
75
|
+
server: process.env.MAILCHIMP_SERVER_PREFIX,
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Initialization
|
|
80
|
+
|
|
81
|
+
### Basic Authentication (API Key)
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
const mailchimp = require('@mailchimp/mailchimp_marketing');
|
|
85
|
+
|
|
86
|
+
mailchimp.setConfig({
|
|
87
|
+
apiKey: process.env.MAILCHIMP_API_KEY,
|
|
88
|
+
server: process.env.MAILCHIMP_SERVER_PREFIX,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Test connection
|
|
92
|
+
async function testConnection() {
|
|
93
|
+
try {
|
|
94
|
+
const response = await mailchimp.ping.get();
|
|
95
|
+
console.log('Connected to Mailchimp:', response);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error('Connection failed:', error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### OAuth2 Authentication
|
|
103
|
+
|
|
104
|
+
For applications that access Mailchimp on behalf of other users:
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const mailchimp = require('@mailchimp/mailchimp_marketing');
|
|
108
|
+
|
|
109
|
+
mailchimp.setConfig({
|
|
110
|
+
accessToken: process.env.MAILCHIMP_ACCESS_TOKEN,
|
|
111
|
+
server: process.env.MAILCHIMP_SERVER_PREFIX,
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Audiences (Lists) Management
|
|
116
|
+
|
|
117
|
+
### Get All Lists
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
async function getAllLists() {
|
|
121
|
+
try {
|
|
122
|
+
const response = await mailchimp.lists.getAllLists();
|
|
123
|
+
console.log('Total lists:', response.total_items);
|
|
124
|
+
|
|
125
|
+
response.lists.forEach(list => {
|
|
126
|
+
console.log(`List: ${list.name} (ID: ${list.id})`);
|
|
127
|
+
console.log(`Members: ${list.stats.member_count}`);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return response.lists;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error('Error fetching lists:', error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Get Specific List Information
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
async function getListInfo(listId) {
|
|
141
|
+
try {
|
|
142
|
+
const response = await mailchimp.lists.getList(listId);
|
|
143
|
+
console.log('List Name:', response.name);
|
|
144
|
+
console.log('Total Members:', response.stats.member_count);
|
|
145
|
+
console.log('Unsubscribe Count:', response.stats.unsubscribe_count);
|
|
146
|
+
console.log('Open Rate:', response.stats.open_rate);
|
|
147
|
+
console.log('Click Rate:', response.stats.click_rate);
|
|
148
|
+
return response;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('Error fetching list info:', error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Create a New List
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
async function createList() {
|
|
159
|
+
try {
|
|
160
|
+
const response = await mailchimp.lists.createList({
|
|
161
|
+
name: 'My New Newsletter',
|
|
162
|
+
contact: {
|
|
163
|
+
company: 'My Company',
|
|
164
|
+
address1: '123 Main St',
|
|
165
|
+
city: 'New York',
|
|
166
|
+
state: 'NY',
|
|
167
|
+
zip: '10001',
|
|
168
|
+
country: 'US',
|
|
169
|
+
},
|
|
170
|
+
permission_reminder: 'You signed up for updates on our website.',
|
|
171
|
+
campaign_defaults: {
|
|
172
|
+
from_name: 'My Company',
|
|
173
|
+
from_email: 'hello@mycompany.com',
|
|
174
|
+
subject: 'Newsletter',
|
|
175
|
+
language: 'en',
|
|
176
|
+
},
|
|
177
|
+
email_type_option: true,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
console.log('List created:', response.id);
|
|
181
|
+
return response;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error('Error creating list:', error);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## List Members Management
|
|
189
|
+
|
|
190
|
+
### Add a Member to a List
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
async function addMemberToList(listId, email, firstName, lastName) {
|
|
194
|
+
try {
|
|
195
|
+
const response = await mailchimp.lists.addListMember(listId, {
|
|
196
|
+
email_address: email,
|
|
197
|
+
status: 'subscribed',
|
|
198
|
+
merge_fields: {
|
|
199
|
+
FNAME: firstName,
|
|
200
|
+
LNAME: lastName,
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
console.log(`Added ${email} to list`);
|
|
205
|
+
return response;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error('Error adding member:', error);
|
|
208
|
+
if (error.status === 400) {
|
|
209
|
+
console.error('Member might already exist or email is invalid');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Add or Update a Member
|
|
216
|
+
|
|
217
|
+
Use this to avoid errors when a member already exists:
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
const crypto = require('crypto');
|
|
221
|
+
|
|
222
|
+
async function addOrUpdateMember(listId, email, firstName, lastName, tags = []) {
|
|
223
|
+
try {
|
|
224
|
+
// Create MD5 hash of lowercase email for subscriber_hash
|
|
225
|
+
const subscriberHash = crypto
|
|
226
|
+
.createHash('md5')
|
|
227
|
+
.update(email.toLowerCase())
|
|
228
|
+
.digest('hex');
|
|
229
|
+
|
|
230
|
+
const response = await mailchimp.lists.setListMember(
|
|
231
|
+
listId,
|
|
232
|
+
subscriberHash,
|
|
233
|
+
{
|
|
234
|
+
email_address: email,
|
|
235
|
+
status_if_new: 'subscribed',
|
|
236
|
+
merge_fields: {
|
|
237
|
+
FNAME: firstName,
|
|
238
|
+
LNAME: lastName,
|
|
239
|
+
},
|
|
240
|
+
tags: tags,
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
console.log(`Added/Updated ${email}`);
|
|
245
|
+
return response;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error('Error adding/updating member:', error);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Get List Members
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
async function getListMembers(listId, count = 100) {
|
|
256
|
+
try {
|
|
257
|
+
const response = await mailchimp.lists.getListMembersInfo(listId, {
|
|
258
|
+
count: count,
|
|
259
|
+
offset: 0,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
console.log(`Total members: ${response.total_items}`);
|
|
263
|
+
|
|
264
|
+
response.members.forEach(member => {
|
|
265
|
+
console.log(`${member.email_address} - ${member.status}`);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
return response.members;
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.error('Error fetching members:', error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Get Specific Member Information
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
const crypto = require('crypto');
|
|
279
|
+
|
|
280
|
+
async function getMemberInfo(listId, email) {
|
|
281
|
+
try {
|
|
282
|
+
const subscriberHash = crypto
|
|
283
|
+
.createHash('md5')
|
|
284
|
+
.update(email.toLowerCase())
|
|
285
|
+
.digest('hex');
|
|
286
|
+
|
|
287
|
+
const response = await mailchimp.lists.getListMember(
|
|
288
|
+
listId,
|
|
289
|
+
subscriberHash
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
console.log('Member:', response.email_address);
|
|
293
|
+
console.log('Status:', response.status);
|
|
294
|
+
console.log('Member since:', response.timestamp_opt);
|
|
295
|
+
console.log('Tags:', response.tags);
|
|
296
|
+
|
|
297
|
+
return response;
|
|
298
|
+
} catch (error) {
|
|
299
|
+
console.error('Error fetching member:', error);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Update Member Information
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
const crypto = require('crypto');
|
|
308
|
+
|
|
309
|
+
async function updateMember(listId, email, updates) {
|
|
310
|
+
try {
|
|
311
|
+
const subscriberHash = crypto
|
|
312
|
+
.createHash('md5')
|
|
313
|
+
.update(email.toLowerCase())
|
|
314
|
+
.digest('hex');
|
|
315
|
+
|
|
316
|
+
const response = await mailchimp.lists.updateListMember(
|
|
317
|
+
listId,
|
|
318
|
+
subscriberHash,
|
|
319
|
+
updates
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
console.log('Member updated:', response.email_address);
|
|
323
|
+
return response;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
console.error('Error updating member:', error);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Example usage
|
|
330
|
+
updateMember('list123', 'user@example.com', {
|
|
331
|
+
merge_fields: {
|
|
332
|
+
FNAME: 'Jane',
|
|
333
|
+
LNAME: 'Smith',
|
|
334
|
+
},
|
|
335
|
+
status: 'subscribed',
|
|
336
|
+
});
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Delete a Member
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
const crypto = require('crypto');
|
|
343
|
+
|
|
344
|
+
async function deleteMember(listId, email) {
|
|
345
|
+
try {
|
|
346
|
+
const subscriberHash = crypto
|
|
347
|
+
.createHash('md5')
|
|
348
|
+
.update(email.toLowerCase())
|
|
349
|
+
.digest('hex');
|
|
350
|
+
|
|
351
|
+
await mailchimp.lists.deleteListMember(listId, subscriberHash);
|
|
352
|
+
console.log(`Deleted ${email} from list`);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error('Error deleting member:', error);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Batch Subscribe or Unsubscribe
|
|
360
|
+
|
|
361
|
+
```javascript
|
|
362
|
+
async function batchSubscribe(listId, members) {
|
|
363
|
+
try {
|
|
364
|
+
const response = await mailchimp.lists.batchListMembers(listId, {
|
|
365
|
+
members: members.map(member => ({
|
|
366
|
+
email_address: member.email,
|
|
367
|
+
status: 'subscribed',
|
|
368
|
+
merge_fields: {
|
|
369
|
+
FNAME: member.firstName,
|
|
370
|
+
LNAME: member.lastName,
|
|
371
|
+
},
|
|
372
|
+
})),
|
|
373
|
+
update_existing: true,
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
console.log('New members:', response.new_members.length);
|
|
377
|
+
console.log('Updated members:', response.updated_members.length);
|
|
378
|
+
console.log('Errors:', response.errors.length);
|
|
379
|
+
|
|
380
|
+
return response;
|
|
381
|
+
} catch (error) {
|
|
382
|
+
console.error('Error batch subscribing:', error);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Example usage
|
|
387
|
+
batchSubscribe('list123', [
|
|
388
|
+
{ email: 'user1@example.com', firstName: 'John', lastName: 'Doe' },
|
|
389
|
+
{ email: 'user2@example.com', firstName: 'Jane', lastName: 'Smith' },
|
|
390
|
+
]);
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## Tags Management
|
|
394
|
+
|
|
395
|
+
### Add Tags to a Member
|
|
396
|
+
|
|
397
|
+
```javascript
|
|
398
|
+
const crypto = require('crypto');
|
|
399
|
+
|
|
400
|
+
async function addTagsToMember(listId, email, tags) {
|
|
401
|
+
try {
|
|
402
|
+
const subscriberHash = crypto
|
|
403
|
+
.createHash('md5')
|
|
404
|
+
.update(email.toLowerCase())
|
|
405
|
+
.digest('hex');
|
|
406
|
+
|
|
407
|
+
const response = await mailchimp.lists.updateListMemberTags(
|
|
408
|
+
listId,
|
|
409
|
+
subscriberHash,
|
|
410
|
+
{
|
|
411
|
+
tags: tags.map(tag => ({ name: tag, status: 'active' })),
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
console.log(`Added tags to ${email}`);
|
|
416
|
+
return response;
|
|
417
|
+
} catch (error) {
|
|
418
|
+
console.error('Error adding tags:', error);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Example usage
|
|
423
|
+
addTagsToMember('list123', 'user@example.com', ['VIP', 'Newsletter']);
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Remove Tags from a Member
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
const crypto = require('crypto');
|
|
430
|
+
|
|
431
|
+
async function removeTagsFromMember(listId, email, tags) {
|
|
432
|
+
try {
|
|
433
|
+
const subscriberHash = crypto
|
|
434
|
+
.createHash('md5')
|
|
435
|
+
.update(email.toLowerCase())
|
|
436
|
+
.digest('hex');
|
|
437
|
+
|
|
438
|
+
const response = await mailchimp.lists.updateListMemberTags(
|
|
439
|
+
listId,
|
|
440
|
+
subscriberHash,
|
|
441
|
+
{
|
|
442
|
+
tags: tags.map(tag => ({ name: tag, status: 'inactive' })),
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
console.log(`Removed tags from ${email}`);
|
|
447
|
+
return response;
|
|
448
|
+
} catch (error) {
|
|
449
|
+
console.error('Error removing tags:', error);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Segments Management
|
|
455
|
+
|
|
456
|
+
### Get All Segments for a List
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
async function getSegments(listId) {
|
|
460
|
+
try {
|
|
461
|
+
const response = await mailchimp.lists.listSegments(listId);
|
|
462
|
+
|
|
463
|
+
console.log('Total segments:', response.total_items);
|
|
464
|
+
|
|
465
|
+
response.segments.forEach(segment => {
|
|
466
|
+
console.log(`Segment: ${segment.name} (ID: ${segment.id})`);
|
|
467
|
+
console.log(`Type: ${segment.type}, Members: ${segment.member_count}`);
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
return response.segments;
|
|
471
|
+
} catch (error) {
|
|
472
|
+
console.error('Error fetching segments:', error);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Create a Segment
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
async function createSegment(listId, segmentName, conditions) {
|
|
481
|
+
try {
|
|
482
|
+
const response = await mailchimp.lists.createSegment(listId, {
|
|
483
|
+
name: segmentName,
|
|
484
|
+
static_segment: [],
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
console.log('Segment created:', response.id);
|
|
488
|
+
return response;
|
|
489
|
+
} catch (error) {
|
|
490
|
+
console.error('Error creating segment:', error);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Add Members to a Segment
|
|
496
|
+
|
|
497
|
+
```javascript
|
|
498
|
+
async function addMembersToSegment(listId, segmentId, emails) {
|
|
499
|
+
try {
|
|
500
|
+
const response = await mailchimp.lists.batchSegmentMembers(
|
|
501
|
+
listId,
|
|
502
|
+
segmentId,
|
|
503
|
+
{
|
|
504
|
+
members_to_add: emails,
|
|
505
|
+
}
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
console.log('Members added to segment:', response.members_added.length);
|
|
509
|
+
return response;
|
|
510
|
+
} catch (error) {
|
|
511
|
+
console.error('Error adding members to segment:', error);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Campaigns Management
|
|
517
|
+
|
|
518
|
+
### Get All Campaigns
|
|
519
|
+
|
|
520
|
+
```javascript
|
|
521
|
+
async function getAllCampaigns(count = 100) {
|
|
522
|
+
try {
|
|
523
|
+
const response = await mailchimp.campaigns.list({
|
|
524
|
+
count: count,
|
|
525
|
+
sort_field: 'create_time',
|
|
526
|
+
sort_dir: 'DESC',
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
console.log('Total campaigns:', response.total_items);
|
|
530
|
+
|
|
531
|
+
response.campaigns.forEach(campaign => {
|
|
532
|
+
console.log(`Campaign: ${campaign.settings.title}`);
|
|
533
|
+
console.log(`Status: ${campaign.status}, Type: ${campaign.type}`);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
return response.campaigns;
|
|
537
|
+
} catch (error) {
|
|
538
|
+
console.error('Error fetching campaigns:', error);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Create a Campaign
|
|
544
|
+
|
|
545
|
+
```javascript
|
|
546
|
+
async function createCampaign(listId, subject, fromName, replyTo) {
|
|
547
|
+
try {
|
|
548
|
+
const response = await mailchimp.campaigns.create({
|
|
549
|
+
type: 'regular',
|
|
550
|
+
recipients: {
|
|
551
|
+
list_id: listId,
|
|
552
|
+
},
|
|
553
|
+
settings: {
|
|
554
|
+
subject_line: subject,
|
|
555
|
+
title: subject,
|
|
556
|
+
from_name: fromName,
|
|
557
|
+
reply_to: replyTo,
|
|
558
|
+
},
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
console.log('Campaign created:', response.id);
|
|
562
|
+
return response;
|
|
563
|
+
} catch (error) {
|
|
564
|
+
console.error('Error creating campaign:', error);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Set Campaign Content
|
|
570
|
+
|
|
571
|
+
```javascript
|
|
572
|
+
async function setCampaignContent(campaignId, htmlContent) {
|
|
573
|
+
try {
|
|
574
|
+
const response = await mailchimp.campaigns.setContent(campaignId, {
|
|
575
|
+
html: htmlContent,
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
console.log('Campaign content set');
|
|
579
|
+
return response;
|
|
580
|
+
} catch (error) {
|
|
581
|
+
console.error('Error setting campaign content:', error);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### Send a Campaign
|
|
587
|
+
|
|
588
|
+
```javascript
|
|
589
|
+
async function sendCampaign(campaignId) {
|
|
590
|
+
try {
|
|
591
|
+
const response = await mailchimp.campaigns.send(campaignId);
|
|
592
|
+
console.log('Campaign sent successfully');
|
|
593
|
+
return response;
|
|
594
|
+
} catch (error) {
|
|
595
|
+
console.error('Error sending campaign:', error);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Complete Campaign Workflow
|
|
601
|
+
|
|
602
|
+
```javascript
|
|
603
|
+
async function createAndSendCampaign(listId, subject, htmlContent) {
|
|
604
|
+
try {
|
|
605
|
+
// 1. Create campaign
|
|
606
|
+
const campaign = await mailchimp.campaigns.create({
|
|
607
|
+
type: 'regular',
|
|
608
|
+
recipients: {
|
|
609
|
+
list_id: listId,
|
|
610
|
+
},
|
|
611
|
+
settings: {
|
|
612
|
+
subject_line: subject,
|
|
613
|
+
title: subject,
|
|
614
|
+
from_name: 'My Company',
|
|
615
|
+
reply_to: 'hello@mycompany.com',
|
|
616
|
+
},
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
console.log('Campaign created:', campaign.id);
|
|
620
|
+
|
|
621
|
+
// 2. Set content
|
|
622
|
+
await mailchimp.campaigns.setContent(campaign.id, {
|
|
623
|
+
html: htmlContent,
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
console.log('Campaign content set');
|
|
627
|
+
|
|
628
|
+
// 3. Send campaign
|
|
629
|
+
await mailchimp.campaigns.send(campaign.id);
|
|
630
|
+
|
|
631
|
+
console.log('Campaign sent successfully');
|
|
632
|
+
|
|
633
|
+
return campaign;
|
|
634
|
+
} catch (error) {
|
|
635
|
+
console.error('Error in campaign workflow:', error);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### Schedule a Campaign
|
|
641
|
+
|
|
642
|
+
```javascript
|
|
643
|
+
async function scheduleCampaign(campaignId, scheduleTime) {
|
|
644
|
+
try {
|
|
645
|
+
const response = await mailchimp.campaigns.schedule(campaignId, {
|
|
646
|
+
schedule_time: scheduleTime, // ISO 8601 format: "2024-12-31T10:00:00Z"
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
console.log('Campaign scheduled for:', scheduleTime);
|
|
650
|
+
return response;
|
|
651
|
+
} catch (error) {
|
|
652
|
+
console.error('Error scheduling campaign:', error);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Update Campaign Settings
|
|
658
|
+
|
|
659
|
+
```javascript
|
|
660
|
+
async function updateCampaign(campaignId, updates) {
|
|
661
|
+
try {
|
|
662
|
+
const response = await mailchimp.campaigns.update(campaignId, updates);
|
|
663
|
+
console.log('Campaign updated');
|
|
664
|
+
return response;
|
|
665
|
+
} catch (error) {
|
|
666
|
+
console.error('Error updating campaign:', error);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// Example usage
|
|
671
|
+
updateCampaign('campaign123', {
|
|
672
|
+
settings: {
|
|
673
|
+
subject_line: 'Updated Subject Line',
|
|
674
|
+
preview_text: 'Check out our latest updates!',
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### Delete a Campaign
|
|
680
|
+
|
|
681
|
+
```javascript
|
|
682
|
+
async function deleteCampaign(campaignId) {
|
|
683
|
+
try {
|
|
684
|
+
await mailchimp.campaigns.remove(campaignId);
|
|
685
|
+
console.log('Campaign deleted');
|
|
686
|
+
} catch (error) {
|
|
687
|
+
console.error('Error deleting campaign:', error);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## Templates Management
|
|
693
|
+
|
|
694
|
+
### Get All Templates
|
|
695
|
+
|
|
696
|
+
```javascript
|
|
697
|
+
async function getAllTemplates() {
|
|
698
|
+
try {
|
|
699
|
+
const response = await mailchimp.templates.list({
|
|
700
|
+
count: 100,
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
console.log('Total templates:', response.total_items);
|
|
704
|
+
|
|
705
|
+
response.templates.forEach(template => {
|
|
706
|
+
console.log(`Template: ${template.name} (ID: ${template.id})`);
|
|
707
|
+
console.log(`Type: ${template.type}, Category: ${template.category}`);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
return response.templates;
|
|
711
|
+
} catch (error) {
|
|
712
|
+
console.error('Error fetching templates:', error);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### Get Specific Template
|
|
718
|
+
|
|
719
|
+
```javascript
|
|
720
|
+
async function getTemplate(templateId) {
|
|
721
|
+
try {
|
|
722
|
+
const response = await mailchimp.templates.getTemplate(templateId);
|
|
723
|
+
console.log('Template:', response.name);
|
|
724
|
+
console.log('HTML:', response.html);
|
|
725
|
+
return response;
|
|
726
|
+
} catch (error) {
|
|
727
|
+
console.error('Error fetching template:', error);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### Create a Template
|
|
733
|
+
|
|
734
|
+
```javascript
|
|
735
|
+
async function createTemplate(name, htmlContent) {
|
|
736
|
+
try {
|
|
737
|
+
const response = await mailchimp.templates.create({
|
|
738
|
+
name: name,
|
|
739
|
+
html: htmlContent,
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
console.log('Template created:', response.id);
|
|
743
|
+
return response;
|
|
744
|
+
} catch (error) {
|
|
745
|
+
console.error('Error creating template:', error);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### Use Template in Campaign
|
|
751
|
+
|
|
752
|
+
```javascript
|
|
753
|
+
async function createCampaignFromTemplate(listId, templateId, subject) {
|
|
754
|
+
try {
|
|
755
|
+
const campaign = await mailchimp.campaigns.create({
|
|
756
|
+
type: 'regular',
|
|
757
|
+
recipients: {
|
|
758
|
+
list_id: listId,
|
|
759
|
+
},
|
|
760
|
+
settings: {
|
|
761
|
+
subject_line: subject,
|
|
762
|
+
title: subject,
|
|
763
|
+
from_name: 'My Company',
|
|
764
|
+
reply_to: 'hello@mycompany.com',
|
|
765
|
+
template_id: templateId,
|
|
766
|
+
},
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
console.log('Campaign created from template:', campaign.id);
|
|
770
|
+
return campaign;
|
|
771
|
+
} catch (error) {
|
|
772
|
+
console.error('Error creating campaign from template:', error);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
## Automation Workflows
|
|
778
|
+
|
|
779
|
+
### Get All Automations
|
|
780
|
+
|
|
781
|
+
```javascript
|
|
782
|
+
async function getAllAutomations() {
|
|
783
|
+
try {
|
|
784
|
+
const response = await mailchimp.automations.list({
|
|
785
|
+
count: 100,
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
console.log('Total automations:', response.total_items);
|
|
789
|
+
|
|
790
|
+
response.automations.forEach(automation => {
|
|
791
|
+
console.log(`Automation: ${automation.settings.title}`);
|
|
792
|
+
console.log(`Status: ${automation.status}, Recipients: ${automation.recipients.list_id}`);
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
return response.automations;
|
|
796
|
+
} catch (error) {
|
|
797
|
+
console.error('Error fetching automations:', error);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
### Get Specific Automation
|
|
803
|
+
|
|
804
|
+
```javascript
|
|
805
|
+
async function getAutomation(workflowId) {
|
|
806
|
+
try {
|
|
807
|
+
const response = await mailchimp.automations.get(workflowId);
|
|
808
|
+
console.log('Automation:', response.settings.title);
|
|
809
|
+
console.log('Status:', response.status);
|
|
810
|
+
console.log('Emails:', response.emails.length);
|
|
811
|
+
return response;
|
|
812
|
+
} catch (error) {
|
|
813
|
+
console.error('Error fetching automation:', error);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
### Pause an Automation
|
|
819
|
+
|
|
820
|
+
```javascript
|
|
821
|
+
async function pauseAutomation(workflowId) {
|
|
822
|
+
try {
|
|
823
|
+
await mailchimp.automations.pause(workflowId);
|
|
824
|
+
console.log('Automation paused');
|
|
825
|
+
} catch (error) {
|
|
826
|
+
console.error('Error pausing automation:', error);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
### Start an Automation
|
|
832
|
+
|
|
833
|
+
```javascript
|
|
834
|
+
async function startAutomation(workflowId) {
|
|
835
|
+
try {
|
|
836
|
+
await mailchimp.automations.start(workflowId);
|
|
837
|
+
console.log('Automation started');
|
|
838
|
+
} catch (error) {
|
|
839
|
+
console.error('Error starting automation:', error);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Add Subscriber to Automation Email Queue
|
|
845
|
+
|
|
846
|
+
```javascript
|
|
847
|
+
async function addSubscriberToAutomation(workflowId, workflowEmailId, email) {
|
|
848
|
+
try {
|
|
849
|
+
const response = await mailchimp.automations.addWorkflowEmailSubscriber(
|
|
850
|
+
workflowId,
|
|
851
|
+
workflowEmailId,
|
|
852
|
+
{
|
|
853
|
+
email_address: email,
|
|
854
|
+
}
|
|
855
|
+
);
|
|
856
|
+
|
|
857
|
+
console.log(`Added ${email} to automation queue`);
|
|
858
|
+
return response;
|
|
859
|
+
} catch (error) {
|
|
860
|
+
console.error('Error adding subscriber to automation:', error);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
## Reports and Analytics
|
|
866
|
+
|
|
867
|
+
### Get Campaign Reports
|
|
868
|
+
|
|
869
|
+
```javascript
|
|
870
|
+
async function getCampaignReport(campaignId) {
|
|
871
|
+
try {
|
|
872
|
+
const response = await mailchimp.reports.getCampaignReport(campaignId);
|
|
873
|
+
|
|
874
|
+
console.log('Campaign:', response.campaign_title);
|
|
875
|
+
console.log('Emails sent:', response.emails_sent);
|
|
876
|
+
console.log('Opens:', response.opens.opens_total);
|
|
877
|
+
console.log('Unique opens:', response.opens.unique_opens);
|
|
878
|
+
console.log('Open rate:', response.opens.open_rate);
|
|
879
|
+
console.log('Clicks:', response.clicks.clicks_total);
|
|
880
|
+
console.log('Unique clicks:', response.clicks.unique_clicks);
|
|
881
|
+
console.log('Click rate:', response.clicks.click_rate);
|
|
882
|
+
console.log('Unsubscribes:', response.unsubscribed);
|
|
883
|
+
|
|
884
|
+
return response;
|
|
885
|
+
} catch (error) {
|
|
886
|
+
console.error('Error fetching campaign report:', error);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
### Get All Campaign Reports
|
|
892
|
+
|
|
893
|
+
```javascript
|
|
894
|
+
async function getAllCampaignReports(count = 100) {
|
|
895
|
+
try {
|
|
896
|
+
const response = await mailchimp.reports.getAllCampaignReports({
|
|
897
|
+
count: count,
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
console.log('Total reports:', response.total_items);
|
|
901
|
+
|
|
902
|
+
response.reports.forEach(report => {
|
|
903
|
+
console.log(`Campaign: ${report.campaign_title}`);
|
|
904
|
+
console.log(`Open rate: ${report.opens.open_rate}%`);
|
|
905
|
+
console.log(`Click rate: ${report.clicks.click_rate}%`);
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
return response.reports;
|
|
909
|
+
} catch (error) {
|
|
910
|
+
console.error('Error fetching reports:', error);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### Get Email Activity for a Member
|
|
916
|
+
|
|
917
|
+
```javascript
|
|
918
|
+
const crypto = require('crypto');
|
|
919
|
+
|
|
920
|
+
async function getEmailActivity(campaignId, email) {
|
|
921
|
+
try {
|
|
922
|
+
const subscriberHash = crypto
|
|
923
|
+
.createHash('md5')
|
|
924
|
+
.update(email.toLowerCase())
|
|
925
|
+
.digest('hex');
|
|
926
|
+
|
|
927
|
+
const response = await mailchimp.reports.getEmailActivityForSubscriber(
|
|
928
|
+
campaignId,
|
|
929
|
+
subscriberHash
|
|
930
|
+
);
|
|
931
|
+
|
|
932
|
+
console.log(`Email activity for ${email}:`);
|
|
933
|
+
response.activity.forEach(activity => {
|
|
934
|
+
console.log(`${activity.action} at ${activity.timestamp}`);
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
return response;
|
|
938
|
+
} catch (error) {
|
|
939
|
+
console.error('Error fetching email activity:', error);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
### Get List Growth History
|
|
945
|
+
|
|
946
|
+
```javascript
|
|
947
|
+
async function getListGrowthHistory(listId) {
|
|
948
|
+
try {
|
|
949
|
+
const response = await mailchimp.lists.getListGrowthHistory(listId, {
|
|
950
|
+
count: 100,
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
console.log('Growth history for list:');
|
|
954
|
+
response.history.forEach(history => {
|
|
955
|
+
console.log(`Month: ${history.month}`);
|
|
956
|
+
console.log(`Subscribed: ${history.subscribed}, Unsubscribed: ${history.unsubscribed}`);
|
|
957
|
+
console.log(`Existing: ${history.existing}`);
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
return response.history;
|
|
961
|
+
} catch (error) {
|
|
962
|
+
console.error('Error fetching growth history:', error);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
## E-commerce Integration
|
|
968
|
+
|
|
969
|
+
### Add a Store
|
|
970
|
+
|
|
971
|
+
```javascript
|
|
972
|
+
async function addStore(listId, storeId, storeName, currencyCode) {
|
|
973
|
+
try {
|
|
974
|
+
const response = await mailchimp.ecommerce.addStore({
|
|
975
|
+
id: storeId,
|
|
976
|
+
list_id: listId,
|
|
977
|
+
name: storeName,
|
|
978
|
+
currency_code: currencyCode,
|
|
979
|
+
});
|
|
980
|
+
|
|
981
|
+
console.log('Store created:', response.id);
|
|
982
|
+
return response;
|
|
983
|
+
} catch (error) {
|
|
984
|
+
console.error('Error adding store:', error);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
### Get All Stores
|
|
990
|
+
|
|
991
|
+
```javascript
|
|
992
|
+
async function getAllStores() {
|
|
993
|
+
try {
|
|
994
|
+
const response = await mailchimp.ecommerce.getStores();
|
|
995
|
+
|
|
996
|
+
console.log('Total stores:', response.total_items);
|
|
997
|
+
|
|
998
|
+
response.stores.forEach(store => {
|
|
999
|
+
console.log(`Store: ${store.name} (ID: ${store.id})`);
|
|
1000
|
+
console.log(`Currency: ${store.currency_code}`);
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
return response.stores;
|
|
1004
|
+
} catch (error) {
|
|
1005
|
+
console.error('Error fetching stores:', error);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
### Add a Customer
|
|
1011
|
+
|
|
1012
|
+
```javascript
|
|
1013
|
+
async function addCustomer(storeId, customerId, email, firstName, lastName) {
|
|
1014
|
+
try {
|
|
1015
|
+
const response = await mailchimp.ecommerce.addStoreCustomer(storeId, {
|
|
1016
|
+
id: customerId,
|
|
1017
|
+
email_address: email,
|
|
1018
|
+
opt_in_status: true,
|
|
1019
|
+
first_name: firstName,
|
|
1020
|
+
last_name: lastName,
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
console.log('Customer added:', response.id);
|
|
1024
|
+
return response;
|
|
1025
|
+
} catch (error) {
|
|
1026
|
+
console.error('Error adding customer:', error);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
### Add a Product
|
|
1032
|
+
|
|
1033
|
+
```javascript
|
|
1034
|
+
async function addProduct(storeId, productId, title, price) {
|
|
1035
|
+
try {
|
|
1036
|
+
const response = await mailchimp.ecommerce.addStoreProduct(storeId, {
|
|
1037
|
+
id: productId,
|
|
1038
|
+
title: title,
|
|
1039
|
+
variants: [
|
|
1040
|
+
{
|
|
1041
|
+
id: `${productId}-variant-1`,
|
|
1042
|
+
title: 'Default Variant',
|
|
1043
|
+
price: price,
|
|
1044
|
+
},
|
|
1045
|
+
],
|
|
1046
|
+
});
|
|
1047
|
+
|
|
1048
|
+
console.log('Product added:', response.id);
|
|
1049
|
+
return response;
|
|
1050
|
+
} catch (error) {
|
|
1051
|
+
console.error('Error adding product:', error);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
### Add an Order
|
|
1057
|
+
|
|
1058
|
+
```javascript
|
|
1059
|
+
async function addOrder(storeId, orderId, customerId, lineItems, total) {
|
|
1060
|
+
try {
|
|
1061
|
+
const response = await mailchimp.ecommerce.addStoreOrder(storeId, {
|
|
1062
|
+
id: orderId,
|
|
1063
|
+
customer: {
|
|
1064
|
+
id: customerId,
|
|
1065
|
+
},
|
|
1066
|
+
lines: lineItems.map(item => ({
|
|
1067
|
+
id: item.id,
|
|
1068
|
+
product_id: item.productId,
|
|
1069
|
+
product_variant_id: item.variantId,
|
|
1070
|
+
quantity: item.quantity,
|
|
1071
|
+
price: item.price,
|
|
1072
|
+
})),
|
|
1073
|
+
currency_code: 'USD',
|
|
1074
|
+
order_total: total,
|
|
1075
|
+
processed_at_foreign: new Date().toISOString(),
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
console.log('Order added:', response.id);
|
|
1079
|
+
return response;
|
|
1080
|
+
} catch (error) {
|
|
1081
|
+
console.error('Error adding order:', error);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
// Example usage
|
|
1086
|
+
addOrder('store123', 'order456', 'customer789', [
|
|
1087
|
+
{
|
|
1088
|
+
id: 'line1',
|
|
1089
|
+
productId: 'prod1',
|
|
1090
|
+
variantId: 'prod1-variant-1',
|
|
1091
|
+
quantity: 2,
|
|
1092
|
+
price: 29.99,
|
|
1093
|
+
},
|
|
1094
|
+
], 59.98);
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
### Add a Cart
|
|
1098
|
+
|
|
1099
|
+
```javascript
|
|
1100
|
+
async function addCart(storeId, cartId, customerId, lineItems) {
|
|
1101
|
+
try {
|
|
1102
|
+
const response = await mailchimp.ecommerce.addStoreCart(storeId, {
|
|
1103
|
+
id: cartId,
|
|
1104
|
+
customer: {
|
|
1105
|
+
id: customerId,
|
|
1106
|
+
},
|
|
1107
|
+
lines: lineItems.map(item => ({
|
|
1108
|
+
id: item.id,
|
|
1109
|
+
product_id: item.productId,
|
|
1110
|
+
product_variant_id: item.variantId,
|
|
1111
|
+
quantity: item.quantity,
|
|
1112
|
+
price: item.price,
|
|
1113
|
+
})),
|
|
1114
|
+
currency_code: 'USD',
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
console.log('Cart added:', response.id);
|
|
1118
|
+
return response;
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
console.error('Error adding cart:', error);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
```
|
|
1124
|
+
|
|
1125
|
+
## Error Handling
|
|
1126
|
+
|
|
1127
|
+
### Comprehensive Error Handling
|
|
1128
|
+
|
|
1129
|
+
```javascript
|
|
1130
|
+
async function handleMailchimpRequest() {
|
|
1131
|
+
try {
|
|
1132
|
+
const response = await mailchimp.lists.getAllLists();
|
|
1133
|
+
return response;
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
console.error('Mailchimp API Error:', error);
|
|
1136
|
+
|
|
1137
|
+
if (error.status) {
|
|
1138
|
+
console.error('Status Code:', error.status);
|
|
1139
|
+
console.error('Error Message:', error.response?.body?.title);
|
|
1140
|
+
console.error('Error Detail:', error.response?.body?.detail);
|
|
1141
|
+
|
|
1142
|
+
switch (error.status) {
|
|
1143
|
+
case 401:
|
|
1144
|
+
console.error('Authentication failed. Check your API key.');
|
|
1145
|
+
break;
|
|
1146
|
+
case 403:
|
|
1147
|
+
console.error('Forbidden. Check your permissions.');
|
|
1148
|
+
break;
|
|
1149
|
+
case 404:
|
|
1150
|
+
console.error('Resource not found.');
|
|
1151
|
+
break;
|
|
1152
|
+
case 400:
|
|
1153
|
+
console.error('Bad request. Check your parameters.');
|
|
1154
|
+
if (error.response?.body?.errors) {
|
|
1155
|
+
console.error('Validation errors:', error.response.body.errors);
|
|
1156
|
+
}
|
|
1157
|
+
break;
|
|
1158
|
+
case 429:
|
|
1159
|
+
console.error('Rate limit exceeded. Wait before retrying.');
|
|
1160
|
+
break;
|
|
1161
|
+
case 500:
|
|
1162
|
+
console.error('Mailchimp server error. Try again later.');
|
|
1163
|
+
break;
|
|
1164
|
+
default:
|
|
1165
|
+
console.error('Unexpected error occurred.');
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
throw error;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
### Retry Logic for Rate Limiting
|
|
1175
|
+
|
|
1176
|
+
```javascript
|
|
1177
|
+
async function retryRequest(requestFn, maxRetries = 3, delay = 1000) {
|
|
1178
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
1179
|
+
try {
|
|
1180
|
+
return await requestFn();
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
if (error.status === 429 && i < maxRetries - 1) {
|
|
1183
|
+
console.log(`Rate limited. Retrying in ${delay}ms...`);
|
|
1184
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
1185
|
+
delay *= 2; // Exponential backoff
|
|
1186
|
+
} else {
|
|
1187
|
+
throw error;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// Example usage
|
|
1194
|
+
const result = await retryRequest(() => mailchimp.lists.getAllLists());
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
## Pagination
|
|
1198
|
+
|
|
1199
|
+
### Paginate Through Large Result Sets
|
|
1200
|
+
|
|
1201
|
+
```javascript
|
|
1202
|
+
async function getAllListMembersPaginated(listId) {
|
|
1203
|
+
let offset = 0;
|
|
1204
|
+
const count = 100;
|
|
1205
|
+
const allMembers = [];
|
|
1206
|
+
|
|
1207
|
+
while (true) {
|
|
1208
|
+
try {
|
|
1209
|
+
const response = await mailchimp.lists.getListMembersInfo(listId, {
|
|
1210
|
+
count: count,
|
|
1211
|
+
offset: offset,
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
allMembers.push(...response.members);
|
|
1215
|
+
|
|
1216
|
+
console.log(`Fetched ${offset + response.members.length} of ${response.total_items} members`);
|
|
1217
|
+
|
|
1218
|
+
if (response.members.length < count) {
|
|
1219
|
+
break; // No more results
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
offset += count;
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
console.error('Error during pagination:', error);
|
|
1225
|
+
break;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
return allMembers;
|
|
1230
|
+
}
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
## TypeScript Support
|
|
1234
|
+
|
|
1235
|
+
The SDK includes TypeScript definitions:
|
|
1236
|
+
|
|
1237
|
+
```typescript
|
|
1238
|
+
import mailchimp from '@mailchimp/mailchimp_marketing';
|
|
1239
|
+
|
|
1240
|
+
mailchimp.setConfig({
|
|
1241
|
+
apiKey: process.env.MAILCHIMP_API_KEY as string,
|
|
1242
|
+
server: process.env.MAILCHIMP_SERVER_PREFIX as string,
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
interface ListMember {
|
|
1246
|
+
email_address: string;
|
|
1247
|
+
status: 'subscribed' | 'unsubscribed' | 'cleaned' | 'pending';
|
|
1248
|
+
merge_fields: {
|
|
1249
|
+
FNAME: string;
|
|
1250
|
+
LNAME: string;
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
async function addTypedMember(listId: string, member: ListMember) {
|
|
1255
|
+
const response = await mailchimp.lists.addListMember(listId, member);
|
|
1256
|
+
return response;
|
|
1257
|
+
}
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
## Common Patterns
|
|
1261
|
+
|
|
1262
|
+
### Bulk Import Subscribers from CSV
|
|
1263
|
+
|
|
1264
|
+
```javascript
|
|
1265
|
+
const fs = require('fs');
|
|
1266
|
+
const csv = require('csv-parser');
|
|
1267
|
+
|
|
1268
|
+
async function importFromCSV(listId, csvFilePath) {
|
|
1269
|
+
const members = [];
|
|
1270
|
+
|
|
1271
|
+
return new Promise((resolve, reject) => {
|
|
1272
|
+
fs.createReadStream(csvFilePath)
|
|
1273
|
+
.pipe(csv())
|
|
1274
|
+
.on('data', (row) => {
|
|
1275
|
+
members.push({
|
|
1276
|
+
email_address: row.email,
|
|
1277
|
+
status: 'subscribed',
|
|
1278
|
+
merge_fields: {
|
|
1279
|
+
FNAME: row.first_name,
|
|
1280
|
+
LNAME: row.last_name,
|
|
1281
|
+
},
|
|
1282
|
+
});
|
|
1283
|
+
})
|
|
1284
|
+
.on('end', async () => {
|
|
1285
|
+
try {
|
|
1286
|
+
// Batch in groups of 500 (Mailchimp limit)
|
|
1287
|
+
const batchSize = 500;
|
|
1288
|
+
for (let i = 0; i < members.length; i += batchSize) {
|
|
1289
|
+
const batch = members.slice(i, i + batchSize);
|
|
1290
|
+
|
|
1291
|
+
const response = await mailchimp.lists.batchListMembers(listId, {
|
|
1292
|
+
members: batch,
|
|
1293
|
+
update_existing: true,
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
console.log(`Batch ${i / batchSize + 1}: ${response.new_members.length} added, ${response.updated_members.length} updated`);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
resolve();
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
reject(error);
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
### Send Welcome Email via Automation
|
|
1309
|
+
|
|
1310
|
+
```javascript
|
|
1311
|
+
async function setupWelcomeAutomation(listId) {
|
|
1312
|
+
try {
|
|
1313
|
+
// Create a basic automation trigger when someone subscribes
|
|
1314
|
+
const automation = await mailchimp.automations.create({
|
|
1315
|
+
recipients: {
|
|
1316
|
+
list_id: listId,
|
|
1317
|
+
},
|
|
1318
|
+
trigger_settings: {
|
|
1319
|
+
workflow_type: 'welcomeSeries',
|
|
1320
|
+
},
|
|
1321
|
+
settings: {
|
|
1322
|
+
title: 'Welcome Email Series',
|
|
1323
|
+
from_name: 'My Company',
|
|
1324
|
+
reply_to: 'hello@mycompany.com',
|
|
1325
|
+
},
|
|
1326
|
+
});
|
|
1327
|
+
|
|
1328
|
+
console.log('Welcome automation created:', automation.id);
|
|
1329
|
+
return automation;
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
console.error('Error setting up welcome automation:', error);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
### Segment Users by Engagement
|
|
1337
|
+
|
|
1338
|
+
```javascript
|
|
1339
|
+
async function createEngagementSegment(listId, segmentName) {
|
|
1340
|
+
try {
|
|
1341
|
+
const response = await mailchimp.lists.createSegment(listId, {
|
|
1342
|
+
name: segmentName,
|
|
1343
|
+
options: {
|
|
1344
|
+
match: 'all',
|
|
1345
|
+
conditions: [
|
|
1346
|
+
{
|
|
1347
|
+
condition_type: 'EmailClient',
|
|
1348
|
+
field: 'email_client',
|
|
1349
|
+
op: 'is',
|
|
1350
|
+
value: 'Gmail',
|
|
1351
|
+
},
|
|
1352
|
+
],
|
|
1353
|
+
},
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1356
|
+
console.log('Engagement segment created:', response.id);
|
|
1357
|
+
return response;
|
|
1358
|
+
} catch (error) {
|
|
1359
|
+
console.error('Error creating segment:', error);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
```
|
|
1363
|
+
|
|
1364
|
+
## Webhooks
|
|
1365
|
+
|
|
1366
|
+
### Process Webhook Events
|
|
1367
|
+
|
|
1368
|
+
```javascript
|
|
1369
|
+
const express = require('express');
|
|
1370
|
+
const crypto = require('crypto');
|
|
1371
|
+
|
|
1372
|
+
const app = express();
|
|
1373
|
+
app.use(express.json());
|
|
1374
|
+
|
|
1375
|
+
// Verify webhook signature
|
|
1376
|
+
function verifyWebhook(secret, body, signature) {
|
|
1377
|
+
const hash = crypto
|
|
1378
|
+
.createHmac('sha1', secret)
|
|
1379
|
+
.update(JSON.stringify(body))
|
|
1380
|
+
.digest('hex');
|
|
1381
|
+
|
|
1382
|
+
return hash === signature;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
app.post('/mailchimp-webhook', (req, res) => {
|
|
1386
|
+
const signature = req.headers['x-mailchimp-signature'];
|
|
1387
|
+
const webhookSecret = process.env.MAILCHIMP_WEBHOOK_SECRET;
|
|
1388
|
+
|
|
1389
|
+
if (!verifyWebhook(webhookSecret, req.body, signature)) {
|
|
1390
|
+
return res.status(401).send('Invalid signature');
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
const { type, data } = req.body;
|
|
1394
|
+
|
|
1395
|
+
switch (type) {
|
|
1396
|
+
case 'subscribe':
|
|
1397
|
+
console.log('New subscriber:', data.email);
|
|
1398
|
+
break;
|
|
1399
|
+
case 'unsubscribe':
|
|
1400
|
+
console.log('Unsubscribed:', data.email);
|
|
1401
|
+
break;
|
|
1402
|
+
case 'profile':
|
|
1403
|
+
console.log('Profile updated:', data.email);
|
|
1404
|
+
break;
|
|
1405
|
+
case 'campaign':
|
|
1406
|
+
console.log('Campaign event:', data);
|
|
1407
|
+
break;
|
|
1408
|
+
default:
|
|
1409
|
+
console.log('Unknown webhook type:', type);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
res.status(200).send('OK');
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
app.listen(3000, () => console.log('Webhook server running on port 3000'));
|
|
1416
|
+
```
|
|
1417
|
+
|
|
1418
|
+
## Notes
|
|
1419
|
+
|
|
1420
|
+
The Mailchimp Marketing Node.js SDK is auto-generated from the OpenAPI specification and provides comprehensive access to all Mailchimp Marketing API endpoints. Always use environment variables for API keys and server prefixes. The library supports both Basic Auth (API key) and OAuth2 authentication methods. Rate limits apply: 10 simultaneous connections per account and throttling based on your plan. Use batch operations when adding multiple members to optimize API usage.
|