Plans & Subscriptions
Audience: Sales / Finance / Management (engineers for the technical section) · Where in app: Sidebar → Billing (admin) → Plans / Change Plan · Plan availability: All plans (every tenant has a subscription row, including trials)
Knock Knock is sold as a monthly subscription. A tenant (company) picks a plan tier; the plan decides which features are switched on and what the monthly usage allowances are (AI credits, lead intelligence, live session views, team seats). Billing runs through Stripe. Annual billing has been retired — only monthly is sold to new tenants, though a handful of legacy "annual" customers may still exist in the data.
What it does
A plan (a PackageModel row) bundles three things for a tenant:
- Feature flags — which capabilities are unlocked (AI calling, lead intelligence, white-label, deeper CRM sync, Nox, etc.).
- Usage allowances — monthly AI credits, lead-intelligence (B2B enrichment) budget, live-session-view budget, and the number of users/agents allowed.
- A price — charged monthly via Stripe.
Each tenant has exactly one active subscription (a SubscriptionModel row) that points at the chosen package and tracks the remaining allowances for the current cycle.
How it works
- On signup a trial subscription is auto-assigned (see Free Tier & Trials).
- When the admin subscribes or changes plan in Billing, Stripe creates/updates the subscription and handles proration; the
SubscriptionModelrow is created or updated and feature gates flip live (checked at request time — no daemon restart). - Usage allowances live on the subscription row and are drawn down as the tenant uses AI, enrichment, and live views. AI usage draws down plan credits first, then falls back to the purchased balance (the wallet).
- Plan-gated feature checks happen on each API call, so a plan change takes effect on the next request.
Configuration & options
Subscription row (SubscriptionModel)
| Field | Meaning |
|---|---|
user_id, company_id, package_id | Owner, tenant, and the plan it points to |
payment_cycle | "normal" (monthly). Historically "annual" — now monthly only |
expiry_date | End of the current paid period |
subscription_status | active / cancelled / expired / past_due |
is_trial | Whether this is a trial subscription |
stripe_trial | Whether Stripe is tracking the trial |
remaining_ai_credits | Base-plan AI credits left this cycle (AI-only; reset on renewal) |
remaining_purchased_ai_credits | Purchased credits = the wallet: funds telephony, AI overflow; carries over cycles |
balance_auto_recharge | Wallet auto-recharge subdoc (enabled, threshold_credits, addon_id) |
remaining_lead_intelligence | B2B enrichment budget left |
remaining_live_session_views | Live-session-view budget left |
Plan tiers (PackageModel)
Plan names vary by sales generation — query the packages collection for the current SKUs. A typical layout:
| Tier | Audience |
|---|---|
| Free / Trial | New signups for evaluation |
| Starter | Small businesses, one user |
| Growth | Teams, basic CRM sync |
| Pro | Full feature access, advanced integrations |
| Enterprise | Custom SLA, white-label, agency capabilities |
Each package defines: a monthly price, a monthly AI credit allotment, a lead intelligence budget, a live session view budget, the number of users / agents, and a set of feature flags. (Exact field names and limits — verify against PackageModel and the live packages collection.)
Defaults when the package doesn't override (backend/app/helpers/SubscriptionHelper.js, package features.* wins): new companies get inbound and outbound calling enabled; caps of 2 outbound / 2 inbound / 2 WhatsApp agents (previously 1/1/0); lead-intelligence (Snitcher) default 20 lookups (previously 0) — features.lead_intelligence ?? 20.
Plan-gated features
Whether these are on depends on the plan:
- White-label widget footer
- Custom domain for the widget
- AI outbound calling
- Lead intelligence (B2B enrichment)
- HubSpot / GHL / Calendly integration depth
- Knowledge-base size cap
- Recording retention duration
- Concurrent agents
- Nox (admin AI assistant) — typically Pro+
Upgrading / downgrading
In Billing → Change Plan:
- Upgrade: new features become available immediately; the tenant is charged the prorated difference for the remainder of the current cycle (Stripe handles the proration math).
- Downgrade: the customer-facing flow applies the change at the end of the current billing cycle; the tenant keeps the current plan's features until then. A downgrade can reduce the team-seat limit or remove features — confirm current usage fits the lower plan first.
Add-ons
AddonModel defines optional one-time purchases on top of a plan, stored as remaining_purchased_* on the subscription and drawn down before base-plan credits:
- AI credits top-up (e.g. 10k / 50k packs)
- Extra lead-intelligence queries
- Extra live session views
- Additional team members (seats)
- Premium voices
Purchased AI credits land in remaining_purchased_ai_credits — the wallet — and carry over across billing cycles (renewal jobs reset plan credits only). They fund telephony and back-stop AI usage after plan credits run out. Add-ons cannot be purchased during a trial — the tenant must subscribe first. A purchase attempt with no card on file returns 402 (not a 500). (Specific pack sizes and prices — verify.)
Agency-managed companies
Companies owned by an agency do not manage their own plan. They use agency packages (AgencyPackageModel) and agency add-ons (AgencyAddonModel), and the company admin sees a "Contact agency" gate instead of the plan-change controls. The wallet is the exception: sub-accounts are now fully self-service for Wallet / Add-ons / Payment Methods (useBalanceAccess grants all) — see Wallet. See Agency Overview.
Behaviors & edge cases
- Cancellation:
subscription_status: "cancelled"— service continues throughexpiry_date, then degrades. The identity graph stops assembling context; the widget still loads but AI features fall back to defaults / queue-for-human. All historical data is retained per the data-retention policy. The tenant can resubscribe from Billing. - Past due / failed payment: Stripe dunning marks the subscription
past_dueand retries; if never paid it becomesuncollectible/expired. See Payments & Invoices. - Trial expiry:
subscription_status: "expired"; the identity-graph subscription gate trips so the AI sees only the current session. See Free Tier & Trials. - Legacy annual customers: the Pay Annually toggle is hidden in the UI, but rows with
payment_cycle: "annual"may still exist — preserve their state; do not "fix" them to monthly. - Plan change latency (QA): gates are evaluated per request, so a plan flip is visible on the next API call — no logout or restart needed.
Plan & limits
- Billing is monthly only for new tenants.
- Exact prices, AI-credit allotments, lead-intelligence budgets, live-session-view budgets, and seat counts per tier are not fixed here — they live in the
packagescollection and change by sales generation. Verify against the live data before quoting any number to a customer. - Add-on pack sizes/prices: verify against
AddonModel.
Technical implementation
- Models:
SubscriptionModel,PackageModel(thepackagescollection),AddonModel, plusAgencyPackageModel/AgencyAddonModelfor agency-managed tenants. - Backend: the Subscription controller / Stripe service handle subscribe, change-plan, cancel, proration, and webhook sync. Feature-gate checks run at request time in the backend.
- Stripe: payment methods, subscription lifecycle, and proration are Stripe-driven;
companies.stripe_customer_idlinks the tenant to its Stripe customer. See Payments & Invoices. - Identity-graph gate: subscription status drives whether the identity graph assembles cross-session context — see /subsystems/identity-graph.