migma 1.3.2 → 1.3.4
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 +171 -22
- package/dist/index.d.mts +240 -61
- package/dist/index.d.ts +240 -61
- package/dist/index.js +123 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +123 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ const { data: email } = await migma.emails.generateAndWait({
|
|
|
36
36
|
if (email?.status === 'completed') {
|
|
37
37
|
console.log('Subject:', email.result.subject);
|
|
38
38
|
console.log('HTML:', email.result.html); // primary email HTML
|
|
39
|
-
console.log('
|
|
39
|
+
console.log('Email ID:', email.result.emails[0].emailId);
|
|
40
40
|
}
|
|
41
41
|
```
|
|
42
42
|
|
|
@@ -66,20 +66,20 @@ const { data: email } = await migma.emails.generateAndWait({
|
|
|
66
66
|
|
|
67
67
|
if (!email?.result) throw new Error('Email generation failed');
|
|
68
68
|
|
|
69
|
-
// 3. Send it —
|
|
69
|
+
// 3. Send it — emailId works for single emails and series slots
|
|
70
70
|
const selectedEmail = email.result.emails[0];
|
|
71
|
-
if (!selectedEmail.
|
|
71
|
+
if (!selectedEmail.emailId) throw new Error('No emailId returned');
|
|
72
72
|
await migma.sending.send({
|
|
73
73
|
recipientType: 'email',
|
|
74
74
|
recipientEmail: 'sarah@example.com',
|
|
75
75
|
from: 'hello@yourcompany.migma.email',
|
|
76
76
|
fromName: 'Your Company',
|
|
77
77
|
subject: selectedEmail.subject,
|
|
78
|
-
|
|
78
|
+
emailId: selectedEmail.emailId,
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
// conversationId also works for single-email conversations.
|
|
82
|
-
// For multi-slot emails or series, use result.emails[].
|
|
82
|
+
// For multi-slot emails or series, use result.emails[].emailId.
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
[Full OpenClaw tutorial](https://docs.migma.ai/tutorials/send-emails-from-openclaw)
|
|
@@ -126,6 +126,7 @@ Every method returns `{ data, error }` instead of throwing. TypeScript narrows t
|
|
|
126
126
|
```typescript
|
|
127
127
|
const { data, error } = await migma.contacts.create({
|
|
128
128
|
email: 'john@example.com',
|
|
129
|
+
status: 'subscribed', // only for contacts with marketing consent
|
|
129
130
|
projectId: 'proj_abc123',
|
|
130
131
|
});
|
|
131
132
|
|
|
@@ -206,7 +207,7 @@ const { data: contact } = await migma.contacts.create({
|
|
|
206
207
|
// List with filters
|
|
207
208
|
const { data: contacts } = await migma.contacts.list({
|
|
208
209
|
projectId: 'proj_abc123',
|
|
209
|
-
status: '
|
|
210
|
+
status: 'subscribed',
|
|
210
211
|
tags: 'newsletter',
|
|
211
212
|
limit: 50,
|
|
212
213
|
});
|
|
@@ -219,6 +220,19 @@ const { data: result } = await migma.contacts.bulkImport({
|
|
|
219
220
|
],
|
|
220
221
|
projectId: 'proj_abc123',
|
|
221
222
|
});
|
|
223
|
+
|
|
224
|
+
// Batch delete by email (up to 1000; unmatched emails come back in notFound)
|
|
225
|
+
const { data: deletion } = await migma.contacts.bulkDeleteByEmail({
|
|
226
|
+
emails: ['a@example.com', 'b@example.com'],
|
|
227
|
+
projectId: 'proj_abc123',
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Safe retries: pass an Idempotency-Key so a retried write never duplicates.
|
|
231
|
+
// Same key + same body within 24h replays the original response.
|
|
232
|
+
await migma.contacts.create(
|
|
233
|
+
{ email: 'jane@example.com', projectId: 'proj_abc123' },
|
|
234
|
+
{ idempotencyKey: 'signup-jane@example.com-1779292800' },
|
|
235
|
+
);
|
|
222
236
|
```
|
|
223
237
|
|
|
224
238
|
[Contacts API Reference](https://docs.migma.ai/api-reference/contacts/get-contact)
|
|
@@ -228,14 +242,14 @@ const { data: result } = await migma.contacts.bulkImport({
|
|
|
228
242
|
Send to a single recipient, segment, tag, or full audience.
|
|
229
243
|
|
|
230
244
|
```typescript
|
|
231
|
-
// Send a generated email by
|
|
245
|
+
// Send a generated email by emailId
|
|
232
246
|
await migma.sending.send({
|
|
233
247
|
recipientType: 'email',
|
|
234
248
|
recipientEmail: 'user@example.com',
|
|
235
249
|
from: 'hello@yourdomain.com',
|
|
236
250
|
fromName: 'Your Company',
|
|
237
251
|
subject: 'Welcome!',
|
|
238
|
-
|
|
252
|
+
emailId: 'email_abc123',
|
|
239
253
|
});
|
|
240
254
|
|
|
241
255
|
// Single-email conversations can also be sent by conversationId.
|
|
@@ -255,7 +269,7 @@ await migma.sending.send({
|
|
|
255
269
|
from: 'hello@yourdomain.com',
|
|
256
270
|
fromName: 'Your Company',
|
|
257
271
|
subject: 'Big Announcement',
|
|
258
|
-
|
|
272
|
+
emailId: 'email_abc123',
|
|
259
273
|
});
|
|
260
274
|
|
|
261
275
|
// Single sends are automatically transactional — no flag needed
|
|
@@ -266,7 +280,7 @@ await migma.sending.send({
|
|
|
266
280
|
from: 'noreply@yourdomain.com',
|
|
267
281
|
fromName: 'Your Company',
|
|
268
282
|
subject: 'Your subscription renews tomorrow',
|
|
269
|
-
|
|
283
|
+
emailId: 'email_abc123',
|
|
270
284
|
transactional: true,
|
|
271
285
|
});
|
|
272
286
|
```
|
|
@@ -275,7 +289,7 @@ await migma.sending.send({
|
|
|
275
289
|
|
|
276
290
|
### Generated Series and Editing
|
|
277
291
|
|
|
278
|
-
Generate a series with `count`, then use each email's `
|
|
292
|
+
Generate a series with `count`, then use each email's `emailId` to fetch, prompt-edit, or send one email.
|
|
279
293
|
|
|
280
294
|
```typescript
|
|
281
295
|
const { data: series } = await migma.emails.generateAndWait({
|
|
@@ -285,21 +299,135 @@ const { data: series } = await migma.emails.generateAndWait({
|
|
|
285
299
|
});
|
|
286
300
|
|
|
287
301
|
for (const generated of series?.result?.emails ?? []) {
|
|
288
|
-
console.log(generated.slot, generated.
|
|
302
|
+
console.log(generated.slot, generated.emailId, generated.html);
|
|
303
|
+
console.log(generated.screenshotUrl);
|
|
289
304
|
}
|
|
290
305
|
|
|
291
|
-
const { data: email } = await migma.emails.get('
|
|
292
|
-
|
|
306
|
+
const { data: email } = await migma.emails.get('email_abc123');
|
|
307
|
+
console.log(email?.html);
|
|
308
|
+
|
|
309
|
+
await migma.emails.edit('email_abc123', {
|
|
310
|
+
prompt: 'Change the CTA from "Start now" to "Start your trial"',
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Campaigns
|
|
315
|
+
|
|
316
|
+
Create a campaign from a generated email, send or schedule it, then read its
|
|
317
|
+
engagement stats and per-recipient logs.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// Create from a generated email
|
|
321
|
+
const { data: campaign } = await migma.campaigns.create({
|
|
322
|
+
projectId: 'proj_abc123',
|
|
323
|
+
name: 'Spring Launch',
|
|
324
|
+
conversationId: 'conv_abc123',
|
|
325
|
+
emailId: 'email_abc123',
|
|
326
|
+
subject: 'Spring is here',
|
|
327
|
+
from: 'hello@yourdomain.com',
|
|
328
|
+
fromName: 'Your Brand',
|
|
329
|
+
recipientType: 'audience',
|
|
330
|
+
recipientId: 'aud_abc123',
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Send now (idempotency key recommended — see below)
|
|
334
|
+
await migma.campaigns.send(campaign.id, {
|
|
335
|
+
idempotencyKey: `campaign-send-${campaign.id}`,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Or schedule for later
|
|
339
|
+
await migma.campaigns.schedule(
|
|
340
|
+
campaign.id,
|
|
341
|
+
{ scheduledAt: '2026-07-01T15:00:00Z', scheduledTimezone: 'America/New_York' },
|
|
342
|
+
{ idempotencyKey: `campaign-send-${campaign.id}` },
|
|
343
|
+
);
|
|
293
344
|
|
|
294
|
-
|
|
295
|
-
|
|
345
|
+
// Aggregated engagement metrics (cached, may be slightly stale)
|
|
346
|
+
const { data: stats } = await migma.campaigns.stats(campaign.id);
|
|
347
|
+
console.log(stats?.openRate, stats?.clickRate, stats?.lastUpdated);
|
|
348
|
+
|
|
349
|
+
// Per-recipient logs, cursor-paginated and optionally filtered by status
|
|
350
|
+
const { data: logs } = await migma.campaigns.logs(campaign.id, {
|
|
351
|
+
status: 'opened',
|
|
352
|
+
limit: 50,
|
|
296
353
|
});
|
|
354
|
+
for (const row of logs?.emails ?? []) {
|
|
355
|
+
console.log(row.to_email, row.status, row.opened_at);
|
|
356
|
+
}
|
|
357
|
+
if (logs?.hasMore) {
|
|
358
|
+
await migma.campaigns.logs(campaign.id, { cursor: logs.nextCursor ?? undefined });
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Campaign stats are sourced from the email tracking worker and cached on the
|
|
363
|
+
campaign, so they can lag live activity. `botOpens`, `botClicks`, and `mppOpens`
|
|
364
|
+
reflect Apple Mail Privacy Protection and bot detection when that data is
|
|
365
|
+
available. Log rows come straight from the tracking store, so their field names
|
|
366
|
+
are `snake_case` (`to_email`, `opened_at`, `bounce_type`) unlike the rest of the
|
|
367
|
+
API.
|
|
297
368
|
|
|
298
|
-
|
|
299
|
-
|
|
369
|
+
[Campaigns Guide](https://docs.migma.ai/campaigns/overview)
|
|
370
|
+
|
|
371
|
+
### Idempotency
|
|
372
|
+
|
|
373
|
+
Write methods accept an optional trailing `CallOptions` argument carrying an
|
|
374
|
+
`idempotencyKey`. The key is sent as the `Idempotency-Key` header (max 100
|
|
375
|
+
characters) and is scoped to your API key for 24 hours:
|
|
376
|
+
|
|
377
|
+
- **Same key + same body** within 24h replays the original response (the server
|
|
378
|
+
marks the replay with an `Idempotent-Replayed: true` header).
|
|
379
|
+
- **Same key + different body** returns `409 IDEMPOTENCY_CONFLICT`.
|
|
380
|
+
- `429` and `5xx` responses are never cached, so they stay safe to retry — and
|
|
381
|
+
the SDK reuses your key across its own automatic retries, so a retried call
|
|
382
|
+
never duplicates.
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// Sending — key on the recipient + send time
|
|
386
|
+
await migma.sending.send(
|
|
387
|
+
{
|
|
388
|
+
recipientType: 'email',
|
|
389
|
+
recipientEmail: 'user@example.com',
|
|
390
|
+
from: 'hello@yourdomain.com',
|
|
391
|
+
fromName: 'Your Brand',
|
|
392
|
+
subject: 'Welcome!',
|
|
393
|
+
emailId: 'email_abc123',
|
|
394
|
+
},
|
|
395
|
+
{ idempotencyKey: 'send-email_abc123-user@example.com-now' },
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Campaign send — one key per campaign send
|
|
399
|
+
await migma.campaigns.send('camp_abc123', {
|
|
400
|
+
idempotencyKey: 'campaign-send-camp_abc123',
|
|
300
401
|
});
|
|
402
|
+
|
|
403
|
+
// Email generation — key on project + the turn/prompt
|
|
404
|
+
await migma.emails.generate(
|
|
405
|
+
{ projectId: 'proj_abc123', prompt: 'Welcome email' },
|
|
406
|
+
{ idempotencyKey: 'email-gen-proj_abc123-welcome' },
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
// Contact add — key on the email
|
|
410
|
+
await migma.contacts.create(
|
|
411
|
+
{ email: 'jane@example.com', projectId: 'proj_abc123' },
|
|
412
|
+
{ idempotencyKey: 'contact-jane@example.com' },
|
|
413
|
+
);
|
|
301
414
|
```
|
|
302
415
|
|
|
416
|
+
**Choose a deterministic key** so the same logical operation produces the same
|
|
417
|
+
key on every attempt:
|
|
418
|
+
|
|
419
|
+
- send: `send-<emailId>-<recipientId|to>-<scheduledAt|"now">`
|
|
420
|
+
- campaign send: `campaign-send-<campaignId>`
|
|
421
|
+
- email generate: `email-gen-<projectId>-<turnOrPromptHash>`
|
|
422
|
+
- contact add: `contact-<email>`
|
|
423
|
+
|
|
424
|
+
**Anti-patterns to avoid:**
|
|
425
|
+
|
|
426
|
+
- Don't generate the key with `uuid()` or `Date.now()` per call — a fresh key
|
|
427
|
+
every attempt defeats deduplication across retries and process restarts.
|
|
428
|
+
- Don't hash the request body to build the key — identical retries you *want*
|
|
429
|
+
deduplicated would each get a different key, and you lose the conflict signal.
|
|
430
|
+
|
|
303
431
|
### Email Validation
|
|
304
432
|
|
|
305
433
|
Run preflight checks — compatibility, links, spelling, and deliverability.
|
|
@@ -377,6 +505,14 @@ const { data: avail } = await migma.domains.checkAvailability('mycompany');
|
|
|
377
505
|
if (avail.available) {
|
|
378
506
|
await migma.domains.createManaged({ prefix: 'mycompany' });
|
|
379
507
|
}
|
|
508
|
+
|
|
509
|
+
// Provision a transactional stream (notify.example.com) to isolate
|
|
510
|
+
// transactional reputation from marketing, then publish the returned DNS records
|
|
511
|
+
await migma.domains.provisionStream({ rootDomain: 'example.com', stream: 'transactional' });
|
|
512
|
+
|
|
513
|
+
// Or provision both streams (send. marketing + notify. transactional) in one call
|
|
514
|
+
const { data } = await migma.domains.setup({ rootDomain: 'example.com' });
|
|
515
|
+
// data.marketing, data.transactional
|
|
380
516
|
```
|
|
381
517
|
|
|
382
518
|
[Domains API Reference](https://docs.migma.ai/api-reference/domains/list-domains)
|
|
@@ -394,7 +530,19 @@ const { data: tag } = await migma.tags.create({
|
|
|
394
530
|
// Segments
|
|
395
531
|
const { data: segment } = await migma.segments.create({
|
|
396
532
|
name: 'Active US Customers',
|
|
397
|
-
filters: {
|
|
533
|
+
filters: {
|
|
534
|
+
status: 'subscribed',
|
|
535
|
+
fields: [{ key: 'country', mode: 'is', values: ['US'] }],
|
|
536
|
+
activity: [{ action: 'opened', channel: 'email', mode: 'within', unit: 'days', amount: 30 }],
|
|
537
|
+
},
|
|
538
|
+
projectId: 'proj_abc123',
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
const { data: campaignSegment } = await migma.segments.create({
|
|
542
|
+
name: 'Campaign openers',
|
|
543
|
+
filters: {
|
|
544
|
+
activity: [{ action: 'opened', channel: 'email', mode: 'within', unit: 'days', amount: 14, campaignId: 'cmp_123' }],
|
|
545
|
+
},
|
|
398
546
|
projectId: 'proj_abc123',
|
|
399
547
|
});
|
|
400
548
|
|
|
@@ -457,12 +605,13 @@ await migma.images.updateLogos('proj_abc123', {
|
|
|
457
605
|
| `migma.segments` | `create` `list` `get` `update` `remove` | [Segments](https://docs.migma.ai/api-reference/audiences/list-audiences) |
|
|
458
606
|
| `migma.topics` | `create` `list` `get` `update` `remove` `subscribe` `unsubscribe` | [Topics](https://docs.migma.ai/api-reference/topics/list-topics) |
|
|
459
607
|
| `migma.sending` | `send` `getBatchStatus` | [Sending](https://docs.migma.ai/api-reference/sending/send-email) |
|
|
460
|
-
| `migma.projects` | `list` `get` `import` `getImportStatus` `retryImport` `importAndWait` | [Projects](https://docs.migma.ai/api-reference/projects/list-projects) |
|
|
461
|
-
| `migma.emails` | `generate` `getGenerationStatus` `generateAndWait` `sendTest` | [Email Generation](https://docs.migma.ai/api-reference/email/generate-email-async) |
|
|
608
|
+
| `migma.projects` | `list` `get` `import` `getImportStatus` `retryImport` `fieldCatalog` `importAndWait` | [Projects](https://docs.migma.ai/api-reference/projects/list-projects) |
|
|
609
|
+
| `migma.emails` | `generate` `getGenerationStatus` `generateAndWait` `sendTest` `get` `edit` | [Email Generation](https://docs.migma.ai/api-reference/email/generate-email-async) |
|
|
610
|
+
| `migma.campaigns` | `list` `create` `get` `send` `schedule` `cancel` `stats` `logs` `archive` `unarchive` | [Campaigns](https://docs.migma.ai/campaigns/overview) |
|
|
462
611
|
| `migma.validation` | `all` `compatibility` `links` `spelling` `deliverability` | [Validation](https://docs.migma.ai/api-reference/email-validation/run-all-validation-checks) |
|
|
463
612
|
| `migma.previews` | `create` `get` `getStatus` `getDevice` `getSupportedDevices` `createAndWait` | [Previews](https://docs.migma.ai/api-reference/email-previews/create-email-preview) |
|
|
464
613
|
| `migma.export` | `getFormats` `getStatus` `html` `mjml` `pdf` `klaviyo` `mailchimp` `hubspot` | [Export](https://docs.migma.ai/api-reference/export/list-export-formats) |
|
|
465
|
-
| `migma.domains` | `create` `list` `get` `verify` `update` `remove` `checkAvailability` `listManaged` `createManaged` `removeManaged` | [Domains](https://docs.migma.ai/api-reference/domains/list-domains) |
|
|
614
|
+
| `migma.domains` | `create` `list` `get` `verify` `update` `remove` `checkAvailability` `listManaged` `createManaged` `removeManaged` `provisionStream` `setup` | [Domains](https://docs.migma.ai/api-reference/domains/list-domains) |
|
|
466
615
|
| `migma.webhooks` | `create` `list` `get` `update` `remove` `test` `getDeliveries` `getEvents` `getStats` | [Webhooks](https://docs.migma.ai/webhooks) |
|
|
467
616
|
| `migma.knowledgeBase` | `list` `add` `update` `remove` | [API Ref](https://docs.migma.ai/api-reference/introduction) |
|
|
468
617
|
| `migma.images` | `add` `update` `remove` `updateLogos` | [API Ref](https://docs.migma.ai/api-reference/introduction) |
|