@subscribeflow/sdk 1.0.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 +379 -0
- package/dist/api-types.d.ts +4865 -0
- package/dist/api-types.d.ts.map +1 -0
- package/dist/api-types.js +6 -0
- package/dist/api-types.js.map +1 -0
- package/dist/index.d.ts +10313 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1029 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# @subscribeflow/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the SubscribeFlow API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Von GitHub (Empfohlen)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# npm
|
|
11
|
+
npm install git+https://github.com/talent-factory/subscribe-flow.git#subdirectory=sdk/typescript
|
|
12
|
+
|
|
13
|
+
# yarn
|
|
14
|
+
yarn add git+https://github.com/talent-factory/subscribe-flow.git#subdirectory=sdk/typescript
|
|
15
|
+
|
|
16
|
+
# bun
|
|
17
|
+
bun add github:talent-factory/subscribe-flow#subdirectory=sdk/typescript
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In `package.json`:
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@subscribeflow/sdk": "git+https://github.com/talent-factory/subscribe-flow.git#subdirectory=sdk/typescript"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Lokale Entwicklung
|
|
30
|
+
|
|
31
|
+
Für parallele Entwicklung von SDK und Anwendung gibt es mehrere Optionen:
|
|
32
|
+
|
|
33
|
+
#### Option 1: `file:` Protokoll (Einfachste)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# npm/yarn/pnpm
|
|
37
|
+
npm install /pfad/zu/subscribeflow/sdk/typescript
|
|
38
|
+
|
|
39
|
+
# bun
|
|
40
|
+
bun add /pfad/zu/subscribeflow/sdk/typescript
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In `package.json`:
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@subscribeflow/sdk": "file:../subscribeflow/sdk/typescript"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### Option 2: `npm link` / `bun link` (Symlink)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Im SDK-Verzeichnis
|
|
56
|
+
cd /pfad/zu/subscribeflow/sdk/typescript
|
|
57
|
+
npm link # oder: bun link
|
|
58
|
+
|
|
59
|
+
# In deinem Projekt
|
|
60
|
+
cd /pfad/zu/deinem/projekt
|
|
61
|
+
npm link @subscribeflow/sdk # oder: bun link @subscribeflow/sdk
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Vorteil:** Änderungen am SDK sind sofort verfügbar ohne Neuinstallation.
|
|
65
|
+
|
|
66
|
+
#### Option 3: Workspace (Monorepo)
|
|
67
|
+
|
|
68
|
+
Für Projekte im selben Repository:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
// package.json (root)
|
|
72
|
+
{
|
|
73
|
+
"workspaces": ["apps/*", "sdk/*"]
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Best Practice für lokale Entwicklung
|
|
78
|
+
|
|
79
|
+
1. **Während der Entwicklung:** `npm link` oder `file:` verwenden
|
|
80
|
+
2. **Vor dem Commit:** Auf GitHub-URL umstellen
|
|
81
|
+
3. **CI/CD:** GitHub-URL nutzen
|
|
82
|
+
|
|
83
|
+
## Quick Start
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { SubscribeFlowClient } from '@subscribeflow/sdk';
|
|
87
|
+
|
|
88
|
+
const client = new SubscribeFlowClient({
|
|
89
|
+
apiKey: process.env.SUBSCRIBEFLOW_API_KEY!,
|
|
90
|
+
baseUrl: 'https://api.subscribeflow.net', // optional, this is the default
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Create a subscriber
|
|
94
|
+
const subscriber = await client.subscribers.create({
|
|
95
|
+
email: 'user@example.com',
|
|
96
|
+
tags: ['newsletter', 'product-updates'],
|
|
97
|
+
metadata: { source: 'website' },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
console.log('Created subscriber:', subscriber.id);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Usage
|
|
104
|
+
|
|
105
|
+
### Subscribers
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// List subscribers
|
|
109
|
+
const { items, total, cursor } = await client.subscribers.list({
|
|
110
|
+
limit: 50,
|
|
111
|
+
status: 'active',
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Get a subscriber
|
|
115
|
+
const subscriber = await client.subscribers.get('subscriber-id');
|
|
116
|
+
|
|
117
|
+
// Update a subscriber
|
|
118
|
+
const updated = await client.subscribers.update('subscriber-id', {
|
|
119
|
+
metadata: { plan: 'premium' },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Delete a subscriber
|
|
123
|
+
await client.subscribers.delete('subscriber-id');
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Tags
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// Create a tag
|
|
130
|
+
const tag = await client.tags.create({
|
|
131
|
+
name: 'Product Updates',
|
|
132
|
+
slug: 'product-updates',
|
|
133
|
+
description: 'Get notified about new features and improvements',
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// List tags
|
|
137
|
+
const { items } = await client.tags.list();
|
|
138
|
+
|
|
139
|
+
// Update a tag
|
|
140
|
+
await client.tags.update('tag-id', {
|
|
141
|
+
description: 'Updated description',
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Delete a tag
|
|
145
|
+
await client.tags.delete('tag-id');
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Templates
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Create an email template
|
|
152
|
+
const template = await client.templates.create({
|
|
153
|
+
name: 'Welcome Email',
|
|
154
|
+
subject: 'Welcome to {{company}}!',
|
|
155
|
+
mjml_content: '<mjml><mj-body>...</mj-body></mjml>',
|
|
156
|
+
category: 'transactional',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// List templates
|
|
160
|
+
const { items } = await client.templates.list({ category: 'transactional' });
|
|
161
|
+
|
|
162
|
+
// Get a template by slug
|
|
163
|
+
const tmpl = await client.templates.getBySlug('welcome-email');
|
|
164
|
+
|
|
165
|
+
// Preview a template
|
|
166
|
+
const preview = await client.templates.preview('template-id', {
|
|
167
|
+
company: 'Acme Inc',
|
|
168
|
+
});
|
|
169
|
+
console.log(preview.html);
|
|
170
|
+
|
|
171
|
+
// Update a template
|
|
172
|
+
await client.templates.update('template-id', { subject: 'New Subject' });
|
|
173
|
+
|
|
174
|
+
// Delete a template
|
|
175
|
+
await client.templates.delete('template-id');
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Email Send
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// Send a transactional email
|
|
182
|
+
const result = await client.emails.send({
|
|
183
|
+
template_slug: 'welcome-email',
|
|
184
|
+
to: 'user@example.com',
|
|
185
|
+
variables: { company: 'Acme Inc' },
|
|
186
|
+
idempotency_key: 'unique-key-123',
|
|
187
|
+
});
|
|
188
|
+
console.log('Email queued:', result.id);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Campaigns
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// Create a campaign
|
|
195
|
+
const campaign = await client.campaigns.create({
|
|
196
|
+
name: 'February Newsletter',
|
|
197
|
+
template_id: 'template-uuid',
|
|
198
|
+
tag_filter: { include_tags: ['newsletter'], match: 'any' },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// List campaigns
|
|
202
|
+
const campaigns = await client.campaigns.list({ status: 'draft' });
|
|
203
|
+
|
|
204
|
+
// Preview recipient count
|
|
205
|
+
const count = await client.campaigns.countRecipients('campaign-id');
|
|
206
|
+
console.log(`Will send to ${count.count} subscribers`);
|
|
207
|
+
|
|
208
|
+
// Send the campaign
|
|
209
|
+
const sendResult = await client.campaigns.send('campaign-id');
|
|
210
|
+
|
|
211
|
+
// Cancel a running campaign
|
|
212
|
+
await client.campaigns.cancel('campaign-id');
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Email Triggers
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Create an event-based trigger
|
|
219
|
+
const trigger = await client.triggers.create({
|
|
220
|
+
event_type: 'subscriber.created',
|
|
221
|
+
template_id: 'welcome-template-uuid',
|
|
222
|
+
description: 'Send welcome email on signup',
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// List triggers
|
|
226
|
+
const triggers = await client.triggers.list();
|
|
227
|
+
|
|
228
|
+
// Update a trigger
|
|
229
|
+
await client.triggers.update('trigger-id', { is_active: false });
|
|
230
|
+
|
|
231
|
+
// Delete a trigger
|
|
232
|
+
await client.triggers.delete('trigger-id');
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Webhooks
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
// Create a webhook endpoint
|
|
239
|
+
const webhook = await client.webhooks.create({
|
|
240
|
+
url: 'https://your-app.com/webhooks/subscribeflow',
|
|
241
|
+
events: ['subscriber.created', 'tag.subscribed'],
|
|
242
|
+
description: 'Main webhook endpoint',
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// The signing secret is only returned on creation
|
|
246
|
+
console.log('Signing secret:', webhook.signing_secret);
|
|
247
|
+
|
|
248
|
+
// List webhook endpoints
|
|
249
|
+
const { items } = await client.webhooks.list();
|
|
250
|
+
|
|
251
|
+
// Update a webhook
|
|
252
|
+
await client.webhooks.update('webhook-id', {
|
|
253
|
+
events: ['subscriber.created', 'subscriber.deleted'],
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Test a webhook
|
|
257
|
+
const result = await client.webhooks.test('webhook-id', 'subscriber.created');
|
|
258
|
+
if (result.success) {
|
|
259
|
+
console.log('Webhook is working!');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Rotate signing secret
|
|
263
|
+
const rotated = await client.webhooks.rotateSecret('webhook-id');
|
|
264
|
+
console.log('New secret:', rotated.signing_secret);
|
|
265
|
+
|
|
266
|
+
// View delivery history
|
|
267
|
+
const deliveries = await client.webhooks.listDeliveries('webhook-id');
|
|
268
|
+
|
|
269
|
+
// Get delivery statistics
|
|
270
|
+
const stats = await client.webhooks.getDeliveryStats('webhook-id');
|
|
271
|
+
console.log(`Success rate: ${stats.success_rate}%`);
|
|
272
|
+
|
|
273
|
+
// Retry a failed delivery
|
|
274
|
+
await client.webhooks.retryDelivery('webhook-id', 'delivery-id');
|
|
275
|
+
|
|
276
|
+
// Delete a webhook
|
|
277
|
+
await client.webhooks.delete('webhook-id');
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Preference Center
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Generate a preference center token
|
|
284
|
+
const tokenResponse = await client.subscribers.generatePreferenceToken('subscriber-id');
|
|
285
|
+
|
|
286
|
+
// Access the preference center with the token
|
|
287
|
+
const prefCenter = client.preferenceCenter(tokenResponse.token);
|
|
288
|
+
|
|
289
|
+
// Get subscriber preferences and available tags
|
|
290
|
+
const info = await prefCenter.getInfo();
|
|
291
|
+
|
|
292
|
+
// Subscribe/unsubscribe from tags
|
|
293
|
+
await prefCenter.subscribeTag('tag-id');
|
|
294
|
+
await prefCenter.unsubscribeTag('tag-id');
|
|
295
|
+
|
|
296
|
+
// Export all data (DSGVO)
|
|
297
|
+
const exportData = await prefCenter.exportData();
|
|
298
|
+
|
|
299
|
+
// Delete account (DSGVO)
|
|
300
|
+
await prefCenter.deleteAccount();
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Error Handling
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import { SubscribeFlowClient, SubscribeFlowError } from '@subscribeflow/sdk';
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
await client.subscribers.get('non-existent-id');
|
|
310
|
+
} catch (error) {
|
|
311
|
+
if (error instanceof SubscribeFlowError) {
|
|
312
|
+
console.error('API Error:', error.message);
|
|
313
|
+
console.error('Status:', error.status);
|
|
314
|
+
console.error('Type:', error.type);
|
|
315
|
+
console.error('Detail:', error.detail);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Configuration
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const client = new SubscribeFlowClient({
|
|
324
|
+
// Required: Your API key
|
|
325
|
+
apiKey: 'sf_live_xxx',
|
|
326
|
+
|
|
327
|
+
// Optional: API base URL (default: https://api.subscribeflow.net)
|
|
328
|
+
baseUrl: 'https://api.subscribeflow.net',
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Lokale API-Instanz
|
|
333
|
+
|
|
334
|
+
Für Entwicklung gegen eine lokale SubscribeFlow-Instanz:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
const client = new SubscribeFlowClient({
|
|
338
|
+
apiKey: 'sf_dev_xxx',
|
|
339
|
+
baseUrl: 'http://localhost:8000',
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## TypeScript Support
|
|
344
|
+
|
|
345
|
+
This SDK is written in TypeScript and provides full type definitions out of the box.
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
import type { paths, components } from '@subscribeflow/sdk';
|
|
349
|
+
|
|
350
|
+
// Use component schemas
|
|
351
|
+
type Subscriber = components['schemas']['SubscriberResponse'];
|
|
352
|
+
type Tag = components['schemas']['TagResponse'];
|
|
353
|
+
|
|
354
|
+
// Type-safe API operations
|
|
355
|
+
const subscriber: Subscriber = await client.subscribers.get('id');
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Regenerating Types
|
|
359
|
+
|
|
360
|
+
If the API changes, you can regenerate the TypeScript types:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Make sure the backend is running
|
|
364
|
+
make backend
|
|
365
|
+
|
|
366
|
+
# Fetch OpenAPI schema and generate types
|
|
367
|
+
curl http://localhost:8000/openapi.json -o openapi.json
|
|
368
|
+
bunx openapi-typescript openapi.json -o src/api-types.ts
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Links
|
|
372
|
+
|
|
373
|
+
- [API Documentation](https://docs.subscribeflow.net/reference/api)
|
|
374
|
+
- [Getting Started Guide](https://docs.subscribeflow.net/getting-started)
|
|
375
|
+
- [Webhook Integration](https://docs.subscribeflow.net/guides/webhooks)
|
|
376
|
+
|
|
377
|
+
## License
|
|
378
|
+
|
|
379
|
+
MIT
|