Subscribe a customer

A checkout your customer signs once. Its sub@ id is the subscription's, for life.

Your server creates a checkout; your customer picks a token, chooses how many periods to authorize and signs once from their wallet.

From the catalog · sample terms

Todayfree: a signed message
7-day trialthey sign the cap
First bill · $4.99as they confirm
Every monthon each due date

Create a subscription checkout

Create a subscription checkout with a trial

checkout-create-subscription.sh

# A monthly subscription with a 7-day trial. The subscription exists, with the session's id, once# the customer signed (here: started the trial): act on the subscription.created webhook.curl https://api.qbitflow.app/v2/checkout-sessions/subscription \  -H "X-API-Key: $QBITFLOW_API_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: $(uuidgen)" \  -d '{    "productName": "T-shirt",    "description": "Blue, size M",    "priceUsd": "4.99",    "frequency": { "value": 1, "unit": "months" },    "trialPeriod": { "value": 7, "unit": "days" },    "reference": "order-1043",    "successUrl": "https://shop.example.com/orders/success?uuid={{UUID}}",    "cancelUrl": "https://shop.example.com/orders/cancel"  }'# 201: a CreatedCheckoutSession ({ "link": "https://…/checkout?uuid=sub@…", "uuid": "sub@…", "expiresAt": "…" })
// The subscription exists, with the session's id, once the customer signed (here: started the// trial). Act on the subscription.created webhook.const session = await client.checkoutSessions.createSubscription({	productName: 'T-shirt',	description: 'Blue, size M',	priceUsd: '4.99', // USD per period, a decimal string	frequency: { value: 1, unit: DurationUnit.Months },	trialPeriod: { value: 7, unit: DurationUnit.Days },	reference: 'order-1043',	successUrl: `https://shop.example.com/orders/success?uuid=${Placeholders.UUID}`,	cancelUrl: 'https://shop.example.com/orders/cancel',});console.log(`Redirect the customer to ${session.link}`);
session = client.checkout_sessions.create_subscription(    product_name="T-shirt",    description="Blue, size M",    price_usd="4.99",  # USD per period, a decimal string    frequency=qbitflow.Duration(value=1, unit=qbitflow.DurationUnit.MONTHS),    trial_period=qbitflow.Duration(value=7, unit=qbitflow.DurationUnit.DAYS),    reference="order-1043",    success_url=f"https://shop.example.com/orders/success?uuid={qbitflow.PLACEHOLDER_UUID}",    cancel_url="https://shop.example.com/orders/cancel",)print("Send the customer to", session.link)  # sub@…: the subscription's id once signed
// The Subscription exists, with the session's id (sub@…), once the customer signed: act on// the subscription.created webhook.session, err := client.CheckoutSessions.CreateSubscription(ctx, &qbitflow.CreateSubscriptionSessionParams{	ProductName: "T-shirt",	Description: "Blue, size M",	PriceUSD:    "4.99", // USD per period, a decimal string	Frequency:   &qbitflow.Duration{Value: 1, Unit: qbitflow.DurationUnitMonths},	TrialPeriod: &qbitflow.Duration{Value: 7, Unit: qbitflow.DurationUnitDays},	Reference:   "order-1043",	SuccessURL:  "https://shop.example.com/orders/success?uuid=" + qbitflow.PlaceholderUUID,	CancelURL:   "https://shop.example.com/orders/cancel",})if err != nil {	log.Fatal(err)}fmt.Println("Redirect the customer to", session.Link)
$session = $client->checkoutSessions->createSubscription(new \QBitFlow\Params\CreateSubscriptionSessionParams(	productName: 'T-shirt',	description: 'Blue, size M',	priceUsd: '4.99', // USD per period, a decimal string	reference: 'order-1043',	frequency: \QBitFlow\Models\Duration::months(1),	trialPeriod: \QBitFlow\Models\Duration::days(7), // the first bill comes after the trial	successUrl: 'https://shop.example.com/orders/success?uuid=' . \QBitFlow\Placeholders::UUID,	cancelUrl: 'https://shop.example.com/orders/cancel',));echo "Subscribe at {$session->link}\n";

This one writes its plan inline: a price per period, a frequency and a 7-day trialPeriod. To sell a catalog plan, send its productUuid (or productReference): its terms are the defaults, and each term you send overrides that one.

It answers 201 with a link and a uuid. That uuid (sub@…) is the subscription's id, for life: every read and webhook names it. Store it with your customer.

Add taxes or the processing fee

A subscription checkout takes the same fees as a payment's (checkout fees): your lines and processingFee. They're locked with the price: every bill charges the price plus every line, the session's amountUsd, and the allowance your customer signs is sized on it. In test mode, a bill is at most $5, lines included.

What your customer signs

  • No trial: the subscription itself, an allowance of a number of periods (at least the checkout's minPeriods), each at most a maximum amount of the token. The first period is charged at once, the next ones on their due dates.
  • A trial: a message that moves no funds and authorizes nothing. The subscription starts in trial; they confirm it (sign the subscription) before the trial ends to be billed. A wallet gets one trial per plan: a wallet that already started one meets 409 trial_already_used, and subscribes without the trial instead (skipTrial: true on its intent).

It doesn't exist until it's signed

Before the customer pays the first period or starts the trial, there is no subscription: reading sub@… answers 404, and no list has it. Only the checkout exists, with its status.

Grant access on subscription.created (the next step), sent once it's confirmed on-chain (a trial: once its message is signed). Never on the redirect: anyone can open your success page, and its {{UUID}} only says which sub@… to look up.

Check it

The answer's uuid starts with sub@. Pay its link with QBFT faucet tokens: the same sub@… shows in Dashboard/Subscriptions, trial here, active for a plan without one.