Example: storefront script

This script reads a catalog from a JSON file, creates listings in bulk, and then polls for new orders. It is a complete runnable script with argument parsing and error handling.


Catalog file format

Create a catalog.json file with your listings:

1[
2 {
3 "name": "Python Async Patterns",
4 "price": 1900,
5 "deliverable": "https://my-bucket.s3.amazonaws.com/python-async.pdf"
6 },
7 {
8 "name": "FastAPI Production Guide",
9 "price": 2900,
10 "deliverable": "https://my-bucket.s3.amazonaws.com/fastapi-guide.pdf"
11 },
12 {
13 "name": "SQL for Data Scientists",
14 "price": 1500,
15 "deliverable": "https://my-bucket.s3.amazonaws.com/sql-datascience.pdf"
16 }
17]

Full script

1#!/usr/bin/env python3
2"""
3ListBee storefront script.
4
5Usage:
6 # Create listings from catalog file
7 python storefront.py create --catalog catalog.json
8
9 # Monitor orders (poll every 30 seconds)
10 python storefront.py orders --interval 30
11
12 # Both: create listings then watch for orders
13 python storefront.py create --catalog catalog.json --then-watch
14"""
15
16import argparse
17import json
18import os
19import sys
20import time
21import uuid
22from datetime import datetime, timezone
23
24import httpx
25
26BASE = "https://api.listbee.so"
27
28
29def get_client() -> tuple[httpx.Client, str]:
30 """Return (client, api_key). Reads LISTBEE_API_KEY from environment."""
31 api_key = os.environ.get("LISTBEE_API_KEY")
32 if not api_key:
33 print("Error: LISTBEE_API_KEY environment variable not set.", file=sys.stderr)
34 sys.exit(1)
35
36 client = httpx.Client(
37 base_url=BASE,
38 headers={"Authorization": f"Bearer {api_key}"},
39 timeout=30.0,
40 )
41 return client, api_key
42
43
44def create_listings(client: httpx.Client, catalog_path: str) -> list[dict]:
45 """Read catalog JSON and create all listings. Return created listing objects."""
46 with open(catalog_path) as f:
47 catalog = json.load(f)
48
49 print(f"Creating {len(catalog)} listings...")
50 created = []
51
52 for item in catalog:
53 idempotency_key = str(uuid.uuid4())
54
55 try:
56 resp = client.post(
57 "/v1/listings",
58 json=item,
59 headers={"Idempotency-Key": idempotency_key},
60 )
61 resp.raise_for_status()
62 listing = resp.json()
63 created.append(listing)
64 print(
65 f" ✓ {listing['name']:<40} {listing['url']}"
66 f" sellable={listing['readiness']['sellable']}"
67 )
68 except httpx.HTTPStatusError as exc:
69 error = exc.response.json()
70 print(
71 f" ✗ {item.get('name', '?'):<40} "
72 f"error={error.get('code')} {error.get('detail')}",
73 file=sys.stderr,
74 )
75
76 print(f"\nCreated {len(created)} of {len(catalog)} listings.")
77 return created
78
79
80def poll_orders(client: httpx.Client, interval: int = 30) -> None:
81 """Poll GET /v1/orders and print new orders as they arrive."""
82 print(f"Watching for orders (polling every {interval}s)... Ctrl+C to stop.\n")
83
84 seen_ids: set[str] = set()
85 cursor: str | None = None
86
87 while True:
88 try:
89 params: dict = {"limit": 50}
90 if cursor:
91 params["cursor"] = cursor
92
93 resp = client.get("/v1/orders", params=params)
94 resp.raise_for_status()
95 result = resp.json()
96
97 for order in result["data"]:
98 if order["id"] not in seen_ids:
99 seen_ids.add(order["id"])
100 ts = datetime.fromisoformat(order["created_at"].replace("Z", "+00:00"))
101 local_ts = ts.astimezone().strftime("%Y-%m-%d %H:%M:%S")
102 amount = order["amount"] / 100
103 print(
104 f"[{local_ts}] New order {order['id']}"
105 f" buyer={order['buyer_email']}"
106 f" amount=${amount:.2f} {order['currency'].upper()}"
107 f" listing={order['listing_id']}"
108 )
109
110 # Update cursor for next page (if paginating)
111 if result.get("cursor"):
112 cursor = result["cursor"]
113
114 except httpx.HTTPStatusError as exc:
115 print(f"Error polling orders: {exc}", file=sys.stderr)
116 except KeyboardInterrupt:
117 print("\nStopped.")
118 break
119
120 time.sleep(interval)
121
122
123def cmd_create(args: argparse.Namespace) -> None:
124 client, _ = get_client()
125 listings = create_listings(client, args.catalog)
126
127 not_sellable = [l for l in listings if not l["readiness"]["sellable"]]
128 if not_sellable:
129 print(f"\n{len(not_sellable)} listing(s) not yet sellable:")
130 for l in not_sellable:
131 next_code = l["readiness"]["next"]
132 print(f" {l['name']}: next action = {next_code}")
133
134 if args.then_watch:
135 print()
136 poll_orders(client, interval=30)
137
138
139def cmd_orders(args: argparse.Namespace) -> None:
140 client, _ = get_client()
141 poll_orders(client, interval=args.interval)
142
143
144def main() -> None:
145 parser = argparse.ArgumentParser(description="ListBee storefront script")
146 subparsers = parser.add_subparsers(dest="command", required=True)
147
148 create_parser = subparsers.add_parser("create", help="Create listings from catalog JSON")
149 create_parser.add_argument("--catalog", required=True, help="Path to catalog.json")
150 create_parser.add_argument(
151 "--then-watch", action="store_true", help="Watch for orders after creating"
152 )
153 create_parser.set_defaults(func=cmd_create)
154
155 orders_parser = subparsers.add_parser("orders", help="Poll for new orders")
156 orders_parser.add_argument(
157 "--interval", type=int, default=30, help="Poll interval in seconds (default: 30)"
158 )
159 orders_parser.set_defaults(func=cmd_orders)
160
161 args = parser.parse_args()
162 args.func(args)
163
164
165if __name__ == "__main__":
166 main()

