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.
Files changed (146) hide show
  1. package/README.md +552 -0
  2. package/dist/cjs/base-client.d.ts +65 -0
  3. package/dist/cjs/base-client.js +167 -0
  4. package/dist/cjs/base-client.js.map +1 -0
  5. package/dist/cjs/client.d.ts +58 -0
  6. package/dist/cjs/client.js +54 -0
  7. package/dist/cjs/client.js.map +1 -0
  8. package/dist/cjs/constants.d.ts +17 -0
  9. package/dist/cjs/constants.js +21 -0
  10. package/dist/cjs/constants.js.map +1 -0
  11. package/dist/cjs/errors.d.ts +89 -0
  12. package/dist/cjs/errors.js +141 -0
  13. package/dist/cjs/errors.js.map +1 -0
  14. package/dist/cjs/index.d.ts +26 -0
  15. package/dist/cjs/index.js +49 -0
  16. package/dist/cjs/index.js.map +1 -0
  17. package/dist/cjs/resources/account.d.ts +25 -0
  18. package/dist/cjs/resources/account.js +39 -0
  19. package/dist/cjs/resources/account.js.map +1 -0
  20. package/dist/cjs/resources/api-keys.d.ts +14 -0
  21. package/dist/cjs/resources/api-keys.js +26 -0
  22. package/dist/cjs/resources/api-keys.js.map +1 -0
  23. package/dist/cjs/resources/index.d.ts +7 -0
  24. package/dist/cjs/resources/index.js +18 -0
  25. package/dist/cjs/resources/index.js.map +1 -0
  26. package/dist/cjs/resources/listings.d.ts +70 -0
  27. package/dist/cjs/resources/listings.js +161 -0
  28. package/dist/cjs/resources/listings.js.map +1 -0
  29. package/dist/cjs/resources/orders.d.ts +11 -0
  30. package/dist/cjs/resources/orders.js +36 -0
  31. package/dist/cjs/resources/orders.js.map +1 -0
  32. package/dist/cjs/resources/signup.d.ts +16 -0
  33. package/dist/cjs/resources/signup.js +21 -0
  34. package/dist/cjs/resources/signup.js.map +1 -0
  35. package/dist/cjs/resources/stores.d.ts +31 -0
  36. package/dist/cjs/resources/stores.js +67 -0
  37. package/dist/cjs/resources/stores.js.map +1 -0
  38. package/dist/cjs/resources/stripe.d.ts +15 -0
  39. package/dist/cjs/resources/stripe.js +25 -0
  40. package/dist/cjs/resources/stripe.js.map +1 -0
  41. package/dist/cjs/resources/webhooks.d.ts +15 -0
  42. package/dist/cjs/resources/webhooks.js +55 -0
  43. package/dist/cjs/resources/webhooks.js.map +1 -0
  44. package/dist/cjs/types/account.d.ts +47 -0
  45. package/dist/cjs/types/account.js +6 -0
  46. package/dist/cjs/types/account.js.map +1 -0
  47. package/dist/cjs/types/api-key.d.ts +18 -0
  48. package/dist/cjs/types/api-key.js +6 -0
  49. package/dist/cjs/types/api-key.js.map +1 -0
  50. package/dist/cjs/types/index.d.ts +10 -0
  51. package/dist/cjs/types/index.js +10 -0
  52. package/dist/cjs/types/index.js.map +1 -0
  53. package/dist/cjs/types/listing.d.ts +177 -0
  54. package/dist/cjs/types/listing.js +6 -0
  55. package/dist/cjs/types/listing.js.map +1 -0
  56. package/dist/cjs/types/order.d.ts +42 -0
  57. package/dist/cjs/types/order.js +6 -0
  58. package/dist/cjs/types/order.js.map +1 -0
  59. package/dist/cjs/types/shared.d.ts +87 -0
  60. package/dist/cjs/types/shared.js +41 -0
  61. package/dist/cjs/types/shared.js.map +1 -0
  62. package/dist/cjs/types/signup.d.ts +24 -0
  63. package/dist/cjs/types/signup.js +6 -0
  64. package/dist/cjs/types/signup.js.map +1 -0
  65. package/dist/cjs/types/store.d.ts +70 -0
  66. package/dist/cjs/types/store.js +6 -0
  67. package/dist/cjs/types/store.js.map +1 -0
  68. package/dist/cjs/types/stripe.d.ts +12 -0
  69. package/dist/cjs/types/stripe.js +6 -0
  70. package/dist/cjs/types/stripe.js.map +1 -0
  71. package/dist/cjs/types/webhook.d.ts +88 -0
  72. package/dist/cjs/types/webhook.js +6 -0
  73. package/dist/cjs/types/webhook.js.map +1 -0
  74. package/dist/esm/base-client.d.ts +65 -0
  75. package/dist/esm/base-client.js +159 -0
  76. package/dist/esm/base-client.js.map +1 -0
  77. package/dist/esm/client.d.ts +58 -0
  78. package/dist/esm/client.js +50 -0
  79. package/dist/esm/client.js.map +1 -0
  80. package/dist/esm/constants.d.ts +17 -0
  81. package/dist/esm/constants.js +18 -0
  82. package/dist/esm/constants.js.map +1 -0
  83. package/dist/esm/errors.d.ts +89 -0
  84. package/dist/esm/errors.js +124 -0
  85. package/dist/esm/errors.js.map +1 -0
  86. package/dist/esm/index.d.ts +26 -0
  87. package/dist/esm/index.js +20 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/resources/account.d.ts +25 -0
  90. package/dist/esm/resources/account.js +35 -0
  91. package/dist/esm/resources/account.js.map +1 -0
  92. package/dist/esm/resources/api-keys.d.ts +14 -0
  93. package/dist/esm/resources/api-keys.js +21 -0
  94. package/dist/esm/resources/api-keys.js.map +1 -0
  95. package/dist/esm/resources/index.d.ts +7 -0
  96. package/dist/esm/resources/index.js +8 -0
  97. package/dist/esm/resources/index.js.map +1 -0
  98. package/dist/esm/resources/listings.d.ts +70 -0
  99. package/dist/esm/resources/listings.js +156 -0
  100. package/dist/esm/resources/listings.js.map +1 -0
  101. package/dist/esm/resources/orders.d.ts +11 -0
  102. package/dist/esm/resources/orders.js +31 -0
  103. package/dist/esm/resources/orders.js.map +1 -0
  104. package/dist/esm/resources/signup.d.ts +16 -0
  105. package/dist/esm/resources/signup.js +17 -0
  106. package/dist/esm/resources/signup.js.map +1 -0
  107. package/dist/esm/resources/stores.d.ts +31 -0
  108. package/dist/esm/resources/stores.js +63 -0
  109. package/dist/esm/resources/stores.js.map +1 -0
  110. package/dist/esm/resources/stripe.d.ts +15 -0
  111. package/dist/esm/resources/stripe.js +21 -0
  112. package/dist/esm/resources/stripe.js.map +1 -0
  113. package/dist/esm/resources/webhooks.d.ts +15 -0
  114. package/dist/esm/resources/webhooks.js +49 -0
  115. package/dist/esm/resources/webhooks.js.map +1 -0
  116. package/dist/esm/types/account.d.ts +47 -0
  117. package/dist/esm/types/account.js +5 -0
  118. package/dist/esm/types/account.js.map +1 -0
  119. package/dist/esm/types/api-key.d.ts +18 -0
  120. package/dist/esm/types/api-key.js +5 -0
  121. package/dist/esm/types/api-key.js.map +1 -0
  122. package/dist/esm/types/index.d.ts +10 -0
  123. package/dist/esm/types/index.js +2 -0
  124. package/dist/esm/types/index.js.map +1 -0
  125. package/dist/esm/types/listing.d.ts +177 -0
  126. package/dist/esm/types/listing.js +5 -0
  127. package/dist/esm/types/listing.js.map +1 -0
  128. package/dist/esm/types/order.d.ts +42 -0
  129. package/dist/esm/types/order.js +5 -0
  130. package/dist/esm/types/order.js.map +1 -0
  131. package/dist/esm/types/shared.d.ts +87 -0
  132. package/dist/esm/types/shared.js +38 -0
  133. package/dist/esm/types/shared.js.map +1 -0
  134. package/dist/esm/types/signup.d.ts +24 -0
  135. package/dist/esm/types/signup.js +5 -0
  136. package/dist/esm/types/signup.js.map +1 -0
  137. package/dist/esm/types/store.d.ts +70 -0
  138. package/dist/esm/types/store.js +5 -0
  139. package/dist/esm/types/store.js.map +1 -0
  140. package/dist/esm/types/stripe.d.ts +12 -0
  141. package/dist/esm/types/stripe.js +5 -0
  142. package/dist/esm/types/stripe.js.map +1 -0
  143. package/dist/esm/types/webhook.d.ts +88 -0
  144. package/dist/esm/types/webhook.js +5 -0
  145. package/dist/esm/types/webhook.js.map +1 -0
  146. 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 {};