Skip to main content
Stripe subscription Checkout produces several related events. Biqli separates attribution, trial leads, and paid invoices so a zero-value trial is not mistaken for revenue and each renewal remains independently idempotent. Create Checkout with mode: 'subscription', register the exact Checkout Session, and let Stripe deliver both Checkout and invoice events.
checkout.session.completed establishes the customer, subscription, invoice, and payment hierarchy. Biqli does not create the subscription sale from that event. The canonical sale comes from invoice.paid. This prevents the first subscription charge from being counted once as Checkout and again as an invoice.

Subscription with a trial

Add trial settings through Stripe’s supported Checkout parameters:
After exact Checkout registration:
  1. a trialing subscription creates one Stripe Free Trial lead;
  2. its zero-value invoice creates no sale;
  3. the first non-zero invoice.paid creates a subscription sale;
  4. later cycle invoices create independent renewal sales.
If your application also records Signed up, one customer can correctly have two leads: application signup and Stripe trial. The trial’s stable identity combines the Stripe environment, account, subscription, and trial start time. Repeated created or updated events for the same trial do not increase the lead count.

Out-of-order events

Stripe may deliver customer.subscription.created before checkout.session.completed. The early event cannot yet prove which Biqli click owns the subscription. Biqli temporarily fails the event when an eligible Checkout mapping is still pending. The webhook ledger adds a short exponential backoff. After Checkout establishes the object hierarchy, a Stripe retry processes the trial once. This temporary 500 processing_failed is expected for that ordering. It needs investigation only when retries continue after Checkout has been processed. Invoices can also arrive before Checkout. When the invoice includes a uniquely eligible email mapping, Biqli can resolve it safely. Otherwise it waits for or ignores the missing attribution rather than guessing.

Initial payment versus renewal

Every non-zero paid Stripe invoice is a separate sale with the Stripe invoice ID as its financial identity. The visible event time uses Stripe’s paid timestamp when available. A test clock can therefore produce a renewal dated in the future relative to the wall-clock time when you are viewing the report.

Upgrades, downgrades, and prorations

Biqli records a sale when Stripe sends a non-zero invoice.paid that remains connected to the attributed subscription. It uses Stripe’s paid amount rather than reconstructing plan mathematics in Biqli. An immediate plan change can therefore produce a paid invoice with billing reason subscription_update. It is a new sale if the amount is greater than zero. A zero-value change creates no sale.

Cancellation

customer.subscription.updated keeps trial handling idempotent but does not create a cancellation conversion. Canceling immediately or at period end does not alter already paid revenue. Expected behavior:
  • cancel at period end: the subscription may remain active until the current period ends;
  • immediate cancellation: no additional sale is created;
  • a final paid invoice: recorded only if Stripe actually sends a non-zero invoice.paid;
  • no later invoice: no renewal appears.
If your product needs cancellation analytics, record a separate application event in your own product analytics. Do not represent cancellation as negative Stripe revenue.

Partial refund

A successful refund smaller than the original sale reduces its net attributed revenue and appears as Partial refund. For a $25.99 sale and $5.00 refund:
  • sales remain 1;
  • gross sale history remains $25.99;
  • the refund activity is -$5.00;
  • net attributed revenue becomes $20.99.

Full refund and multiple refunds

Biqli sums successful refunds linked to the sale and caps the net adjustment at the original sale value. A second refund that returns the remaining amount produces Refund completed and net revenue $0.00. Each refund is identified by its Stripe re_... ID. Repeated refund.created and refund.updated deliveries update that refund rather than subtracting it twice.

Failed and pending refunds

Pending and requires_action refunds are retained as lifecycle state but do not reduce report revenue until they succeed. Failed and canceled refunds do not reduce revenue. A successful refund delivered before the original sale is available temporarily fails so Stripe can retry it after sale attribution exists. For some charge-only refund payloads, Biqli may read the charge from Stripe to obtain its PaymentIntent and link it back to the sale.

Product labels

Biqli uses the first embedded invoice line description and product reference when Stripe includes them in the permitted invoice payload. Activity can appear as:
  • Purchased 1 × Acme Pro (at $12.00 / month);
  • Renewed 1 × Acme Pro (at $12.00 / month);
  • a generic Purchase or Subscription renewed when no safe product label is present.
The label does not affect amount, attribution, or idempotency. Continue with Testing and operations.