Running the script

$# Install dependencies
$pip install httpx
$
$# Set your API key
$export LISTBEE_API_KEY=lb_...
$
$# Create listings
$python storefront.py create --catalog catalog.json
$
$# Watch for orders
$python storefront.py orders --interval 30
$
$# Create and then watch
$python storefront.py create --catalog catalog.json --then-watch

Sample output

Creating 3 listings...
✓ Python Async Patterns https://buy.listbee.so/r7kq2xy9 sellable=True
✓ FastAPI Production Guide https://buy.listbee.so/m3pr5tw1 sellable=True
✓ SQL for Data Scientists https://buy.listbee.so/vb8azn4j sellable=True
Created 3 of 3 listings.
Watching for orders (polling every 30s)... Ctrl+C to stop.
[2026-03-29 10:15:03] New order ord_abc123 buyer=customer@example.com amount=$19.00 USD listing=lst_xyz789
[2026-03-29 10:47:22] New order ord_def456 buyer=another@example.com amount=$29.00 USD listing=lst_uvw012

Next steps

  • API reference — explore every endpoint in detail.
  • Webhooks — get notified on orders instead of polling.

Copy for AI assistants

Cursor / Claude Code
1# ListBee — bulk listing creation + order polling
2#
3# Create listings from JSON array:
4# POST /v1/listings { name, price (cents), deliverable }
5# Use Idempotency-Key header per request (uuid4)
6# Response: { id, slug, url, readiness: { sellable, actions, next } }
7#
8# Poll for orders:
9# GET /v1/orders?limit=50&cursor=...
10# Response: { object: "list", data: [...], has_more: bool, cursor: str | null }
11# Order fields: id (ord_...), listing_id (lst_...), buyer_email,
12# amount (cents), currency, created_at
13#
14# Pagination: pass cursor from response as cursor param on next request
15# Auth: Authorization: Bearer lb_...
16# Docs: https://docs.listbee.so