listbee 0.3.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 +552 -0
- package/dist/cjs/base-client.d.ts +65 -0
- package/dist/cjs/base-client.js +167 -0
- package/dist/cjs/base-client.js.map +1 -0
- package/dist/cjs/client.d.ts +58 -0
- package/dist/cjs/client.js +54 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/constants.d.ts +17 -0
- package/dist/cjs/constants.js +21 -0
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/errors.d.ts +89 -0
- package/dist/cjs/errors.js +141 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +26 -0
- package/dist/cjs/index.js +49 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/resources/account.d.ts +25 -0
- package/dist/cjs/resources/account.js +39 -0
- package/dist/cjs/resources/account.js.map +1 -0
- package/dist/cjs/resources/api-keys.d.ts +14 -0
- package/dist/cjs/resources/api-keys.js +26 -0
- package/dist/cjs/resources/api-keys.js.map +1 -0
- package/dist/cjs/resources/index.d.ts +7 -0
- package/dist/cjs/resources/index.js +18 -0
- package/dist/cjs/resources/index.js.map +1 -0
- package/dist/cjs/resources/listings.d.ts +70 -0
- package/dist/cjs/resources/listings.js +161 -0
- package/dist/cjs/resources/listings.js.map +1 -0
- package/dist/cjs/resources/orders.d.ts +11 -0
- package/dist/cjs/resources/orders.js +36 -0
- package/dist/cjs/resources/orders.js.map +1 -0
- package/dist/cjs/resources/signup.d.ts +16 -0
- package/dist/cjs/resources/signup.js +21 -0
- package/dist/cjs/resources/signup.js.map +1 -0
- package/dist/cjs/resources/stores.d.ts +31 -0
- package/dist/cjs/resources/stores.js +67 -0
- package/dist/cjs/resources/stores.js.map +1 -0
- package/dist/cjs/resources/stripe.d.ts +15 -0
- package/dist/cjs/resources/stripe.js +25 -0
- package/dist/cjs/resources/stripe.js.map +1 -0
- package/dist/cjs/resources/webhooks.d.ts +15 -0
- package/dist/cjs/resources/webhooks.js +55 -0
- package/dist/cjs/resources/webhooks.js.map +1 -0
- package/dist/cjs/types/account.d.ts +47 -0
- package/dist/cjs/types/account.js +6 -0
- package/dist/cjs/types/account.js.map +1 -0
- package/dist/cjs/types/api-key.d.ts +18 -0
- package/dist/cjs/types/api-key.js +6 -0
- package/dist/cjs/types/api-key.js.map +1 -0
- package/dist/cjs/types/index.d.ts +10 -0
- package/dist/cjs/types/index.js +10 -0
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/listing.d.ts +177 -0
- package/dist/cjs/types/listing.js +6 -0
- package/dist/cjs/types/listing.js.map +1 -0
- package/dist/cjs/types/order.d.ts +42 -0
- package/dist/cjs/types/order.js +6 -0
- package/dist/cjs/types/order.js.map +1 -0
- package/dist/cjs/types/shared.d.ts +87 -0
- package/dist/cjs/types/shared.js +41 -0
- package/dist/cjs/types/shared.js.map +1 -0
- package/dist/cjs/types/signup.d.ts +24 -0
- package/dist/cjs/types/signup.js +6 -0
- package/dist/cjs/types/signup.js.map +1 -0
- package/dist/cjs/types/store.d.ts +70 -0
- package/dist/cjs/types/store.js +6 -0
- package/dist/cjs/types/store.js.map +1 -0
- package/dist/cjs/types/stripe.d.ts +12 -0
- package/dist/cjs/types/stripe.js +6 -0
- package/dist/cjs/types/stripe.js.map +1 -0
- package/dist/cjs/types/webhook.d.ts +88 -0
- package/dist/cjs/types/webhook.js +6 -0
- package/dist/cjs/types/webhook.js.map +1 -0
- package/dist/esm/base-client.d.ts +65 -0
- package/dist/esm/base-client.js +159 -0
- package/dist/esm/base-client.js.map +1 -0
- package/dist/esm/client.d.ts +58 -0
- package/dist/esm/client.js +50 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/constants.d.ts +17 -0
- package/dist/esm/constants.js +18 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/errors.d.ts +89 -0
- package/dist/esm/errors.js +124 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +26 -0
- package/dist/esm/index.js +20 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/account.d.ts +25 -0
- package/dist/esm/resources/account.js +35 -0
- package/dist/esm/resources/account.js.map +1 -0
- package/dist/esm/resources/api-keys.d.ts +14 -0
- package/dist/esm/resources/api-keys.js +21 -0
- package/dist/esm/resources/api-keys.js.map +1 -0
- package/dist/esm/resources/index.d.ts +7 -0
- package/dist/esm/resources/index.js +8 -0
- package/dist/esm/resources/index.js.map +1 -0
- package/dist/esm/resources/listings.d.ts +70 -0
- package/dist/esm/resources/listings.js +156 -0
- package/dist/esm/resources/listings.js.map +1 -0
- package/dist/esm/resources/orders.d.ts +11 -0
- package/dist/esm/resources/orders.js +31 -0
- package/dist/esm/resources/orders.js.map +1 -0
- package/dist/esm/resources/signup.d.ts +16 -0
- package/dist/esm/resources/signup.js +17 -0
- package/dist/esm/resources/signup.js.map +1 -0
- package/dist/esm/resources/stores.d.ts +31 -0
- package/dist/esm/resources/stores.js +63 -0
- package/dist/esm/resources/stores.js.map +1 -0
- package/dist/esm/resources/stripe.d.ts +15 -0
- package/dist/esm/resources/stripe.js +21 -0
- package/dist/esm/resources/stripe.js.map +1 -0
- package/dist/esm/resources/webhooks.d.ts +15 -0
- package/dist/esm/resources/webhooks.js +49 -0
- package/dist/esm/resources/webhooks.js.map +1 -0
- package/dist/esm/types/account.d.ts +47 -0
- package/dist/esm/types/account.js +5 -0
- package/dist/esm/types/account.js.map +1 -0
- package/dist/esm/types/api-key.d.ts +18 -0
- package/dist/esm/types/api-key.js +5 -0
- package/dist/esm/types/api-key.js.map +1 -0
- package/dist/esm/types/index.d.ts +10 -0
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/listing.d.ts +177 -0
- package/dist/esm/types/listing.js +5 -0
- package/dist/esm/types/listing.js.map +1 -0
- package/dist/esm/types/order.d.ts +42 -0
- package/dist/esm/types/order.js +5 -0
- package/dist/esm/types/order.js.map +1 -0
- package/dist/esm/types/shared.d.ts +87 -0
- package/dist/esm/types/shared.js +38 -0
- package/dist/esm/types/shared.js.map +1 -0
- package/dist/esm/types/signup.d.ts +24 -0
- package/dist/esm/types/signup.js +5 -0
- package/dist/esm/types/signup.js.map +1 -0
- package/dist/esm/types/store.d.ts +70 -0
- package/dist/esm/types/store.js +5 -0
- package/dist/esm/types/store.js.map +1 -0
- package/dist/esm/types/stripe.d.ts +12 -0
- package/dist/esm/types/stripe.js +5 -0
- package/dist/esm/types/stripe.js.map +1 -0
- package/dist/esm/types/webhook.d.ts +88 -0
- package/dist/esm/types/webhook.js +5 -0
- package/dist/esm/types/webhook.js.map +1 -0
- package/package.json +136 -0
package/README.md
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
# listbee
|
|
2
|
+
|
|
3
|
+
Official TypeScript SDK for the [ListBee API](https://listbee.so) — one API call to sell and deliver digital content.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install listbee
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add listbee
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ListBee } from 'listbee';
|
|
19
|
+
|
|
20
|
+
const client = new ListBee({ apiKey: 'lb_...' });
|
|
21
|
+
|
|
22
|
+
const listing = await client.listings.create({
|
|
23
|
+
name: 'SEO Playbook',
|
|
24
|
+
price: 2900,
|
|
25
|
+
content: 'https://example.com/seo-playbook.pdf',
|
|
26
|
+
});
|
|
27
|
+
console.log(listing.url); // https://buy.listbee.so/r7kq2xy9
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Using an environment variable instead:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export LISTBEE_API_KEY="lb_..."
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { ListBee } from 'listbee';
|
|
38
|
+
|
|
39
|
+
const client = new ListBee(); // reads LISTBEE_API_KEY automatically
|
|
40
|
+
|
|
41
|
+
const listing = await client.listings.create({
|
|
42
|
+
name: 'SEO Playbook',
|
|
43
|
+
price: 2900,
|
|
44
|
+
content: 'https://example.com/seo-playbook.pdf',
|
|
45
|
+
});
|
|
46
|
+
console.log(listing.url);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Authentication
|
|
50
|
+
|
|
51
|
+
Pass your API key explicitly or via the `LISTBEE_API_KEY` environment variable.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { ListBee } from 'listbee';
|
|
55
|
+
|
|
56
|
+
// Explicit key
|
|
57
|
+
const client = new ListBee({ apiKey: 'lb_...' });
|
|
58
|
+
|
|
59
|
+
// Environment variable (LISTBEE_API_KEY)
|
|
60
|
+
const client = new ListBee();
|
|
61
|
+
|
|
62
|
+
// process.env lookup
|
|
63
|
+
const client = new ListBee({ apiKey: process.env.LISTBEE_API_KEY });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The key is validated lazily — the client constructs successfully even with a missing or invalid key. An `AuthenticationError` is raised only when you make the first API call.
|
|
67
|
+
|
|
68
|
+
API keys start with `lb_`. Get yours at [listbee.so](https://listbee.so).
|
|
69
|
+
|
|
70
|
+
## Resources
|
|
71
|
+
|
|
72
|
+
### Listings
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { ListBee } from 'listbee';
|
|
76
|
+
|
|
77
|
+
const client = new ListBee({ apiKey: 'lb_...' });
|
|
78
|
+
|
|
79
|
+
// Create — minimal
|
|
80
|
+
const listing = await client.listings.create({
|
|
81
|
+
name: 'SEO Playbook',
|
|
82
|
+
price: 2900, // $29.00 in cents
|
|
83
|
+
content: 'https://example.com/seo-playbook.pdf', // file URL, redirect URL, or plain text
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Create — all optional params
|
|
87
|
+
const listing = await client.listings.create({
|
|
88
|
+
name: 'SEO Playbook 2026',
|
|
89
|
+
price: 2900,
|
|
90
|
+
content: 'https://example.com/seo-playbook.pdf',
|
|
91
|
+
description: 'A comprehensive guide to modern SEO techniques.',
|
|
92
|
+
tagline: 'Updated for 2026 algorithm changes',
|
|
93
|
+
highlights: ['50+ pages', 'Actionable tips', 'Free updates'],
|
|
94
|
+
cta: 'Get Instant Access', // buy button text; defaults to "Buy Now"
|
|
95
|
+
cover_url: 'https://example.com/cover.png',
|
|
96
|
+
compare_at_price: 3900, // strikethrough price
|
|
97
|
+
badges: ['Limited time', 'Best seller'],
|
|
98
|
+
cover_blur: 'auto', // "auto" | "true" | "false"
|
|
99
|
+
rating: 4.8,
|
|
100
|
+
rating_count: 1243,
|
|
101
|
+
reviews: [
|
|
102
|
+
{ name: 'Clara D.', rating: 5.0, content: 'Excellent quality content.' },
|
|
103
|
+
],
|
|
104
|
+
faqs: [
|
|
105
|
+
{ q: 'Is this for beginners?', a: 'Yes, completely beginner-friendly.' },
|
|
106
|
+
],
|
|
107
|
+
metadata: { source: 'n8n', campaign: 'launch-week' },
|
|
108
|
+
});
|
|
109
|
+
console.log(listing.id); // lst_r7kq2xy9m3pR5tW1
|
|
110
|
+
console.log(listing.url); // https://buy.listbee.so/m3pr5tw1
|
|
111
|
+
|
|
112
|
+
// Get by slug
|
|
113
|
+
const listing = await client.listings.get('m3pr5tw1');
|
|
114
|
+
|
|
115
|
+
// List — paginated
|
|
116
|
+
const page = await client.listings.list({ limit: 20 });
|
|
117
|
+
for (const listing of page.data) {
|
|
118
|
+
console.log(listing.slug, listing.name);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Update — partial updates
|
|
122
|
+
const updated = await client.listings.update('r7kq2xy9', {
|
|
123
|
+
name: 'SEO Playbook 2026 Updated',
|
|
124
|
+
price: 3900,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Pause / Resume
|
|
128
|
+
await client.listings.pause('r7kq2xy9');
|
|
129
|
+
await client.listings.resume('r7kq2xy9');
|
|
130
|
+
|
|
131
|
+
// Delete
|
|
132
|
+
await client.listings.delete('m3pr5tw1');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Orders
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// List all orders
|
|
139
|
+
const page = await client.orders.list();
|
|
140
|
+
for (const order of page.data) {
|
|
141
|
+
console.log(order.id, order.status);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Filter by status, listing, date range
|
|
145
|
+
const page = await client.orders.list({
|
|
146
|
+
status: 'completed',
|
|
147
|
+
listing: 'seo-playbook',
|
|
148
|
+
created_after: new Date('2026-03-01'),
|
|
149
|
+
created_before: '2026-03-31T23:59:59Z', // Date objects or ISO strings
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Get by ID
|
|
153
|
+
const order = await client.orders.get('ord_9xM4kP7nR2qT5wY1');
|
|
154
|
+
console.log(order.listing_id, order.amount);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Webhooks
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { ListBee, WebhookEventType } from 'listbee';
|
|
161
|
+
|
|
162
|
+
const client = new ListBee({ apiKey: 'lb_...' });
|
|
163
|
+
|
|
164
|
+
// Create — subscribe to specific events
|
|
165
|
+
const webhook = await client.webhooks.create({
|
|
166
|
+
name: 'Production endpoint',
|
|
167
|
+
url: 'https://example.com/webhooks/listbee',
|
|
168
|
+
events: [
|
|
169
|
+
WebhookEventType.ORDER_COMPLETED,
|
|
170
|
+
WebhookEventType.ORDER_REFUNDED,
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
console.log(webhook.id); // wh_3mK8nP2qR5tW7xY1
|
|
174
|
+
console.log(webhook.secret); // HMAC signing key
|
|
175
|
+
|
|
176
|
+
// Create — receive all events (omit events param)
|
|
177
|
+
const webhook = await client.webhooks.create({
|
|
178
|
+
name: 'Catch-all',
|
|
179
|
+
url: 'https://example.com/webhooks/listbee-all',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// List
|
|
183
|
+
const webhooks = await client.webhooks.list();
|
|
184
|
+
for (const wh of webhooks) {
|
|
185
|
+
console.log(wh.id, wh.name, wh.enabled);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Update — disable without deleting
|
|
189
|
+
await client.webhooks.update('wh_3mK8nP2qR5tW7xY1', { enabled: false });
|
|
190
|
+
|
|
191
|
+
// Update — change URL and events
|
|
192
|
+
await client.webhooks.update('wh_3mK8nP2qR5tW7xY1', {
|
|
193
|
+
url: 'https://example.com/webhooks/v2',
|
|
194
|
+
events: [WebhookEventType.ORDER_COMPLETED],
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// List delivery events
|
|
198
|
+
const events = await client.webhooks.listEvents('wh_3mK8nP2qR5tW7xY1', {
|
|
199
|
+
status: 'failed',
|
|
200
|
+
});
|
|
201
|
+
for (const evt of events.data) {
|
|
202
|
+
console.log(evt.event_type, evt.status, evt.last_error);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Test endpoint
|
|
206
|
+
const test = await client.webhooks.test('wh_3mK8nP2qR5tW7xY1');
|
|
207
|
+
console.log(test.success, test.status_code);
|
|
208
|
+
|
|
209
|
+
// Delete
|
|
210
|
+
await client.webhooks.delete('wh_3mK8nP2qR5tW7xY1');
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Account
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const account = await client.account.get();
|
|
217
|
+
console.log(account.id); // acc_7kQ2xY9mN3pR5tW1
|
|
218
|
+
console.log(account.email); // seller@example.com
|
|
219
|
+
console.log(account.plan); // free | growth | scale
|
|
220
|
+
console.log(account.readiness.operational);
|
|
221
|
+
|
|
222
|
+
// Update Google Analytics tracking
|
|
223
|
+
await client.account.update({ ga_measurement_id: 'G-XXXXXXXXXX' });
|
|
224
|
+
|
|
225
|
+
// Clear GA tracking
|
|
226
|
+
await client.account.update({ ga_measurement_id: null });
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Signup
|
|
230
|
+
|
|
231
|
+
Agent self-service onboarding — no API key required:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { ListBee } from 'listbee';
|
|
235
|
+
|
|
236
|
+
const client = new ListBee(); // no API key needed
|
|
237
|
+
|
|
238
|
+
// Request a signup code
|
|
239
|
+
await client.signup.create({ email: 'seller@example.com' });
|
|
240
|
+
|
|
241
|
+
// Verify the code — returns account + API key
|
|
242
|
+
const result = await client.signup.verify({
|
|
243
|
+
email: 'seller@example.com',
|
|
244
|
+
code: '123456',
|
|
245
|
+
});
|
|
246
|
+
console.log(result.api_key); // lb_... (one-time display)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### API keys
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// List all API keys
|
|
253
|
+
const keys = await client.apiKeys.list();
|
|
254
|
+
for (const key of keys) {
|
|
255
|
+
console.log(key.id, key.name);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Create a new key — the key value is only shown once
|
|
259
|
+
const newKey = await client.apiKeys.create({ name: 'CI pipeline' });
|
|
260
|
+
console.log(newKey.key); // lb_... (save this immediately)
|
|
261
|
+
|
|
262
|
+
// Delete a key
|
|
263
|
+
await client.apiKeys.delete('lbk_7kQ2xY9mN3pR5tW1');
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Stores
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Create a store
|
|
270
|
+
const store = await client.stores.create({ handle: 'fitness-brand', name: 'Fitness Brand' });
|
|
271
|
+
console.log(store.id); // str_7kQ2xY9mN3pR5tW1vB8a
|
|
272
|
+
console.log(store.handle); // fitness-brand
|
|
273
|
+
|
|
274
|
+
// List all stores
|
|
275
|
+
const stores = await client.stores.list();
|
|
276
|
+
for (const s of stores.data) {
|
|
277
|
+
console.log(s.handle, s.display_name);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Get a store
|
|
281
|
+
const store = await client.stores.get('str_7kQ2xY9mN3pR5tW1vB8a');
|
|
282
|
+
|
|
283
|
+
// Update a store
|
|
284
|
+
const updated = await client.stores.update('str_7kQ2xY9mN3pR5tW1vB8a', {
|
|
285
|
+
name: 'Fitness Pro',
|
|
286
|
+
bio: 'Premium fitness content',
|
|
287
|
+
social_links: ['https://twitter.com/fitnesspro'],
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Delete a store
|
|
291
|
+
await client.stores.delete('str_7kQ2xY9mN3pR5tW1vB8a');
|
|
292
|
+
|
|
293
|
+
// Connect Stripe — returns a URL to redirect the user to
|
|
294
|
+
const session = await client.stores.connectStripe('str_7kQ2xY9mN3pR5tW1vB8a');
|
|
295
|
+
console.log(session.url); // redirect seller here
|
|
296
|
+
|
|
297
|
+
// Custom domains
|
|
298
|
+
const domain = await client.stores.setDomain('str_7kQ2xY9mN3pR5tW1vB8a', { domain: 'fitness.com' });
|
|
299
|
+
console.log(domain.cname_target); // buy.listbee.so — point your CNAME here
|
|
300
|
+
|
|
301
|
+
const verified = await client.stores.verifyDomain('str_7kQ2xY9mN3pR5tW1vB8a');
|
|
302
|
+
console.log(verified.status); // "verified" or "pending"
|
|
303
|
+
|
|
304
|
+
await client.stores.removeDomain('str_7kQ2xY9mN3pR5tW1vB8a');
|
|
305
|
+
|
|
306
|
+
// Create a listing in a specific store
|
|
307
|
+
const listing = await client.listings.create({
|
|
308
|
+
name: 'SEO Playbook',
|
|
309
|
+
price: 2900,
|
|
310
|
+
content: 'https://example.com/seo-playbook.pdf',
|
|
311
|
+
store_id: 'str_7kQ2xY9mN3pR5tW1vB8a',
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Stripe
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// Set your Stripe secret key
|
|
319
|
+
await client.stripe.setKey({ secretKey: 'sk_live_...' });
|
|
320
|
+
|
|
321
|
+
// Generate a Stripe Connect onboarding link
|
|
322
|
+
const connect = await client.stripe.connect();
|
|
323
|
+
console.log(connect.url); // redirect seller here
|
|
324
|
+
|
|
325
|
+
// Disconnect Stripe
|
|
326
|
+
await client.stripe.disconnect();
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Readiness system
|
|
330
|
+
|
|
331
|
+
Every listing and account includes a `readiness` field that tells you whether it can currently accept payments.
|
|
332
|
+
|
|
333
|
+
- `listing.readiness.sellable` — `true` when buyers can complete a purchase
|
|
334
|
+
- `account.readiness.operational` — `true` when the account can sell
|
|
335
|
+
|
|
336
|
+
When `false`, an `actions` array explains what's needed and how to resolve each item. The `next` field points to the highest-priority action (prefers `kind: api`).
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
import { ActionKind } from 'listbee';
|
|
340
|
+
|
|
341
|
+
const account = await client.account.get();
|
|
342
|
+
if (!account.readiness.operational) {
|
|
343
|
+
for (const action of account.readiness.actions) {
|
|
344
|
+
if (action.kind === ActionKind.API) {
|
|
345
|
+
console.log(`API action: ${action.code} -> ${action.resolve.endpoint}`);
|
|
346
|
+
} else {
|
|
347
|
+
console.log(`Manual step: ${action.code} -> ${action.resolve.url}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
console.log(`Next action: ${account.readiness.next}`);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Pagination
|
|
355
|
+
|
|
356
|
+
`listings.list()` and `orders.list()` return a `CursorPage` with cursor-based pagination.
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// First page
|
|
360
|
+
const page = await client.listings.list({ limit: 10 });
|
|
361
|
+
console.log(page.data); // ListingResponse[]
|
|
362
|
+
console.log(page.has_more); // true if more pages exist
|
|
363
|
+
console.log(page.cursor); // cursor string for the next page
|
|
364
|
+
|
|
365
|
+
// Fetch next page
|
|
366
|
+
if (page.has_more) {
|
|
367
|
+
const nextPage = await client.listings.list({ limit: 10, cursor: page.cursor });
|
|
368
|
+
console.log(nextPage.data);
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Error handling
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
ListBeeError
|
|
376
|
+
├── APIConnectionError // network error — request never reached the server
|
|
377
|
+
├── APITimeoutError // request timed out
|
|
378
|
+
└── APIStatusError // server returned 4xx/5xx
|
|
379
|
+
├── AuthenticationError // 401 — invalid or missing API key
|
|
380
|
+
├── NotFoundError // 404 — resource not found
|
|
381
|
+
├── ConflictError // 409 — resource conflict
|
|
382
|
+
├── ValidationError // 422 — request validation failed
|
|
383
|
+
├── RateLimitError // 429 — rate limit exceeded
|
|
384
|
+
└── InternalServerError // 500+ — server-side error
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Catch specific errors:
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
import {
|
|
391
|
+
ListBee,
|
|
392
|
+
AuthenticationError,
|
|
393
|
+
NotFoundError,
|
|
394
|
+
RateLimitError,
|
|
395
|
+
ValidationError,
|
|
396
|
+
APIConnectionError,
|
|
397
|
+
APITimeoutError,
|
|
398
|
+
APIStatusError,
|
|
399
|
+
} from 'listbee';
|
|
400
|
+
|
|
401
|
+
const client = new ListBee({ apiKey: 'lb_...' });
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const listing = await client.listings.get('does-not-exist');
|
|
405
|
+
} catch (e) {
|
|
406
|
+
if (e instanceof NotFoundError) {
|
|
407
|
+
console.log(e.status); // 404
|
|
408
|
+
console.log(e.code); // machine-readable code
|
|
409
|
+
console.log(e.detail); // human-readable explanation
|
|
410
|
+
} else if (e instanceof AuthenticationError) {
|
|
411
|
+
console.log('Invalid API key');
|
|
412
|
+
} else if (e instanceof RateLimitError) {
|
|
413
|
+
console.log(`Rate limited. Resets at ${e.reset}, ${e.remaining}/${e.limit} remaining`);
|
|
414
|
+
} else if (e instanceof ValidationError) {
|
|
415
|
+
console.log(`Bad request — field: ${e.param}, detail: ${e.detail}`);
|
|
416
|
+
} else if (e instanceof APIConnectionError) {
|
|
417
|
+
console.log('Network error — check your connection');
|
|
418
|
+
} else if (e instanceof APITimeoutError) {
|
|
419
|
+
console.log('Request timed out');
|
|
420
|
+
} else if (e instanceof APIStatusError) {
|
|
421
|
+
console.log(`API error ${e.status}: ${e.detail}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Error responses follow [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) (Problem Details). All `APIStatusError` subclasses expose:
|
|
427
|
+
|
|
428
|
+
| Attribute | Type | Description |
|
|
429
|
+
|-----------|------|-------------|
|
|
430
|
+
| `status` | `number` | HTTP status code |
|
|
431
|
+
| `code` | `string` | Machine-readable error code |
|
|
432
|
+
| `detail` | `string` | Specific explanation |
|
|
433
|
+
| `title` | `string` | Short, stable error category label |
|
|
434
|
+
| `type` | `string` | URI identifying the error type |
|
|
435
|
+
| `param` | `string \| null` | Request field that caused the error |
|
|
436
|
+
|
|
437
|
+
`RateLimitError` additionally exposes `limit`, `remaining`, and `reset` (parsed from response headers).
|
|
438
|
+
|
|
439
|
+
## Configuration
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
import { ListBee } from 'listbee';
|
|
443
|
+
|
|
444
|
+
const client = new ListBee({
|
|
445
|
+
apiKey: 'lb_...',
|
|
446
|
+
timeoutMs: 60_000, // default: 30000
|
|
447
|
+
maxRetries: 5, // default: 3; retries on 429/500/502/503/504
|
|
448
|
+
baseUrl: 'https://api.listbee.so', // default; override for testing
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
`listings.create()` uses a default timeout of **120 seconds** because cover image processing can take longer. Pass `timeoutMs` to override:
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
const listing = await client.listings.create({
|
|
456
|
+
name: 'Quick listing',
|
|
457
|
+
price: 999,
|
|
458
|
+
content: 'https://example.com/file.pdf',
|
|
459
|
+
timeoutMs: 30_000, // override the 120s default for this call
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## Types and enums
|
|
464
|
+
|
|
465
|
+
All types are importable directly from `listbee`:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
import {
|
|
469
|
+
// Client
|
|
470
|
+
ListBee,
|
|
471
|
+
CursorPage,
|
|
472
|
+
|
|
473
|
+
// Response types
|
|
474
|
+
type ListingResponse,
|
|
475
|
+
type OrderResponse,
|
|
476
|
+
type WebhookResponse,
|
|
477
|
+
type AccountResponse,
|
|
478
|
+
type ApiKeyResponse,
|
|
479
|
+
type SignupResponse,
|
|
480
|
+
type VerifyResponse,
|
|
481
|
+
type StripeConnectSessionResponse,
|
|
482
|
+
type StoreResponse,
|
|
483
|
+
type StoreListResponse,
|
|
484
|
+
type DomainResponse,
|
|
485
|
+
type WebhookEventResponse,
|
|
486
|
+
type WebhookTestResponse,
|
|
487
|
+
|
|
488
|
+
// Enums (runtime values)
|
|
489
|
+
ContentType, // "file" | "url" | "text"
|
|
490
|
+
OrderStatus, // "completed"
|
|
491
|
+
WebhookEventType, // "order.completed" | "order.refunded" | ...
|
|
492
|
+
ActionCode, // "set_stripe_key" | "connect_stripe" | ...
|
|
493
|
+
ActionKind, // "api" | "human"
|
|
494
|
+
|
|
495
|
+
// Errors
|
|
496
|
+
ListBeeError,
|
|
497
|
+
APIStatusError,
|
|
498
|
+
APIConnectionError,
|
|
499
|
+
APITimeoutError,
|
|
500
|
+
AuthenticationError,
|
|
501
|
+
NotFoundError,
|
|
502
|
+
ConflictError,
|
|
503
|
+
ValidationError,
|
|
504
|
+
RateLimitError,
|
|
505
|
+
InternalServerError,
|
|
506
|
+
} from 'listbee';
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Enums are `as const` objects — use them to avoid magic strings:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
import { ContentType, WebhookEventType } from 'listbee';
|
|
513
|
+
|
|
514
|
+
// Check content type
|
|
515
|
+
if (listing.content_type === ContentType.FILE) {
|
|
516
|
+
console.log('Delivers a file');
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Subscribe to specific events
|
|
520
|
+
const webhook = await client.webhooks.create({
|
|
521
|
+
name: 'Orders only',
|
|
522
|
+
url: 'https://example.com/hooks',
|
|
523
|
+
events: [
|
|
524
|
+
WebhookEventType.ORDER_COMPLETED,
|
|
525
|
+
WebhookEventType.ORDER_REFUNDED,
|
|
526
|
+
],
|
|
527
|
+
});
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
## Tree-shaking
|
|
531
|
+
|
|
532
|
+
Import individual resources for smaller bundles:
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
import { WebhooksResource } from 'listbee/webhooks';
|
|
536
|
+
import { OrdersResource } from 'listbee/orders';
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## Requirements
|
|
540
|
+
|
|
541
|
+
- Node.js >= 18
|
|
542
|
+
|
|
543
|
+
## License
|
|
544
|
+
|
|
545
|
+
Apache-2.0. See [LICENSE](LICENSE).
|
|
546
|
+
|
|
547
|
+
## Links
|
|
548
|
+
|
|
549
|
+
- [Documentation](https://docs.listbee.so)
|
|
550
|
+
- [API Reference](https://docs.listbee.so/api)
|
|
551
|
+
- [GitHub](https://github.com/listbee-dev/listbee-typescript)
|
|
552
|
+
- [npm](https://www.npmjs.com/package/listbee)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base HTTP client for the ListBee SDK.
|
|
3
|
+
*/
|
|
4
|
+
import type { ListResponse } from './types/shared';
|
|
5
|
+
/** Options accepted by the ListBee client constructor. */
|
|
6
|
+
export interface ClientOptions {
|
|
7
|
+
/** Your ListBee API key (lb_...). Falls back to LISTBEE_API_KEY env var. */
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
/** API base URL. Default: https://api.listbee.so */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
/** Default request timeout in milliseconds. Default: 30000 */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
/** Max retries on 429/5xx responses. Default: 3 */
|
|
14
|
+
maxRetries?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Options for individual HTTP requests. */
|
|
17
|
+
export interface RequestOptions {
|
|
18
|
+
/** Request timeout in milliseconds. */
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
/** Whether to include the Authorization header. Default: true. */
|
|
21
|
+
authenticated?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** A cursor page holding one page of results. */
|
|
24
|
+
export declare class CursorPage<T> {
|
|
25
|
+
readonly object: "list";
|
|
26
|
+
readonly data: T[];
|
|
27
|
+
readonly has_more: boolean;
|
|
28
|
+
readonly cursor: string | null;
|
|
29
|
+
constructor(body: ListResponse<T>);
|
|
30
|
+
}
|
|
31
|
+
/** Internal HTTP response wrapper. */
|
|
32
|
+
interface HttpResponse {
|
|
33
|
+
status: number;
|
|
34
|
+
headers: Record<string, string>;
|
|
35
|
+
json(): Promise<unknown>;
|
|
36
|
+
text(): Promise<string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Low-level HTTP client with auth, retries, and error handling.
|
|
40
|
+
*/
|
|
41
|
+
export declare class BaseClient {
|
|
42
|
+
protected readonly _apiKey: string | undefined;
|
|
43
|
+
protected readonly _baseUrl: string;
|
|
44
|
+
protected readonly _timeoutMs: number;
|
|
45
|
+
protected readonly _maxRetries: number;
|
|
46
|
+
constructor(opts?: ClientOptions);
|
|
47
|
+
protected _ensureApiKey(): string;
|
|
48
|
+
protected _buildHeaders(authenticated?: boolean): Record<string, string>;
|
|
49
|
+
protected _shouldRetry(status: number, attempt: number): boolean;
|
|
50
|
+
protected _retryDelayMs(attempt: number, headers: Record<string, string>): number;
|
|
51
|
+
/** Perform an HTTP request with retry logic. */
|
|
52
|
+
_request(method: string, path: string, opts?: {
|
|
53
|
+
body?: unknown;
|
|
54
|
+
params?: Record<string, string | number | boolean>;
|
|
55
|
+
timeoutMs?: number;
|
|
56
|
+
authenticated?: boolean;
|
|
57
|
+
}): Promise<HttpResponse>;
|
|
58
|
+
get(path: string, params?: Record<string, string | number | boolean>, options?: RequestOptions): Promise<HttpResponse>;
|
|
59
|
+
post(path: string, body?: unknown, options?: RequestOptions): Promise<HttpResponse>;
|
|
60
|
+
put(path: string, body?: unknown, options?: RequestOptions): Promise<HttpResponse>;
|
|
61
|
+
patch(path: string, body?: unknown, options?: RequestOptions): Promise<HttpResponse>;
|
|
62
|
+
delete(path: string, options?: RequestOptions): Promise<HttpResponse>;
|
|
63
|
+
getPage<T>(path: string, params: Record<string, string | number | boolean>, parse: (item: unknown) => T, options?: RequestOptions): Promise<CursorPage<T>>;
|
|
64
|
+
}
|
|
65
|
+
export {};
|