Skip to content

Stripe billing

Twinlix uses Stripe for subscription billing. Each tenant gets a stripe_customer_id on first checkout; ongoing webhook events keep our internal Subscription row in sync with the Stripe-side state.

Live keys

As of 2026-05-22 (TWIN-135) the platform runs against the live Stripe account acct_1TKhZKI7Gof92OLY (Twinlix.com, Poland).

  • Webhook endpointPOST https://api.twinlix.com/v1/webhooks/stripe, signing secret stored in backend .env as STRIPE_WEBHOOK_SECRET.
  • Products + prices — three tiers (Small / Middle / Large), monthly + annual price per tier, EUR. Stored on pricing_tiers table with stripe_price_id column.

Test cards

For sanity checks before going live, switch the keys back to sk_test_… and use:

  • 4242 4242 4242 4242 — succeeds.
  • 4000 0000 0000 9995 — declined (insufficient funds).

Subscription lifecycle

   signup (Free tier, no Stripe interaction)

            v
   user clicks "Upgrade" on the change-plan page

            v
   POST /v1/crm/stripe/checkout → Stripe Checkout Session URL

            v
   user pays in Stripe-hosted form

            v
   checkout.session.completed webhook

            v
   backend writes Subscription { tier='small', stripe_subscription_id }

Cancellation flow lands customer.subscription.deleted on the webhook; backend keeps the row for audit but flips status='cancelled'.

Retention discount (planned)

RETENTION_50_OFF_1MONTH coupon (50% off next month) is on the roadmap for the cancel flow but not yet wired (see TWIN-45).

Twinlix platform documentation.