#Subscriptions
#Plan vs subscription vs billing
| Term | Meaning | Lives in |
|---|---|---|
| Plan | What the customer can buy: tier, cycle, price, limits, features | Plan catalog Missing |
| Subscription | The account's/organization's active relationship with one plan: status, cycle, period, cancel flag | Subscription record |
| Billing | Money: wallet, payments, transactions, invoices, charges, tax | Billing tables + gateways |
#Who owns the subscription
V7 background: one subscription per user in new_subscription_plans (user_id + the organization_id of the user's main organization); servers each have a new_subscriptions row pointing at that plan; permission checks use the organization owner's plan. V7 only
#Subscription flow
Plan selectionSubscription requestCheckout (if amount0)Payment (wallet or gateway)Backend verificationSubscription activeUpdated plan limitsUpdated dashboard
- The user selects a plan and cycle.
- BE quotes the amount (credit already paid, tax, promo).
- If the amount is 0 (free/trial), it activates at once.
- Otherwise BE charges wallet credits. If credits are short, the user tops up through a gateway first (see Billing).
- BE confirms the payment (gateway verify / webhook), then activates or changes the subscription, writes a charge + audit entry, and updates the per-tier API rate limit (V7).
- FE reloads subscription, usage, permission map (features depend on the tier) and dashboard.
#States
V7 has no status column. State comes from expires_in_days, cycle and meta flags. V8 should expose an explicit status. Missing
| V8 state | Meaning | V7 equivalent | UI |
|---|---|---|---|
trial | Trial period, no payment yet | standard_trial_plan meta + trial days | "Trial, N days left" + "Choose a plan" |
active | Paid and within period | expires_in_days ≥ 0 | Green badge, renewal date |
pending | Payment started, not verified yet | Transaction status = 2 (pending) | "Payment pending", no limits changed |
cancelled | Will not renew. Works until the period ends | subscription_plan_cancel = 1 | "Ends on |
expired | Period over | expires_in_days < 0 (grace until −16) | Red banner: server actions blocked, Renew |
failed | Renewal or payment failed | Failed transaction / not enough credits | "Payment failed", Add credit / Retry |
renewal (event) | Period extended | renew-subscription | Toast + new date |
lifetime | Never expires, can't be cancelled | cycle = Lifetime | "Lifetime" badge |
#Expiry and renewal
- A daily job counts the remaining days down. Reminders go out from 7 days before the end. V7 only
- Expired: every server-level action except server delete is refused with "subscription has expired. Please renew it." V7 only
VerifyPermission - Renew within 15 days of expiry: the remaining (negative) days are kept. After that, a fresh period starts. V7 only
- Auto-renew: V7 renews by deducting wallet credits, with optional Stripe auto-recharge topping the wallet up. V7 only Is V8 renewal automatic? Open question D-4
#Subscription screen (/[locale]/subscription)
- Current subscription card: plan, cycle, state badge, period dates, price, payment source (wallet / card).
- Usage: servers, applications (with the cost caveat in Plans).
- Actions, each enabled only when the API allows it: Change plan, Change cycle, Cancel, Resume, Renew now.
- History: subscription events (from the audit log or charges).
#Required API (none exists)
| Capability | V7 reference | Status |
|---|---|---|
| Get current subscription + usage | GET /organizations/{org}/new-subscription-plan | Missing |
| Create (first plan) | POST /create-subscription | Missing |
| Change plan / cycle | PATCH /change-subscription | Missing |
| Quote / remaining credit | GET /remaining-credit | Missing |
| Renew | PATCH /renew-subscription | Missing |
| Cancel / resume | PATCH /cancel-subscription, /resume-subscription | Missing |
| Promo codes | GET /available-promo-codes, GET /discount-percentage | Missing |
| Lifetime | POST /create-lifetime-subscription, PATCH /convert-to-lifetime | Missing Open question |