Plans, with an optional free trial
A product with billing terms. Create it once; its terms become every checkout's defaults.
A plan is a product with subscription terms: a price per period, how often it bills, an optional free trial. No catalog? Write the plan inline in each checkout (next step): QBitFlow keeps a hidden product for it.
Create a plan
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";Add a subscription object to the same request and it's a plan:
| Field | What it is | Rules |
|---|---|---|
subscription.frequency | How often it bills: { "value", "unit" } | Required. seconds, minutes, hours, days, weeks, months (30 days) or years (365 days). At least 1 hour live, 5 minutes in test; at most 1 year |
subscription.trialPeriod | A free trial before the first bill | Optional; { "value": 0 } means none |
subscription.minPeriods | The fewest periods a customer may sign for | Optional, 0 to 1,000 |
priceUsd is each period's price, in USD. The contract's own example, a monthly team plan with a
14-day trial and at least 3 periods (the SDKs take the same fields):
JSON
{ "name": "Team plan", "priceUsd": "49", "subscription": { "frequency": { "value": 1, "unit": "months" }, "trialPeriod": { "value": 14, "unit": "days" }, "minPeriods": 3 }}The answer writes each duration in its largest exact unit: the 14-day trial comes back as 2 weeks.
A plan for test mode
That price is above test mode's cap of $5 (live plans: above $0.25), and a month is a long wait. Bill every 5 minutes, the shortest test mode allows, and run the bills back to back (step 7):
Shell
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": "Pro plan (test)", "priceUsd": "4.99", "reference": "pro-test", "subscription": { "frequency": { "value": 5, "unit": "minutes" } } }'Check it
The answer has your subscription terms, and the plan is in Dashboard/Products
(test mode). GET /products with subscription=true lists plans only.
Prices are locked at signup
A subscriber pays the price they signed for, for life, with the lines their checkout added (a tax, the processing fee): a new price applies to new subscribers only. To move someone to a new price, cancel theirs at the end of its paid period (step 6) and send them a new checkout.