@sendmailos/sdk 1.2.0 → 1.2.1

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 CHANGED
@@ -45,7 +45,7 @@ await client.emails.send({
45
45
  ### Emails
46
46
 
47
47
  ```typescript
48
- // Send transactional email
48
+ // Send transactional email (Single Brand)
49
49
  await client.emails.send({
50
50
  to: 'user@example.com',
51
51
  subject: 'Hello!',
@@ -54,6 +54,16 @@ await client.emails.send({
54
54
  fromEmail: 'hello@acme.com',
55
55
  });
56
56
 
57
+ // Send email (Multi-Brand / SaaS Platform)
58
+ // Workspace auto-detected from fromEmail domain - no extra params needed!
59
+ await platform.emails.send({
60
+ to: 'customer@example.com',
61
+ subject: 'Your order is ready!',
62
+ html: '<h1>Order Ready!</h1>',
63
+ fromName: 'Pizza Palace',
64
+ fromEmail: 'orders@pizzapalace.com', // ← Workspace auto-detected
65
+ });
66
+
57
67
  // Send with template
58
68
  await client.emails.sendTemplate({
59
69
  to: 'user@example.com',
@@ -65,24 +75,38 @@ await client.emails.sendTemplate({
65
75
  ### Subscribers
66
76
 
67
77
  ```typescript
68
- // Create subscriber
78
+ // Create subscriber (Single Brand)
69
79
  const { subscriber } = await client.subscribers.create({
70
80
  email: 'user@example.com',
71
81
  firstName: 'John',
72
82
  tags: ['newsletter', 'premium']
73
83
  });
74
84
 
85
+ // Create subscriber (Multi-Brand / SaaS Platform)
86
+ const { subscriber } = await platform.subscribers.create({
87
+ email: 'customer@example.com',
88
+ firstName: 'Jane',
89
+ domain: 'pizzapalace.com', // Required for multi-brand
90
+ tags: ['loyalty-member']
91
+ });
92
+
75
93
  // List subscribers
76
94
  const { subscribers, total } = await client.subscribers.list({
77
95
  limit: 50,
78
96
  offset: 0
79
97
  });
98
+
99
+ // List subscribers for a specific client (Multi-Brand)
100
+ const { subscribers } = await platform.subscribers.list({
101
+ domain: 'pizzapalace.com',
102
+ limit: 50
103
+ });
80
104
  ```
81
105
 
82
106
  ### Campaigns
83
107
 
84
108
  ```typescript
85
- // Send campaign
109
+ // Send campaign (Single Brand)
86
110
  await client.campaigns.send({
87
111
  name: 'Weekly Newsletter',
88
112
  subject: 'What\'s new this week',
@@ -91,17 +115,39 @@ await client.campaigns.send({
91
115
  html: '<h1>Hello {{first_name}}!</h1>',
92
116
  tags: ['newsletter'] // Filter by subscriber tags
93
117
  });
118
+
119
+ // Send campaign (Multi-Brand / SaaS Platform)
120
+ // Workspace auto-detected from fromEmail domain
121
+ await platform.campaigns.send({
122
+ name: 'Pizza Promo',
123
+ subject: 'New menu items!',
124
+ fromName: 'Pizza Palace',
125
+ fromEmail: 'promo@pizzapalace.com', // ← Workspace auto-detected
126
+ html: '<h1>Check out our new items!</h1>',
127
+ sourceDomains: ['pizzapalace.com'] // Only send to subscribers from this domain
128
+ });
94
129
  ```
95
130
 
96
131
  ### Domains
97
132
 
98
133
  ```typescript
99
- // Add sending domain
134
+ // Add sending domain (Single Brand)
100
135
  const { domain } = await client.domains.create({
101
136
  domain: 'yourcompany.com'
102
137
  });
103
138
 
104
139
  console.log('DNS Records to add:', domain.dnsRecords);
140
+
141
+ // Add client domain (Multi-Brand / SaaS Platform)
142
+ // Show these DNS records to your client in your UI
143
+ const { dns_records, domain_id } = await platform.domains.create({
144
+ domain: 'pizzapalace.com'
145
+ });
146
+
147
+ // After client verifies DNS:
148
+ // ✓ Domain status becomes "verified"
149
+ // ✓ Workspace is AUTO-CREATED for this domain
150
+ // ✓ You can now send emails from @pizzapalace.com
105
151
  ```
106
152
 
107
153
  ## Organization & Industries
@@ -131,27 +177,97 @@ console.log(INDUSTRIES);
131
177
 
132
178
  Hotels, Restaurants, Gyms, Travel Agencies, Real Estate, Schools, E-commerce, Dentists, Car Dealerships, Events, Beauty Salons, Law Firms, Non-Profits, SaaS, Recruitment, Insurance, Online Courses, Municipalities, Personal Trainers, Influencers, Doctors/Clinics, Nightclubs, Coworking, Wedding Planners, Art Galleries, Car Rentals, Podcasters, Consultants, Bakeries, Veterinarians, Airbnb Hosts, Accountants, Developers, Musicians, Spas, Bookstores, Cleaning Services, Churches, Graphic Designers, Coffee Shops, Florists, Political Campaigns, Libraries, Taxis/Limos, Home Inspectors, Photographers, Universities, Fashion, Nutritionists, Startups
133
179
 
134
- ## Agency Workspaces
180
+ ## Account Types
181
+
182
+ ### Single Brand (Business)
183
+
184
+ For companies sending emails from their own domain. Simple setup, no workspaces needed.
185
+
186
+ ```typescript
187
+ const client = new SendMailOS('sk_live_your_api_key');
188
+
189
+ await client.emails.send({
190
+ to: 'customer@example.com',
191
+ fromEmail: 'hello@yourcompany.com',
192
+ subject: 'Welcome!',
193
+ html: '<h1>Hello!</h1>'
194
+ });
195
+ ```
196
+
197
+ ### Multi-Brand / SaaS Platform
135
198
 
136
- Agencies can manage multiple clients from one account, each with isolated data.
199
+ For agencies or SaaS platforms managing multiple clients. Each client gets their own workspace with isolated data.
200
+
201
+ ```typescript
202
+ // Your platform's master API key
203
+ const platform = new SendMailOS('sk_live_platform_key');
204
+
205
+ // 1. Client signs up → Register their domain
206
+ const { dns_records } = await platform.domains.create({
207
+ domain: 'pizzapalace.com'
208
+ });
209
+ // Show dns_records to client in your UI
210
+
211
+ // 2. Domain verified → Workspace auto-created!
212
+ // (No manual workspace creation needed)
213
+
214
+ // 3. Send emails → Workspace auto-detected from fromEmail
215
+ await platform.emails.send({
216
+ to: 'customer@example.com',
217
+ fromEmail: 'orders@pizzapalace.com', // ← Workspace detected automatically!
218
+ fromName: 'Pizza Palace',
219
+ subject: 'Your order is ready!',
220
+ html: '<h1>Order Ready!</h1>'
221
+ });
222
+
223
+ // 4. Add subscribers → Use domain param
224
+ await platform.subscribers.create({
225
+ email: 'customer@example.com',
226
+ domain: 'pizzapalace.com' // Required for multi-brand
227
+ });
228
+
229
+ // 5. List subscribers for a specific client
230
+ const { subscribers } = await platform.subscribers.list({
231
+ domain: 'pizzapalace.com'
232
+ });
233
+
234
+ // 6. Send campaign → Workspace auto-detected
235
+ await platform.campaigns.send({
236
+ subject: 'New Menu Items!',
237
+ fromName: 'Pizza Palace',
238
+ fromEmail: 'promo@pizzapalace.com', // ← Auto-detected
239
+ html: '<h1>Check out our new menu!</h1>'
240
+ });
241
+ ```
242
+
243
+ ### How Workspace Detection Works
244
+
245
+ | Action | How workspace is identified |
246
+ |--------|----------------------------|
247
+ | Register domain | Creates domain record (pending) |
248
+ | Domain verified | **Workspace auto-created** |
249
+ | Send email | Auto-detect from `fromEmail` domain |
250
+ | Send campaign | Auto-detect from `fromEmail` domain |
251
+ | Add subscriber | From `domain` parameter |
252
+ | List subscribers | From `domain` parameter |
253
+
254
+ **One verified domain = One workspace.** Simple.
255
+
256
+ ## Agency Workspaces (Advanced)
257
+
258
+ For more control, you can manually manage workspaces:
137
259
 
138
260
  ```typescript
139
261
  // Convert to agency account first
140
262
  await client.organization.convertToAgency();
141
263
 
142
- // Create client workspaces
264
+ // Create client workspaces manually
143
265
  const pizzaPlace = await client.workspaces.create({
144
266
  name: 'Pizza Palace',
145
267
  industry: 'restaurants',
146
268
  import_templates: true // Auto-import restaurant templates
147
269
  });
148
270
 
149
- const gym = await client.workspaces.create({
150
- name: 'FitLife Gym',
151
- industry: 'gyms',
152
- import_templates: true
153
- });
154
-
155
271
  // List all clients
156
272
  const { workspaces } = await client.workspaces.list();
157
273
  for (const ws of workspaces) {
@@ -167,6 +283,174 @@ console.log(details.stats);
167
283
  await client.workspaces.inviteClient(pizzaPlace.id, 'owner@pizzapalace.com');
168
284
  ```
169
285
 
286
+ ## Workflows
287
+
288
+ Automate email sequences with workflows. Create them via API, build the steps in your UI, then trigger them programmatically.
289
+
290
+ ### Workflow Lifecycle
291
+
292
+ ```
293
+ 1. Create workflow (draft)
294
+ 2. Add nodes & edges (build the flow)
295
+ 3. Activate workflow (start accepting triggers)
296
+ 4. Trigger for subscribers (via API or events)
297
+ ```
298
+
299
+ ### Create & Manage Workflows
300
+
301
+ ```typescript
302
+ // Create a workflow for a client (Multi-Brand)
303
+ const { data } = await platform.workflows.create({
304
+ name: 'Welcome Sequence',
305
+ domain: 'pizzapalace.com', // Auto-detect workspace
306
+ trigger: { type: 'api' } // Triggered via API
307
+ });
308
+
309
+ const workflowId = data.workflow.id;
310
+
311
+ // List workflows
312
+ const { data: list } = await platform.workflows.list({ domain: 'pizzapalace.com' });
313
+
314
+ // Get workflow with nodes/edges
315
+ const { data: workflow } = await platform.workflows.get(workflowId);
316
+
317
+ // Delete workflow
318
+ await platform.workflows.delete(workflowId);
319
+ ```
320
+
321
+ ### Build Workflow Steps
322
+
323
+ Update a workflow with nodes (steps) and edges (connections):
324
+
325
+ ```typescript
326
+ await platform.workflows.update(workflowId, {
327
+ nodes: [
328
+ {
329
+ id: 'trigger-1',
330
+ type: 'trigger',
331
+ data: { triggerType: 'api' }
332
+ },
333
+ {
334
+ id: 'email-1',
335
+ type: 'email',
336
+ data: {
337
+ subject: 'Welcome to {{restaurantName}}!',
338
+ templateId: 'tmpl_welcome'
339
+ }
340
+ },
341
+ {
342
+ id: 'delay-1',
343
+ type: 'delay',
344
+ data: { duration: 3, unit: 'days' }
345
+ },
346
+ {
347
+ id: 'email-2',
348
+ type: 'email',
349
+ data: {
350
+ subject: 'Your first order discount',
351
+ templateId: 'tmpl_promo'
352
+ }
353
+ }
354
+ ],
355
+ edges: [
356
+ { id: 'e1', source: 'trigger-1', target: 'email-1' },
357
+ { id: 'e2', source: 'email-1', target: 'delay-1' },
358
+ { id: 'e3', source: 'delay-1', target: 'email-2' }
359
+ ]
360
+ });
361
+ ```
362
+
363
+ ### Node Types
364
+
365
+ | Type | Description | Data Fields |
366
+ |------|-------------|-------------|
367
+ | `trigger` | Entry point | `triggerType` |
368
+ | `email` | Send email | `subject`, `templateId`, `fromName`, `fromEmail` |
369
+ | `delay` | Wait period | `duration`, `unit` (minutes/hours/days) |
370
+ | `condition` | Branch logic | `field`, `operator`, `value` |
371
+ | `tag` | Add/remove tags | `action` (add/remove), `tags` |
372
+ | `http` | Call webhook | `url`, `method`, `headers`, `body` |
373
+ | `wait_for_event` | Wait for event | `eventName`, `timeout` |
374
+ | `unsubscribe` | Unsubscribe user | - |
375
+ | `exit` | End workflow | - |
376
+
377
+ ### Activate & Pause
378
+
379
+ ```typescript
380
+ // Activate workflow (start accepting triggers)
381
+ await platform.workflows.activate(workflowId);
382
+
383
+ // Pause workflow (stop new triggers, existing runs continue)
384
+ await platform.workflows.pause(workflowId);
385
+ ```
386
+
387
+ ### Trigger Workflows
388
+
389
+ ```typescript
390
+ // When a customer signs up at the restaurant
391
+ await platform.workflows.trigger(workflowId, {
392
+ email: 'customer@example.com',
393
+ data: {
394
+ firstName: 'John',
395
+ restaurantName: 'Pizza Palace',
396
+ signupSource: 'website'
397
+ }
398
+ });
399
+ ```
400
+
401
+ ### Wait for Events
402
+
403
+ Workflows can pause and wait for specific events:
404
+
405
+ ```typescript
406
+ // Workflow has a "wait_for_event: purchase_completed" node
407
+ // When customer makes a purchase, send the event:
408
+ await platform.workflows.sendEvent({
409
+ event: 'purchase_completed',
410
+ email: 'customer@example.com',
411
+ data: { orderTotal: 45.99 }
412
+ });
413
+ // The workflow resumes from where it was waiting
414
+ ```
415
+
416
+ ### Example: Restaurant Welcome Flow
417
+
418
+ ```typescript
419
+ // 1. Create workflow
420
+ const { data } = await platform.workflows.create({
421
+ name: 'New Customer Welcome',
422
+ domain: 'pizzapalace.com'
423
+ });
424
+
425
+ // 2. Build the flow
426
+ await platform.workflows.update(data.workflow.id, {
427
+ nodes: [
428
+ { id: '1', type: 'trigger', data: { triggerType: 'api' } },
429
+ { id: '2', type: 'email', data: { subject: 'Welcome!', templateId: 'tmpl_welcome' } },
430
+ { id: '3', type: 'delay', data: { duration: 2, unit: 'days' } },
431
+ { id: '4', type: 'condition', data: { field: 'has_ordered', operator: 'eq', value: true } },
432
+ { id: '5', type: 'email', data: { subject: 'Thanks for ordering!', templateId: 'tmpl_thanks' } },
433
+ { id: '6', type: 'email', data: { subject: '10% off your first order', templateId: 'tmpl_promo' } }
434
+ ],
435
+ edges: [
436
+ { id: 'e1', source: '1', target: '2' },
437
+ { id: 'e2', source: '2', target: '3' },
438
+ { id: 'e3', source: '3', target: '4' },
439
+ { id: 'e4', source: '4', target: '5', sourceHandle: 'yes' },
440
+ { id: 'e5', source: '4', target: '6', sourceHandle: 'no' }
441
+ ]
442
+ });
443
+
444
+ // 3. Activate
445
+ await platform.workflows.activate(data.workflow.id);
446
+
447
+ // 4. Trigger when new customer signs up
448
+ await platform.workflows.trigger(data.workflow.id, {
449
+ email: 'newcustomer@gmail.com',
450
+ data: { firstName: 'Jane', restaurantName: 'Pizza Palace' }
451
+ });
452
+ ```
453
+
170
454
  ## Pixel Tracking
171
455
 
172
456
  Track website visitors and connect their behavior to email campaigns.