Products, or inline ones
A catalog for what you sell again and again, each with a payment link. Or no catalog at all.
A checkout sells a catalog product or an inline one: a name, a price and a description written into the checkout itself. You don't need a catalog to take a payment.
| Catalog product | Inline product | |
|---|---|---|
| Created | once, here | with each checkout (next step) |
| Best for | a fixed item, a plan, a payment link | a cart, a price your server computes |
| Your own id | reference on the product | reference on the checkout (your order) |
| Payment link | yes, paymentLink | no |
Create a product
products-create.sh
# A catalog product with your own reference (unique per space).curl https://api.qbitflow.app/v2/products \ -H "X-API-Key: $QBITFLOW_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "name": "T-shirt", "description": "Blue, size M", "priceUsd": "4.99", "reference": "tshirt-blue-m" }'# 201: a Productconst product = await client.products.create({ name: 'T-shirt', description: 'Blue, size M', priceUsd: '4.99', // USD, a decimal string, never a float reference: 'tshirt-blue-m', // your own id: unique per space});console.log(`product ${product.uuid}, payment link ${product.paymentLink}`);product = client.products.create( name="T-shirt", description="Blue, size M", price_usd="4.99", # USD, a decimal string: never a float reference="tshirt-blue-m", # your own id: unique per space)print(product.uuid, product.payment_link)product, err := client.Products.Create(ctx, &qbitflow.CreateProductParams{ Name: "T-shirt", Description: "Blue, size M", PriceUSD: "4.99", // a decimal string, never a float Reference: "tshirt-blue-m", // your own id: unique per space})if err != nil { log.Fatal(err)}fmt.Println("created", product.UUID, "payment link:", product.PaymentLink)$product = $client->products->create(new \QBitFlow\Params\CreateProductParams( name: 'T-shirt', priceUsd: '4.99', // a decimal string, never a float description: 'Blue, size M', reference: 'tshirt-blue-m', // your own reference, unique per space));echo "Created {$product->uuid}, payment link {$product->paymentLink}\n";nameandpriceUsd: in USD, a decimal string above 0 (test mode: at most $5, else400 validation_failedonpriceUsd).descriptionis optional.reference: your id (letters, digits and. _ : @ -, never.or..alone, up to 100 characters), unique among your products (409 unique_violationotherwise). Left out, it's the product'suuid.- The SDK sends an
Idempotency-Key: a retried create never makes a second product.
Check it
The answer has the product's uuid, your reference (tshirt-blue-m) and its paymentLink,
which starts a checkout. It's in Dashboard/Products, in test mode.
List your products
products-list.sh
# The space's active products; ?includeHidden=true adds the hidden ones.curl https://api.qbitflow.app/v2/products \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Product ({ items, hasMore, nextCursor? })// iterate walks every page (list returns one); hidden products only with includeHidden.for await (const product of client.products.iterate()) { console. log( `${product. reference}: ${product.name}, ${product.priceUsd} USD`);}# iterate walks every page (list returns one); hidden products only with include_hidden.for product in client.products.iterate(): print(product.reference, product.name, product.price_usd, "USD")// Iterate walks every page (List returns one); hidden products only with IncludeHidden.for p, err := range client.Products.Iterate(ctx, nil) { if err != nil { log.Fatal(err) } fmt.Printf("%s %q: %s USD (%s)\n", p.UUID, p.Name, p.PriceUSD, p.Reference)}// iterate() walks every page (list() returns one); hidden products only with includeHidden.foreach ($client->products->iterate() as $product) { echo "{$product->reference} {$product->name}: {$product->priceUsd} USD\n";}Your active products, newest first, a page at a time (pagination). A hidden product (isActive: false) leaves the list but stays
readable by uuid or reference; includeHidden adds those.
A product changes in place: a new price applies to new checkouts only, while open checkouts and past payments keep theirs. A reference never changes.