Official Python SDK for the ListBee API — one API call to sell and deliver digital content.
Project description
listbee
Official Python SDK for the ListBee API — sell anything, payment collected, digital delivery handled.
Install
pip install listbee
uv add listbee
Quick Start
from listbee import ListBee, CheckoutField
client = ListBee(api_key="lb_...")
Resources
| Resource | Methods |
|---|---|
| Listings | create, get, list, update, delete, set_deliverables, remove_deliverables, add_deliverable, remove_deliverable, create_complete, publish |
| Orders | get, list, fulfill, refund |
| Customers | get, list |
| Files | upload |
| Webhooks | create, list, update, delete, list_events, retry_event, test |
| Account | get, update, delete |
| Stripe | connect, disconnect |
| API Keys | create, list, delete |
| Utility | ping, plans |
from listbee import ListBee, Deliverable
client = ListBee(api_key="lb_...")
# Static content — ListBee delivers pre-attached file automatically
# One-shot: create listing + attach deliverable + publish
listing = client.listings.create_complete(
name="SEO Playbook",
price=2900,
deliverables=[Deliverable.url("https://example.com/seo-playbook.pdf")],
)
listing = client.listings.publish(listing.slug)
print(listing.url) # https://buy.listbee.so/r7kq2xy9
# Webhook content — you handle delivery via webhooks
from listbee import CheckoutField
listing = client.listings.create(
name="Custom Consulting",
price=3500,
content_type="webhook",
checkout_schema=[
CheckoutField.text("brief", label="Project Brief", sort_order=0),
],
)
listing = client.listings.publish(listing.slug)
Using an environment variable instead:
export LISTBEE_API_KEY="lb_..."
from listbee import ListBee
from listbee import ListBee, Deliverable
client = ListBee() # reads LISTBEE_API_KEY automatically
listing = client.listings.create_complete(
name="SEO Playbook",
price=2900,
deliverables=[Deliverable.url("https://example.com/seo-playbook.pdf")],
)
listing = client.listings.publish(listing.slug)
print(listing.url)
Authentication
Pass your API key explicitly or via the LISTBEE_API_KEY environment variable.
import os
from listbee import ListBee
# Explicit key
client = ListBee(api_key="lb_...")
# Environment variable (LISTBEE_API_KEY)
client = ListBee()
# os.environ lookup
client = ListBee(api_key=os.environ["LISTBEE_API_KEY"])
The key is validated lazily — the client constructs successfully even with a missing or invalid key. A ListBeeError (specifically AuthenticationError) is raised only when you make the first API call.
API keys start with lb_. Get yours at console.listbee.so.
Resources
Listings
from listbee import ListBee
client = ListBee(api_key="lb_...")
# Create — static content (ListBee delivers pre-attached file)
# Listings start as drafts. Attach deliverables then publish.
listing = client.listings.create(
name="SEO Playbook",
price=2900, # $29.00 in cents
content_type="static",
)
# Create — webhook content (you handle delivery via webhooks)
from listbee import CheckoutField
listing = client.listings.create(
name="Custom Consulting",
price=3500,
content_type="webhook",
checkout_schema=[
CheckoutField.text("brief", label="Project Brief", sort_order=0),
],
)
# Create — generated content (your system creates content after payment)
listing = client.listings.create(
name="AI Report",
price=2900,
content_type="generated",
)
# Create — all optional params
listing = 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", # buy button text; defaults to "Buy Now"
cover_url="https://example.com/cover.png",
compare_at_price=3900, # strikethrough price
badges=["Limited time", "Best seller"],
cover_blur="auto", # "auto" | "true" | "false"
rating=4.8,
rating_count=1243,
reviews=[
{"name": "Clara D.", "rating": 5.0, "content": "Excellent quality content."}
],
faqs=[
{"q": "Is this for beginners?", "a": "Yes, completely beginner-friendly."}
],
metadata={"source": "n8n", "campaign": "launch-week"},
)
print(listing.id) # lst_r7kq2xy9m3pR5tW1
# Attach deliverables and publish when ready
from listbee import Deliverable
client.listings.set_deliverables(
listing.slug,
deliverables=[Deliverable.url("https://example.com/seo-playbook.pdf")],
)
listing = client.listings.publish(listing.slug)
print(listing.url) # https://buy.listbee.so/m3pr5tw1
# Get by slug
listing = client.listings.get("m3pr5tw1")
# List — auto-paginates
for listing in client.listings.list():
print(listing.slug, listing.name)
# Update — partial updates
updated = client.listings.update(
"r7kq2xy9",
name="SEO Playbook 2026 Updated",
price=3900,
)
# Update content type and checkout schema
from listbee import CheckoutField
updated = client.listings.update(
"r7kq2xy9",
content_type="webhook",
checkout_schema=[
CheckoutField.text("notes", label="Special Instructions", sort_order=0),
],
)
# Raw dicts also accepted for backward compatibility:
updated = client.listings.update(
"r7kq2xy9",
checkout_schema=[
{"key": "notes", "label": "Special Instructions", "type": "text", "sort_order": 0},
],
)
# Set deliverables on a draft listing (one or more)
client.listings.set_deliverables(
"r7kq2xy9",
deliverables=[
Deliverable.url("https://example.com/seo-playbook.pdf"),
],
)
# Remove all deliverables from a draft listing
client.listings.remove_deliverables("r7kq2xy9")
# Add a single deliverable
client.listings.add_deliverable("r7kq2xy9", Deliverable.url("https://example.com/playbook.pdf"))
client.listings.add_deliverable("r7kq2xy9", Deliverable.text("Your license key: XXXX-XXXX"))
with open("guide.pdf", "rb") as f:
file = client.files.upload(file=f, filename="guide.pdf")
client.listings.add_deliverable("r7kq2xy9", Deliverable.from_token(file.id))
# Remove a single deliverable by del_ ID
client.listings.remove_deliverable("r7kq2xy9", "del_4hR9nK2mQ7tV5wX1")
# Create a listing and attach deliverables in one call
listing = client.listings.create_complete(
name="SEO Playbook",
price=2900,
deliverables=[
Deliverable.url("https://example.com/seo-playbook.pdf"),
],
)
listing = client.listings.publish(listing.slug)
# Publish a draft listing — makes it live and purchasable
listing = client.listings.publish("r7kq2xy9")
print(listing.status) # "published"
# Delete
client.listings.delete("m3pr5tw1")
Orders
# List all orders
for order in client.orders.list():
print(order.id, order.status)
# Filter by status
for order in client.orders.list(status="paid"):
print(order.id, order.buyer_email)
# Get by ID
order = client.orders.get("ord_9xM4kP7nR2qT5wY1")
print(order.listing_id, order.amount)
print(order.checkout_data) # custom fields from checkout
print(order.content_type) # "static" | "generated" | "webhook"
print(order.payment_status) # "unpaid" | "paid" | "refunded"
print(order.listing_snapshot) # listing data at time of purchase
print(order.seller_snapshot) # seller data at time of purchase
print(order.paid_at) # when payment was confirmed
print(order.handed_off_at) # when handed to seller (webhook orders only)
# Fulfill a generated order — push deliverables for ListBee to deliver
order = client.orders.fulfill("ord_9xM4kP7nR2qT5wY1")
print(order.status) # "fulfilled"
# Fulfill with dynamic content — push deliverables for ListBee to deliver
from listbee import Deliverable
order = client.orders.fulfill(
"ord_9xM4kP7nR2qT5wY1",
deliverables=[
Deliverable.text("Here is your personalized report..."),
],
)
print(order.status) # "fulfilled"
# Fulfill with a URL
order = client.orders.fulfill(
"ord_9xM4kP7nR2qT5wY1",
deliverables=[
Deliverable.url("https://example.com/generated-report.pdf"),
],
)
# Refund an order — issues a full refund and marks order canceled
order = client.orders.refund("ord_9xM4kP7nR2qT5wY1")
print(order.status) # "canceled"
Webhooks
from listbee import WebhookEventType
# Create — subscribe to specific events
webhook = client.webhooks.create(
name="Production endpoint",
url="https://example.com/webhooks/listbee",
events=[
WebhookEventType.ORDER_PAID,
WebhookEventType.ORDER_FULFILLED,
WebhookEventType.ORDER_SHIPPED,
WebhookEventType.ORDER_REFUNDED,
],
)
print(webhook.id) # wh_3mK8nP2qR5tW7xY1
print(webhook.secret)
# Create — receive all events (omit events param)
webhook = client.webhooks.create(
name="Catch-all",
url="https://example.com/webhooks/listbee-all",
)
# List
webhooks = client.webhooks.list()
for wh in webhooks:
print(wh.id, wh.name, wh.enabled)
# Update — disable without deleting
webhook = client.webhooks.update("wh_3mK8nP2qR5tW7xY1", enabled=False)
# Update — change URL and events
webhook = client.webhooks.update(
"wh_3mK8nP2qR5tW7xY1",
url="https://example.com/webhooks/v2",
events=[WebhookEventType.ORDER_PAID],
)
# Retry a failed webhook event delivery
client.webhooks.retry_event("wh_3mK8nP2qR5tW7xY1", event_id="evt_2nL9oQ3rS6uX8zV2")
# Delete
client.webhooks.delete("wh_3mK8nP2qR5tW7xY1")
Account
account = client.account.get()
print(account.id) # acc_7kQ2xY9mN3pR5tW1
print(account.email) # seller@example.com
print(account.plan) # free | growth | scale
print(account.fee_rate) # "0.10" (10%)
print(account.readiness.operational)
# Delete account — irreversible
client.account.delete()
API Keys
# List all API keys
for key in client.api_keys.list():
print(key.id, key.label)
# Create a new key — the key value is only shown once
new_key = client.api_keys.create(label="CI pipeline")
print(new_key.key) # lb_... (save this immediately)
# Delete a key
client.api_keys.delete("lbk_7kQ2xY9mN3pR5tW1")
Customers
# List all customers (buyers who have placed orders)
for customer in client.customers.list():
print(customer.email, customer.order_count)
# Get a customer by ID
customer = client.customers.get("acc_4hR9nK2mQ7tV5wX1")
print(customer.email)
print(customer.total_spent) # total amount in cents
print(customer.order_count)
Files
from listbee import Deliverable
# Upload a file to use as a deliverable
with open("playbook.pdf", "rb") as f:
file = client.files.upload(file=f, filename="playbook.pdf")
print(file.id) # file token to pass to Deliverable.from_token()
print(file.url) # CDN URL
# Then attach to a listing using the uploaded file token
client.listings.set_deliverables(
"r7kq2xy9",
deliverables=[Deliverable.from_token(file.id)],
)
Stripe
# Generate a Stripe Connect onboarding link
connect = client.stripe.connect()
print(connect.url) # redirect seller here
# Disconnect Stripe
client.stripe.disconnect()
Utility
# Check API connectivity
response = client.utility.ping()
print(response.status) # "ok"
# List available pricing plans (no authentication required)
plans = client.utility.plans()
for plan in plans.data:
print(f"{plan.name}: ${plan.price_monthly / 100}/month (fee: {plan.fee_rate})")
Content Types
ListBee supports three content types that determine how orders are fulfilled:
Static — ListBee delivers pre-attached digital content (files, URLs, text) automatically on payment via access grants.
from listbee import Deliverable
# One-shot: create listing + attach deliverables + publish
listing = client.listings.create_complete(
name="SEO Playbook",
price=2900,
deliverables=[
Deliverable.url("https://example.com/seo-playbook.pdf"),
],
)
listing = client.listings.publish(listing.slug)
# Add or remove individual deliverables after creation
client.listings.add_deliverable(listing.slug, Deliverable.text("Bonus: license key XXXX-XXXX"))
client.listings.remove_deliverable(listing.slug, "del_4hR9nK2mQ7tV5wX1")
Upload a file and use it as a deliverable:
with open("playbook.pdf", "rb") as f:
file = client.files.upload(file=f, filename="playbook.pdf")
client.listings.add_deliverable(listing.slug, Deliverable.from_token(file.id))
Generated — ListBee fires order.paid webhook, your system generates content and pushes it back via POST /fulfill. ListBee then delivers it to the buyer.
from listbee import CheckoutField, Deliverable
listing = client.listings.create(
name="Custom AI Report",
price=4900,
content_type="generated",
checkout_schema=[
CheckoutField.text("topic", label="Report Topic", sort_order=0),
],
)
listing = client.listings.publish(listing.slug)
# When you receive the order.paid webhook, generate content and fulfill:
order = client.orders.fulfill(
"ord_9xM4kP7nR2qT5wY1",
deliverables=[
Deliverable.text("Your personalized report..."),
],
)
Webhook — ListBee fires order.paid webhook, your app handles delivery entirely. Use for physical goods, services, or anything outside ListBee.
listing = client.listings.create(
name="Custom Consulting",
price=4900,
content_type="webhook",
)
listing = client.listings.publish(listing.slug)
# Receive order.paid webhook and handle delivery yourself
Use order.content_type to branch post-payment logic without re-fetching the listing:
order = client.orders.get("ord_9xM4kP7nR2qT5wY1")
if order.content_type == "generated":
# Generate content and call orders.fulfill()
pass
elif order.content_type == "webhook":
# Handle delivery in your own system
pass
# static orders are auto-fulfilled by ListBee — no action needed
Readiness System
Every listing and account includes a readiness field that tells you whether it can currently accept payments.
listing.readiness.sellable—Truewhen buyers can complete a purchaseaccount.readiness.operational—Truewhen the account can sell
When False, an actions list explains what's needed and how to resolve each item. The next field points to the highest-priority action (prefers kind: api).
from listbee import ActionKind
account = client.account.get()
if not account.readiness.operational:
for action in account.readiness.actions:
if action.kind == ActionKind.API:
print(f"API action: {action.code} -> {action.resolve.endpoint}")
else:
print(f"Manual step: {action.code} -> {action.resolve.url}")
# Highest priority action
print(f"Next action: {account.readiness.next}")
Listing readiness follows the same shape:
listing = client.listings.get("r7kq2xy9")
if not listing.readiness.sellable:
for action in listing.readiness.actions:
print(action.code, action.message)
print(f"Next: {listing.readiness.next}")
Action codes:
| Code | Meaning |
|---|---|
connect_stripe |
No Stripe account connected — start Connect onboarding |
enable_charges |
Stripe charges are disabled — complete Stripe onboarding |
update_billing |
ListBee subscription payment failed or unpaid |
configure_webhook |
Webhook content_type listing needs a webhook endpoint |
publish_listing |
Listing is a draft — publish to make it purchasable |
webhook_disabled |
Webhook endpoint is disabled |
Webhook Signature Verification
Verify that incoming webhook requests genuinely come from ListBee before processing them.
from listbee import verify_signature, WebhookVerificationError
# In your webhook handler (e.g. FastAPI, Flask, Django):
payload = request.body # raw bytes — do not parse first
signature = request.headers["listbee-signature"]
secret = "whsec_..." # from webhook.secret at creation time
try:
verify_signature(payload=payload, signature=signature, secret=secret)
except WebhookVerificationError:
# Signature invalid — reject the request
return Response(status_code=401)
# Signature valid — safe to process the event
event = json.loads(payload)
verify_signature raises WebhookVerificationError (a subclass of ListBeeError) if the signature is missing, malformed, or does not match.
Utility
Verify API connectivity and that your API key is valid:
response = client.utility.ping()
print(response.status) # "ok"
For async:
response = await client.utility.ping()
print(response.status) # "ok"
Pagination
listings.list() and orders.list() return a CursorPage that auto-fetches subsequent pages when iterated.
# Auto-pagination — iterates all pages transparently
for listing in client.listings.list():
print(listing.name)
# Manual page control — access current page directly
page = client.listings.list(limit=10)
print(page.data) # list of ListingResponse on this page
print(page.has_more) # True if more pages exist
print(page.cursor) # cursor string for the next page
# Fetch next page manually
if page.has_more:
next_page = client.listings.list(limit=10, cursor=page.cursor)
print(next_page.data)
# Collect all pages into a single list
all_listings = page.to_list(limit=None)
print(len(all_listings)) # total items across all pages
Helper Methods & Properties
The SDK includes convenience helpers for common patterns and state checks.
Order State Helpers
order = client.orders.get("ord_9xM4kP7nR2qT5wY1")
# Payment state checkers
if order.is_paid:
print("Order has been paid")
if order.is_refunded:
print("Order was refunded")
if order.is_disputed:
print("Order is under dispute")
# Fulfillment state checkers
if order.needs_fulfillment:
print("Call orders.fulfill() to push content")
if order.is_terminal:
print("Order is in a final state (fulfilled, canceled, or failed)")
# Content type branch
if order.content_type == ContentType.GENERATED:
if order.is_paid and order.needs_fulfillment:
order = client.orders.fulfill(
order.id,
deliverables=[Deliverable.text("Your generated report...")]
)
Listing State Helpers
listing = client.listings.get("r7kq2xy9")
# Publication state
if listing.is_draft:
print("Listing is not yet publishable")
if listing.is_published:
print("Listing is live and purchasable")
# Stock state
if listing.is_in_stock:
print("Stock available for purchase")
# Content state
if listing.has_deliverables:
print(f"Listing has {len(listing.deliverables)} deliverables")
# Checkout link
print(f"Share: {listing.checkout_url}")
Readiness System Helpers
account = client.account.get()
# Quick readiness check
if account.is_ready:
print("Account is fully operational")
# Get the highest-priority action
if not account.is_ready:
action = account.next_action
print(f"Action needed: {action.code} -> {action.message}")
# Filter actions by kind
api_actions = account.actions_by_kind("api")
manual_actions = account.actions_by_kind("human")
for action in api_actions:
print(f"Can be fixed via API: {action.code}")
print(f" Endpoint: {action.resolve.endpoint}")
print(f" Method: {action.resolve.method}")
Similar helpers on ListingReadiness:
listing = client.listings.get("r7kq2xy9")
if not listing.readiness.is_ready:
next_action = listing.readiness.next_action
print(f"Next: {next_action.code}")
Price Formatting
from listbee import format_price, to_minor, from_minor
# Format cents as a decimal price
price_str = format_price(2900) # "$29.00"
# Convert decimal to cents
cents = to_minor(29.00) # 2900
# Convert cents to decimal
decimal = from_minor(2900) # 29.00
Webhook Parsing & Verification
Parse and verify webhook events in one step:
from listbee import parse_webhook_event, WebhookVerificationError
# In your webhook handler
payload = request.body # raw bytes
signature = request.headers["listbee-signature"]
secret = "whsec_..." # from webhook.secret
try:
event = parse_webhook_event(payload=payload, signature=signature, secret=secret)
print(f"Event: {event.type}")
print(f"Order ID: {event.data.id}")
except WebhookVerificationError:
# Signature invalid — reject the request
return Response(status_code=401)
parse_webhook_event automatically verifies the signature and parses the JSON payload. Raises WebhookVerificationError if verification fails.
Or verify and parse separately:
from listbee import verify_signature, WebhookVerificationError
import json
payload = request.body
signature = request.headers["listbee-signature"]
try:
verify_signature(payload=payload, signature=signature, secret=secret)
except WebhookVerificationError:
return Response(status_code=401)
event = json.loads(payload)
Client Configuration
Per-Call Options
Override defaults for a single request:
# Custom timeout for this call
listing = client.listings.create(
name="Heavy image processing",
price=2900,
cover_url="https://example.com/large.jpg",
timeout=180.0, # 3 minutes, overrides default 120s for create()
)
# Custom retries for this call
order = client.orders.get(
"ord_9xM4kP7nR2qT5wY1",
max_retries=5, # retry more aggressively on this request
)
Client-Level Options
from listbee import ListBee
client = ListBee(
api_key="lb_...",
timeout=60.0, # default request timeout
max_retries=3, # retries on 429/500/502/503/504
base_url="https://api.listbee.so", # default; override for testing
)
Custom HTTP Client
Use a custom httpx.Client or httpx.AsyncClient:
import httpx
from listbee import ListBee, DefaultHttpxClient
# Custom sync client with extra configuration
http_client = httpx.Client(
timeout=120.0,
limits=httpx.Limits(max_keepalive_connections=10),
headers={"User-Agent": "my-app/1.0"},
)
client = ListBee(
api_key="lb_...",
http_client=DefaultHttpxClient(client=http_client),
)
For async:
import httpx
from listbee import AsyncListBee, DefaultAsyncHttpxClient
http_client = httpx.AsyncClient(
timeout=120.0,
limits=httpx.Limits(max_keepalive_connections=10),
)
client = AsyncListBee(
api_key="lb_...",
http_client=DefaultAsyncHttpxClient(client=http_client),
)
Raw Response Access
Access HTTP response headers, status, and request metadata:
from listbee import ListBee
client = ListBee(api_key="lb_...")
# Get the raw response wrapper
response = client.with_raw_response().account.get()
# Access parsed model
print(response.parsed.email)
# Access raw HTTP response
print(response.response.status_code)
print(response.response.headers["x-request-id"])
print(response.response.headers["x-ratelimit-remaining"])
This works on any resource method:
response = client.with_raw_response().listings.get("r7kq2xy9")
print(f"Status: {response.response.status_code}")
print(f"Request ID: {response.response.headers.get('x-request-id')}")
print(f"Listing: {response.parsed.name}")
Action Resolution (Advanced)
Automatically resolve readiness actions via API:
from listbee import resolve_action
account = client.account.get()
if not account.is_ready:
action = account.next_action
# Resolve this action (if it's an API action)
if action.kind == "api":
result = resolve_action(client, action)
# Handles action code, calls appropriate endpoint
For async:
from listbee import resolve_action_async
account = await client.account.get()
result = await resolve_action_async(client, action)
Error Handling
ListBeeError
├── APIConnectionError # network error — request never reached the server
├── APITimeoutError # request timed out
└── APIStatusError # server returned 4xx/5xx
├── AuthenticationError # 401 — invalid or missing API key
├── NotFoundError # 404 — resource not found
├── ConflictError # 409 — resource conflict
├── ValidationError # 422 — request validation failed
├── RateLimitError # 429 — rate limit exceeded
└── InternalServerError # 500+ — server-side error
Catch specific errors:
from listbee import (
ListBee,
AuthenticationError,
NotFoundError,
RateLimitError,
ValidationError,
APIConnectionError,
APITimeoutError,
APIStatusError,
)
client = ListBee(api_key="lb_...")
try:
listing = client.listings.get("does-not-exist")
except NotFoundError as e:
print(e.status) # 404
print(e.code) # machine-readable code
print(e.detail) # human-readable explanation
print(e.title) # short stable label
print(e.type) # URI pointing to docs
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Resets at {e.reset}, {e.remaining}/{e.limit} remaining")
except ValidationError as e:
print(f"Bad request — field: {e.param}, detail: {e.detail}")
except APIConnectionError:
print("Network error — check your connection")
except APITimeoutError:
print("Request timed out")
except APIStatusError as e:
# Catch-all for unexpected status codes
print(f"API error {e.status}: {e.detail}")
Error responses follow RFC 9457 (Problem Details). All APIStatusError subclasses expose:
| Attribute | Type | Description |
|---|---|---|
status |
int |
HTTP status code |
code |
str |
Machine-readable error code |
detail |
str |
Specific explanation |
title |
str |
Short, stable error category label |
type |
str |
URI identifying the error type |
param |
str | None |
Request field that caused the error |
RateLimitError additionally exposes limit, remaining, and reset (parsed from response headers).
Async Usage
Use AsyncListBee for async frameworks (FastAPI, aiohttp, etc.):
import asyncio
from listbee import AsyncListBee, Deliverable
async def main():
client = AsyncListBee(api_key="lb_...")
# Create a listing, attach deliverable, publish
listing = await client.listings.create_complete(
name="SEO Playbook",
price=2900,
deliverables=[Deliverable.url("https://example.com/seo-playbook.pdf")],
)
listing = await client.listings.publish(listing.slug)
print(listing.url)
# Iterate all listings
async for listing in await client.listings.list():
print(listing.slug, listing.name)
# Filter paid orders
async for order in await client.orders.list(status="paid"):
print(order.id)
# Fulfill an order (async)
order = await client.orders.fulfill(
"ord_9xM4kP7nR2qT5wY1",
deliverables=[Deliverable.text("Generated content here")],
)
asyncio.run(main())
Use as an async context manager to ensure the connection is closed:
async def main():
async with AsyncListBee(api_key="lb_...") as client:
account = await client.account.get()
print(account.email)
The sync client also supports context manager usage:
with ListBee(api_key="lb_...") as client:
for listing in client.listings.list():
print(listing.name)
Configuration
from listbee import ListBee
client = ListBee(
api_key="lb_...",
timeout=60.0, # default: 30.0 seconds
max_retries=5, # default: 3; retries on 429/500/502/503/504
base_url="https://api.listbee.so", # default; override for testing
)
Note: listings.create() uses a separate default timeout of 120 seconds because cover image processing can take longer. Pass timeout= explicitly to override it:
listing = client.listings.create(
name="Quick listing",
price=999,
timeout=30.0, # override the 120s default for this call
)
Types and Enums
All types are importable directly from listbee:
from listbee import (
# Clients
ListBee,
AsyncListBee,
# Response models
ListingResponse,
OrderResponse,
WebhookResponse,
AccountResponse,
CustomerResponse,
FileResponse,
ListingReadiness,
AccountReadiness,
Action,
ActionResolve,
Review,
FaqItem,
CursorPage,
CheckoutFieldResponse,
# Builder classes
CheckoutField, # input class: .text() | .select() | .address() | .date()
Deliverable, # input class: .file() | .url() | .text() | .from_token()
# Enums
ContentType, # "static" | "generated" | "webhook"
DeliverableType, # "file" | "url" | "text"
PaymentStatus, # "unpaid" | "paid" | "refunded"
CheckoutFieldType, # "text" | "select" | "address" | "date"
BlurMode, # "auto" | "true" | "false"
ListingStatus, # "draft" | "published"
OrderStatus, # "pending" | "paid" | "processing" | "fulfilled" | "handed_off" | "canceled" | "failed"
WebhookEventType, # "order.paid" | "order.fulfilled" | "order.shipped" | ...
ActionCode, # "connect_stripe" | "configure_webhook" | ...
ActionKind, # "api" | "human"
# Exceptions
ListBeeError,
APIStatusError,
APIConnectionError,
APITimeoutError,
AuthenticationError,
NotFoundError,
ConflictError,
ValidationError,
RateLimitError,
InternalServerError,
PartialCreationError, # listing created but deliverable attachment failed
)
Use enums to avoid magic strings:
from listbee import ContentType, DeliverableType, PaymentStatus, ActionCode, ActionKind, WebhookEventType
# Check content type
if listing.content_type == ContentType.STATIC and listing.deliverables:
print(f"Delivers {listing.deliverables[0].type} file")
# Branch order fulfillment logic on content type
if order.content_type == ContentType.GENERATED:
print("Generate and push content via orders.fulfill()")
elif order.content_type == ContentType.WEBHOOK:
print("Handle delivery in your own system")
# Subscribe to specific events
webhook = client.webhooks.create(
name="Orders only",
url="https://example.com/hooks",
events=[
WebhookEventType.ORDER_PAID,
WebhookEventType.ORDER_FULFILLED,
WebhookEventType.ORDER_SHIPPED,
WebhookEventType.ORDER_REFUNDED,
WebhookEventType.LISTING_CREATED,
],
)
# Branch on action code
for action in listing.readiness.actions:
if action.code == ActionCode.CONFIGURE_WEBHOOK:
print(f"Create a webhook: {action.resolve.endpoint}")
elif action.code == ActionCode.CONNECT_STRIPE:
print(f"Connect Stripe: {action.resolve.url}")
Migration Guide
From v0.13.x to v0.14.0
Breaking Change: Fulfillment → Content Type
The fulfillment concept has been replaced with content types. Update your code:
# Old (v0.13.x)
listing = client.listings.create(
name="Report",
price=2900,
fulfillment="managed",
)
# New (v0.14.0)
from listbee import ContentType
listing = client.listings.create(
name="Report",
price=2900,
content_type=ContentType.STATIC, # or "static"
)
New: Order fields
Orders now include content-aware fields:
order = client.orders.get("ord_...")
# New fields in v0.14.0
print(order.content_type) # "static" | "generated" | "webhook"
print(order.payment_status) # "unpaid" | "paid" | "refunded"
print(order.listing_snapshot) # listing data at purchase time
print(order.seller_snapshot) # seller data at purchase time
print(order.handed_off_at) # when order was handed to seller (webhook only)
# Old field removed
# order.shipping_address # removed
New: Order status values
OrderStatus enum expanded with new states:
from listbee import OrderStatus
# New states in v0.14.0
OrderStatus.PROCESSING # order is generating content
OrderStatus.HANDED_OFF # order handed to seller (webhook orders)
From v0.12.x to v0.13.x
Breaking Change: Removed signup resource
Account creation is now handled via the ListBee Console. The client.signup resource has been removed.
# Old (v0.12.x)
response = client.signup.send_otp("seller@example.com")
token = client.signup.verify_otp("seller@example.com", "123456")
# New (v0.13.x)
# Use the Console at https://console.listbee.so to create accounts
# Then use API key for subsequent API calls
Requirements
- Python >= 3.10
License
Apache-2.0. See LICENSE.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file listbee-0.14.2.tar.gz.
File metadata
- Download URL: listbee-0.14.2.tar.gz
- Upload date:
- Size: 127.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d266e5991232efec863e32d687486b63e90a31030655bc3ea3dd2cde3547516
|
|
| MD5 |
fe5d72bbccfab731d462dae978a65d23
|
|
| BLAKE2b-256 |
3c6fc7601a3535fa479036165111eb3feaee2a2e85173d86a179d879ca39fd43
|
Provenance
The following attestation bundles were made for listbee-0.14.2.tar.gz:
Publisher:
publish.yml on listbee-dev/listbee-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
listbee-0.14.2.tar.gz -
Subject digest:
9d266e5991232efec863e32d687486b63e90a31030655bc3ea3dd2cde3547516 - Sigstore transparency entry: 1256404677
- Sigstore integration time:
-
Permalink:
listbee-dev/listbee-python@b0d51feeb9fc43845a027b6133a7366edeb7e38a -
Branch / Tag:
refs/tags/v0.14.2 - Owner: https://github.com/listbee-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b0d51feeb9fc43845a027b6133a7366edeb7e38a -
Trigger Event:
push
-
Statement type:
File details
Details for the file listbee-0.14.2-py3-none-any.whl.
File metadata
- Download URL: listbee-0.14.2-py3-none-any.whl
- Upload date:
- Size: 60.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54c948618497e320a59adeb08bf803c5945e2c0e4f2c0a9337ba4715fd919008
|
|
| MD5 |
f5ed6c169633c15987266edc9234fad0
|
|
| BLAKE2b-256 |
7e6bb3a8fdb986992498686359d839e8a7d307050664b90ed8234f413eb524c2
|
Provenance
The following attestation bundles were made for listbee-0.14.2-py3-none-any.whl:
Publisher:
publish.yml on listbee-dev/listbee-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
listbee-0.14.2-py3-none-any.whl -
Subject digest:
54c948618497e320a59adeb08bf803c5945e2c0e4f2c0a9337ba4715fd919008 - Sigstore transparency entry: 1256404865
- Sigstore integration time:
-
Permalink:
listbee-dev/listbee-python@b0d51feeb9fc43845a027b6133a7366edeb7e38a -
Branch / Tag:
refs/tags/v0.14.2 - Owner: https://github.com/listbee-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b0d51feeb9fc43845a027b6133a7366edeb7e38a -
Trigger Event:
push
-
Statement type: