@masters-union/outbound-sdk 0.1.4 → 0.1.5
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 +113 -118
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,183 +2,178 @@
|
|
|
2
2
|
|
|
3
3
|
Official Node.js SDK for the [Outbound](https://github.com/AdarshChakrworty/outbound) email platform.
|
|
4
4
|
|
|
5
|
-
## Install
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
::: code-group
|
|
9
|
+
```bash [npm]
|
|
10
|
+
npm install @masters-union/outbound-sdk
|
|
11
|
+
```
|
|
12
|
+
```bash [yarn]
|
|
13
|
+
yarn add @masters-union/outbound-sdk
|
|
14
|
+
```
|
|
15
|
+
```bash [pnpm]
|
|
16
|
+
pnpm add @masters-union/outbound-sdk
|
|
9
17
|
```
|
|
18
|
+
:::
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
**Requirements:** Node.js 18+ (uses native `fetch`)
|
|
12
21
|
|
|
13
|
-
|
|
14
|
-
import { Outbound } from 'outbound-sdk';
|
|
22
|
+
## Quick Setup
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
|
|
24
|
+
### 1. Get your API key
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
toEmail: 'user@example.com',
|
|
21
|
-
fromEmail: 'noreply@company.com',
|
|
22
|
-
emailSubject: 'Welcome!',
|
|
23
|
-
htmlBody: '<h1>Hello World</h1>',
|
|
24
|
-
});
|
|
25
|
-
```
|
|
26
|
+
Your Outbound admin will provide you with an API key. It looks like:
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
```
|
|
29
|
+
mu_outbound_a1b2c3d4e5f6...
|
|
30
|
+
```
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
### 2. Initialize the client
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
::: code-group
|
|
35
|
+
```ts [ESM]
|
|
36
|
+
import { Outbound } from '@masters-union/outbound-sdk';
|
|
33
37
|
|
|
34
|
-
const
|
|
35
|
-
|
|
38
|
+
const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
|
|
39
|
+
```
|
|
40
|
+
```js [CommonJS]
|
|
41
|
+
const { Outbound } = require('@masters-union/outbound-sdk');
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
await outbound.email.send({ toEmail: '...', ... }, { apiKey: tenantBKey });
|
|
43
|
+
const outbound = new Outbound({ apiKey: 'mu_outbound_...' });
|
|
39
44
|
```
|
|
45
|
+
:::
|
|
40
46
|
|
|
41
|
-
|
|
47
|
+
Once you set the API key in the constructor, every method uses it automatically. No need to pass it on every call.
|
|
42
48
|
|
|
43
|
-
### Send
|
|
49
|
+
### 3. Send your first email
|
|
44
50
|
|
|
45
51
|
```ts
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{ toEmail: 'bob@example.com', htmlBody: '<h1>Hi Bob</h1>' },
|
|
52
|
-
],
|
|
52
|
+
const { jobId, messageId } = await outbound.email.send({
|
|
53
|
+
toEmail: 'user@example.com',
|
|
54
|
+
fromEmail: 'noreply@yourcompany.com', // must be a verified domain
|
|
55
|
+
emailSubject: 'Welcome!',
|
|
56
|
+
htmlBody: '<h1>Hello World</h1>',
|
|
53
57
|
});
|
|
54
|
-
|
|
58
|
+
|
|
59
|
+
console.log(`Email queued: ${jobId}`);
|
|
55
60
|
```
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
::: warning Verified Domains Only
|
|
63
|
+
The `fromEmail` must use a domain that has been verified and assigned to your tenant account by the admin. Sending from an unverified domain will return a `403 Forbidden` error.
|
|
64
|
+
:::
|
|
65
|
+
|
|
66
|
+
### 4. Check delivery status
|
|
58
67
|
|
|
59
68
|
```ts
|
|
60
|
-
const status = await outbound.email.status(
|
|
61
|
-
|
|
69
|
+
const status = await outbound.email.status(jobId);
|
|
70
|
+
|
|
71
|
+
for (const recipient of status.recipients) {
|
|
72
|
+
console.log(`${recipient.recipient_email}: ${recipient.status}`);
|
|
73
|
+
// "sent" → "delivered" → "opened" → "clicked"
|
|
74
|
+
}
|
|
62
75
|
```
|
|
63
76
|
|
|
64
|
-
###
|
|
77
|
+
### 5. Send with a template
|
|
65
78
|
|
|
66
79
|
```ts
|
|
67
|
-
// Create
|
|
80
|
+
// Create a reusable template
|
|
68
81
|
const { template } = await outbound.templates.create({
|
|
69
|
-
name: 'welcome',
|
|
82
|
+
name: 'welcome-email',
|
|
70
83
|
subject: 'Welcome {{firstName}}!',
|
|
71
|
-
htmlBody: '<h1>Hello {{firstName}}</h1>',
|
|
72
|
-
variables: ['firstName'],
|
|
84
|
+
htmlBody: '<h1>Hello {{firstName}}</h1><p>Welcome to {{company}}.</p>',
|
|
85
|
+
variables: ['firstName', 'company'],
|
|
73
86
|
});
|
|
74
87
|
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Send using template
|
|
79
|
-
const { jobId } = await outbound.templates.send({
|
|
88
|
+
// Send to one person
|
|
89
|
+
await outbound.templates.send({
|
|
80
90
|
templateId: template.id,
|
|
81
91
|
toEmail: 'user@example.com',
|
|
82
|
-
fromEmail: 'noreply@
|
|
83
|
-
variables: { firstName: 'John' },
|
|
92
|
+
fromEmail: 'noreply@yourcompany.com',
|
|
93
|
+
variables: { firstName: 'John', company: 'Acme' },
|
|
84
94
|
});
|
|
85
95
|
|
|
86
|
-
//
|
|
87
|
-
|
|
96
|
+
// Send to many people
|
|
97
|
+
await outbound.templates.bulkSend({
|
|
88
98
|
templateId: template.id,
|
|
89
|
-
fromEmail: 'noreply@
|
|
99
|
+
fromEmail: 'noreply@yourcompany.com',
|
|
90
100
|
recipients: [
|
|
91
|
-
{ toEmail: 'alice@example.com', variables: { firstName: 'Alice' } },
|
|
92
|
-
{ toEmail: 'bob@example.com', variables: { firstName: 'Bob' } },
|
|
101
|
+
{ toEmail: 'alice@example.com', variables: { firstName: 'Alice', company: 'Acme' } },
|
|
102
|
+
{ toEmail: 'bob@example.com', variables: { firstName: 'Bob', company: 'Acme' } },
|
|
93
103
|
],
|
|
94
104
|
});
|
|
95
|
-
|
|
96
|
-
// Preview
|
|
97
|
-
const preview = await outbound.templates.preview(template.id, {
|
|
98
|
-
variables: { firstName: 'John' },
|
|
99
|
-
});
|
|
100
105
|
```
|
|
101
106
|
|
|
102
|
-
###
|
|
107
|
+
### 6. Multi-tenant usage
|
|
108
|
+
|
|
109
|
+
The SDK supports multi-tenant applications. You can override the API key on any individual call using the optional last argument:
|
|
103
110
|
|
|
104
111
|
```ts
|
|
105
|
-
//
|
|
106
|
-
await outbound.suppressions.add({ email: 'bad@example.com', reason: 'manual' });
|
|
112
|
+
const outbound = new Outbound(); // no default apiKey
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
const
|
|
114
|
+
const tenantAKey = 'mu_outbound_tenant_a_...';
|
|
115
|
+
const tenantBKey = 'mu_outbound_tenant_b_...';
|
|
110
116
|
|
|
111
|
-
//
|
|
112
|
-
await outbound.
|
|
117
|
+
// Pass { apiKey } as the last argument to override per call
|
|
118
|
+
await outbound.email.send({ /* ... */ }, { apiKey: tenantAKey });
|
|
119
|
+
await outbound.email.send({ /* ... */ }, { apiKey: tenantBKey });
|
|
113
120
|
```
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
You can also set a default in the constructor and override only when needed:
|
|
116
123
|
|
|
117
124
|
```ts
|
|
118
|
-
//
|
|
119
|
-
const { webhook, secret } = await outbound.webhooks.create({
|
|
120
|
-
url: 'https://myapp.com/webhooks/outbound',
|
|
121
|
-
events: ['delivery', 'bounce', 'complaint'],
|
|
122
|
-
});
|
|
123
|
-
// Store `secret` securely for signature verification
|
|
125
|
+
const outbound = new Outbound({ apiKey: tenantAKey }); // default
|
|
124
126
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
+
await outbound.email.send({ /* ... */ }); // uses tenantAKey
|
|
128
|
+
await outbound.email.send({ /* ... */ }, { apiKey: tenantBKey }); // uses tenantBKey
|
|
127
129
|
```
|
|
128
130
|
|
|
129
|
-
|
|
131
|
+
## Key Concepts
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
const dashboard = await outbound.dashboard.get();
|
|
133
|
-
// dashboard.last30Days.sent, dashboard.quota, etc.
|
|
133
|
+
### Email Lifecycle
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
Every email goes through these statuses:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
queued → processing → sent → delivered
|
|
139
|
+
↘ bounced
|
|
140
|
+
↘ complained
|
|
141
|
+
delivered → opened → clicked
|
|
137
142
|
```
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
| Status | Meaning |
|
|
145
|
+
|--------|---------|
|
|
146
|
+
| `queued` | Email is in the queue, waiting to be processed |
|
|
147
|
+
| `processing` | Email is being sent to AWS SES |
|
|
148
|
+
| `sent` | SES accepted the email |
|
|
149
|
+
| `delivered` | Email landed in recipient's inbox |
|
|
150
|
+
| `bounced` | Email bounced (bad address or mailbox full) |
|
|
151
|
+
| `complained` | Recipient marked it as spam |
|
|
152
|
+
| `opened` | Recipient opened the email (requires tracking) |
|
|
153
|
+
| `clicked` | Recipient clicked a link (requires tracking) |
|
|
154
|
+
| `failed` | Failed to send (SES rejection or error) |
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
|--------|---------|-------------|
|
|
143
|
-
| `apiKey` | — | Default API key (optional if provided per call) |
|
|
144
|
-
| `baseUrl` | `https://outbound-api.mastersunion.org` | API base URL |
|
|
145
|
-
| `timeout` | `30000` | Request timeout in ms |
|
|
146
|
-
| `maxRetries` | `3` | Max retries on 429/5xx |
|
|
147
|
-
| `retryDelay` | `1000` | Initial retry delay in ms (exponential backoff) |
|
|
156
|
+
### Suppression List
|
|
148
157
|
|
|
149
|
-
|
|
158
|
+
The platform automatically suppresses emails that bounce or receive complaints. You can also manually suppress emails. Any future send to a suppressed address is **silently filtered out** — it won't count against your quota.
|
|
150
159
|
|
|
151
|
-
|
|
160
|
+
### Quotas
|
|
152
161
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
console.log('Resource not found');
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
162
|
+
Your tenant account has:
|
|
163
|
+
- **Daily limit** — Max emails per day
|
|
164
|
+
- **Monthly limit** — Max emails per month
|
|
165
|
+
- **Rate limit** — Max emails per second
|
|
166
|
+
- **Template limit** — Max number of templates
|
|
167
|
+
|
|
168
|
+
Check your quota anytime with `outbound.dashboard.quota()`.
|
|
169
|
+
|
|
170
|
+
## What's Next?
|
|
166
171
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
| `NotFoundError` | 404 |
|
|
173
|
-
| `ConflictError` | 409 |
|
|
174
|
-
| `RateLimitError` | 429 |
|
|
175
|
-
| `ServerError` | 5xx |
|
|
176
|
-
| `TimeoutError` | - |
|
|
177
|
-
| `NetworkError` | - |
|
|
178
|
-
|
|
179
|
-
## Requirements
|
|
180
|
-
|
|
181
|
-
- Node.js 18+ (uses native `fetch`)
|
|
172
|
+
- [Configuration](/guide/configuration) — Customize timeouts, retries, and more
|
|
173
|
+
- [Error Handling](/guide/error-handling) — Handle every error type
|
|
174
|
+
- [Email API](/api/email) — Single and bulk sending reference
|
|
175
|
+
- [Templates API](/api/templates) — Full template lifecycle
|
|
176
|
+
- [Webhooks API](/api/webhooks) — Real-time event notifications
|
|
182
177
|
|
|
183
178
|
## License
|
|
184
179
|
|