Package Exports
- listbee
Readme
listbee
Official TypeScript SDK for the ListBee API — one API call to sell and deliver digital content.
- Zero runtime dependencies (native fetch, Node >= 18)
- Types generated from OpenAPI spec — zero drift
- Full error hierarchy (RFC 9457)
- Cursor-based pagination
- Retry with exponential backoff
- Idempotency support
Install
npm install listbeepnpm add listbeeQuick start
import { ListBee } from 'listbee';
const client = new ListBee({ apiKey: 'lb_...' });
// Create a listing, set a deliverable, publish
const listing = await client.listings.create({
name: 'SEO Playbook',
price: 2900, // $29.00 in cents
description: 'A comprehensive guide to modern SEO.',
});
await client.listings.setDeliverables(listing.id, {
url: 'https://example.com/seo-playbook.pdf',
});
const published = await client.listings.publish(listing.id);
console.log(published.url); // https://buy.listbee.so/r7kq2xy9Or read from the environment:
export LISTBEE_API_KEY="lb_..."const client = new ListBee(); // reads LISTBEE_API_KEY automaticallyAuthentication
Pass your API key explicitly or via the LISTBEE_API_KEY environment variable.
const client = new ListBee({ apiKey: 'lb_...' });
const client = new ListBee(); // env varThe key is validated lazily — an AuthenticationError is raised only when you make the first API call. API keys start with lb_. Get yours at listbee.so.
Resources
| Resource | Methods |
|---|---|
listings |
create, get, list, update, publish, setDeliverables, removeDeliverables, delete |
orders |
get, list, deliver, refund |
customers |
get, list |
files |
upload |
webhooks |
create, get, list, update, delete, listEvents, retryEvent, test, verify |
account |
get, update, delete |
apiKeys |
list, create, delete |
signup |
create, verify |
stripe |
connect, disconnect |
Listings
// Create
const listing = await client.listings.create({
name: 'SEO Playbook 2026',
price: 2900,
description: 'A comprehensive guide to modern SEO techniques.',
tagline: 'Updated for 2026 algorithm changes',
highlights: ['50+ pages', 'Actionable tips', 'Free updates'],
cta: 'Get Instant Access',
cover_url: 'https://example.com/cover.png',
compare_at_price: 3900,
metadata: { source: 'n8n', campaign: 'launch-week' },
});
console.log(listing.id); // lst_r7kq2xy9m3pR5tW1
// Set deliverables (file, URL, or text)
await client.listings.setDeliverables(listing.id, {
url: 'https://example.com/seo-playbook.pdf',
});
// Publish
const published = await client.listings.publish(listing.id);
console.log(published.url); // https://buy.listbee.so/r7kq2xy9
// Get by ID
const listing = await client.listings.get('lst_r7kq2xy9m3pR5tW1');
// List — with filters
const page = await client.listings.list({
status: 'published',
limit: 20,
});
for (const l of page.data) {
console.log(l.id, l.name, l.status);
}
console.log(page.total_count); // total matching listings
// Update
await client.listings.update('lst_r7kq2xy9m3pR5tW1', { price: 3900 });
// Remove deliverables (revert to external fulfillment)
await client.listings.removeDeliverables('lst_r7kq2xy9m3pR5tW1');
// Delete
await client.listings.delete('lst_r7kq2xy9m3pR5tW1');Orders
// List — with filters
const page = await client.orders.list({
status: 'paid',
buyer_email: 'buyer@example.com',
created_after: new Date('2026-03-01'),
created_before: '2026-03-31T23:59:59Z',
});
console.log(page.total_count);
// Get by ID
const order = await client.orders.get('ord_9xM4kP7nR2qT5wY1');
console.log(order.status); // "pending" | "paid" | "fulfilled" | "canceled" | "failed"
console.log(order.checkout_data); // custom checkout field values
console.log(order.paid_at); // ISO 8601 timestamp
// Deliver — push content to the buyer (external fulfillment)
const fulfilled = await client.orders.deliver('ord_9xM4kP7nR2qT5wY1', {
content: 'Your AI-generated report is ready.',
content_type: 'text',
});
console.log(fulfilled.status); // "fulfilled"
// Or with a URL
await client.orders.deliver('ord_9xM4kP7nR2qT5wY1', {
content_url: 'https://example.com/report.pdf',
});
// Refund
const refunded = await client.orders.refund('ord_9xM4kP7nR2qT5wY1');
console.log(refunded.status); // "canceled"Customers
// List customers
const page = await client.customers.list({ limit: 20, email: 'buyer@example.com' });
for (const c of page.data) {
console.log(c.id, c.email);
}
// Get a customer
const customer = await client.customers.get('cus_7kQ2xY9mN3pR5tW1');
console.log(customer.email, customer.order_count);Files
import { createReadStream } from 'fs';
// Upload a file (multipart, native FormData)
const file = await client.files.upload({
file: createReadStream('/path/to/report.pdf'),
filename: 'report.pdf',
});
console.log(file.id); // use this ID in setDeliverables
// Then attach to a listing
await client.listings.setDeliverables(listing.id, { file_id: file.id });Webhooks
import { ListBee, WebhookEventType } from 'listbee';
const client = new ListBee({ apiKey: 'lb_...' });
// Create — subscribe to specific events
const webhook = await client.webhooks.create({
name: 'Production endpoint',
url: 'https://example.com/webhooks/listbee',
events: [
WebhookEventType.ORDER_PAID,
WebhookEventType.ORDER_FULFILLED,
WebhookEventType.CUSTOMER_CREATED,
],
});
console.log(webhook.id); // wh_3mK8nP2qR5tW7xY1
console.log(webhook.secret); // HMAC signing key — save this
// Verify an incoming webhook (HMAC-SHA256, uses crypto.subtle — no dependencies)
const isValid = await client.webhooks.verify({
payload: rawBodyString,
signature: req.headers['listbee-signature'],
secret: webhook.secret,
});
// List delivery events
const events = await client.webhooks.listEvents('wh_3mK8nP2qR5tW7xY1', { status: 'failed' });
// Retry a failed event
await client.webhooks.retryEvent('wh_3mK8nP2qR5tW7xY1', 'evt_abc123');
// Update, test, delete
await client.webhooks.update('wh_3mK8nP2qR5tW7xY1', { enabled: false });
await client.webhooks.test('wh_3mK8nP2qR5tW7xY1');
await client.webhooks.delete('wh_3mK8nP2qR5tW7xY1');Account
const account = await client.account.get();
console.log(account.id); // acc_7kQ2xY9mN3pR5tW1
console.log(account.email);
console.log(account.plan); // free | growth | scale
console.log(account.readiness.operational);
await client.account.update({ ga_measurement_id: 'G-XXXXXXXXXX' });
await client.account.delete();Signup
Agent self-service onboarding — no API key required:
const client = new ListBee(); // no API key needed
await client.signup.create({ email: 'seller@example.com' });
const result = await client.signup.verify({ email: 'seller@example.com', code: '123456' });
console.log(result.api_key); // lb_... (one-time display)API keys
const keys = await client.apiKeys.list();
const newKey = await client.apiKeys.create({ name: 'CI pipeline' });
console.log(newKey.key); // lb_... (save this immediately)
await client.apiKeys.delete('lbk_7kQ2xY9mN3pR5tW1');Stripe
// Generate a Stripe Connect onboarding link
const connect = await client.stripe.connect();
console.log(connect.url); // redirect seller here
// Disconnect Stripe
await client.stripe.disconnect();Fulfillment modes
- Managed — ListBee delivers digital content automatically. Call
setDeliverables()on the listing, thenpublish(). - External — ListBee fires
order.paidwebhook, your app handles delivery. Callorders.deliver()to push content back.
// External fulfillment — AI-generated content
const listing = await client.listings.create({
name: 'Custom SEO Report',
price: 4900,
fulfillment: 'external',
checkout_schema: [
{ type: 'text', key: 'website_url', label: 'Your website URL', required: true },
],
});
await client.listings.publish(listing.id);
// On order.paid webhook:
await client.orders.deliver(order.id, {
content: generatedReport,
content_type: 'text',
});Readiness system
Every listing and account includes a readiness field.
const account = await client.account.get();
if (!account.readiness.operational) {
for (const action of account.readiness.actions) {
if (action.kind === 'api') {
console.log(`API action: ${action.code} -> ${action.resolve.endpoint}`);
} else {
console.log(`Manual step: ${action.code} -> ${action.resolve.url}`);
}
}
}Idempotency
Pass idempotencyKey to any mutating request. Same key within 24h returns the cached response:
await client.listings.create(
{ name: 'SEO Playbook', price: 2900 },
{ idempotencyKey: 'create-listing-campaign-2026' },
);Pagination
const page = await client.listings.list({ limit: 10 });
console.log(page.data); // ListingResponse[]
console.log(page.has_more); // true if more pages exist
console.log(page.cursor); // pass to next call
console.log(page.total_count); // total matching items
if (page.has_more) {
const nextPage = await client.listings.list({ limit: 10, cursor: page.cursor });
}Error handling
ListBeeError
├── APIConnectionError network error — request never reached the server
├── APITimeoutError request timed out
└── APIStatusError server returned 4xx/5xx
├── BadRequestError 400
├── AuthenticationError 401
├── ForbiddenError 403
├── NotFoundError 404
├── ConflictError 409
├── PayloadTooLargeError 413
├── ValidationError 422
├── RateLimitError 429
└── InternalServerError 500+import { NotFoundError, AuthenticationError, RateLimitError, ErrorCode } from 'listbee';
try {
await client.listings.get('lst_does-not-exist');
} catch (e) {
if (e instanceof NotFoundError) {
console.log(e.status); // 404
console.log(e.code); // ErrorCode value
console.log(e.detail); // human-readable explanation
} else if (e instanceof RateLimitError) {
console.log(`Rate limited. Resets at ${e.reset}`);
}
}All APIStatusError subclasses expose: status, code (ErrorCode), detail, title, type, param.
Configuration
const client = new ListBee({
apiKey: 'lb_...',
timeoutMs: 60_000, // default: 30000
maxRetries: 5, // default: 3; retries on 429/500/502/503/504
baseUrl: 'https://api.listbee.so', // override for testing
});Types
All types are importable from listbee:
import {
ListBee,
CursorPage,
ErrorCode,
// Response types
type ListingResponse,
type OrderResponse,
type CustomerResponse,
type FileResponse,
type WebhookResponse,
type AccountResponse,
type ApiKeyResponse,
type SignupResponse,
type VerifyResponse,
type WebhookEventResponse,
type WebhookTestResponse,
type CheckoutField,
// Enums
DeliverableType, // "file" | "url" | "text"
FulfillmentMode, // "managed" | "external"
ListingStatus, // "draft" | "published"
OrderStatus, // "pending" | "paid" | "fulfilled" | "canceled" | "failed"
WebhookEventType,
ActionCode,
ActionKind,
// Errors
ListBeeError,
APIStatusError,
APIConnectionError,
APITimeoutError,
BadRequestError,
AuthenticationError,
ForbiddenError,
NotFoundError,
ConflictError,
PayloadTooLargeError,
ValidationError,
RateLimitError,
InternalServerError,
} from 'listbee';Requirements
- Node.js >= 18
License
Apache-2.0. See LICENSE.