Skip to content

n1.care Subscription Model — Product Spec Sheet

n1.care Subscription Model — Product Spec Sheet

Section titled “n1.care Subscription Model — Product Spec Sheet”

n1.care is moving from a prepaid-balance / pay-as-you-go model (bill per LLM call, wallet top-ups via Stripe one-off checkout) to a subscription model with metered page and report budgets. The intent is predictable monthly revenue, simpler customer mental model (“you get X pages and Y reports per month”), and a cleaner pricing story on the website.

This document is a product spec — it defines the commercial rules, not the implementation. A separate engineering plan will follow once the spec is approved. The spec also includes a phased modular rollout so we can ship incrementally rather than one big switchover.


Free Trial Starter Professional Practice Enterprise
Monthly price $0 $149 $349 $799 Custom
Credit card required No Yes Yes Yes Contract
Time limit None (lifetime cap)
Record parsing 100 pages (lifetime) 500 pages/mo 2,000 pages/mo 8,000 pages/mo Unlimited
Parsing overage Not available $0.20/page $0.15/page $0.10/page
Reports included 1 (lifetime) 5/mo 20/mo 60/mo Custom
Report overage Not available $29 each $22 each $18 each Custom
Patient management Unlimited Unlimited Unlimited Unlimited Unlimited
All plans are billed monthly. No annual commitment at launch — we want room to evolve pricing as the model matures.

  • The doctor holds the subscription. One subscription per doctor account.
  • Quota is shared across all the doctor’s patients. A 500-page/mo plan means 500 pages total across every patient the doctor manages.
  • Patient count is unlimited on every tier.
  • Billing resolution stays aligned with the existing get_billing_user_id_sync pattern in api-backend.

  • A “page” is one page of the uploaded file, counted uniformly across formats:
    • PDF: native page count.
    • DOCX / ODT / RTF and other reflowable formats: convert to PDF first (existing upload flow already does this), count the resulting PDF pages.
    • Single image (JPG, PNG, HEIC, etc.): 1 page.
    • Image-merge record (2–50 images via /records/add/images): N images = N pages.
  • Password-protected / unreadable file: rejected on upload before reaching the review step, so never charged (see §5).
  • One report generation (any CHR workflow) = 1 report against the monthly quota, charged at the moment the doctor clicks Generate (see §5).
  • Failed generations are recovered via free reprocessing (see §5) — the charge is tied to the click, not the outcome.

  • Monthly, anniversary-based. A doctor who subscribes on the 15th has their quota reset on the 15th of each month.
  • No rollover. Unused pages and reports are forfeited at period end — “use it or lose it.”

  • When a doctor exhausts their page or report quota, behaviour depends on an “Allow extra usage beyond my plan” toggle in billing settings.
  • Default: OFF. New subscribers start with a hard cap until they explicitly opt in. No surprise invoices.
  • When OFF and quota exhausted: extract/report-generate is blocked with a “Quota exceeded — upgrade plan or enable extra usage” modal.
  • When ON and quota exhausted: work continues, overage is metered at the per-tier rate (see pricing table), charged on the next invoice.
  • Toggle effect is forward-only. Flipping the toggle takes effect immediately for subsequent extracts. Disabling mid-period stops further overage from accruing, but does not reverse or refund overage already accrued earlier in the same billing period — those charges stand and bill at period end. The T&C names this explicitly.
  • Free Trial has no overage option regardless of toggle — a hard cap at 100 pages / 1 report, lifetime.
  • Upload lands a file in a “ready to extract” state — no pages are charged yet. The doctor sees each file’s page count on a review screen before committing.
  • Quota is charged at the instant the doctor clicks Extract. The charge is immutable: one append-only event row per extract click, covering the pages they authorized.
  • Report generation follows the same two-step pattern — a review + explicit generate click charges 1 report.
  • An unreadable or password-protected file is rejected at upload time (before the review screen) and is therefore never charged.

Parse failures are recovered via free reprocessing, not refunds

Section titled “Parse failures are recovered via free reprocessing, not refunds”
  • If parse fails after the charge (LLM timeout, parser crash, transient error), the doctor hits Reprocess on the failed record. Reprocess replays the original charge idempotency key — no second charge, no quota refunded or released. The parse runs again against the same record, at no additional cost.
  • There is no limit on reprocess attempts per record. A record that keeps failing is a system bug, handled by support — not a commercial refund negotiation.
  • Same applies to report generation: Reprocess on a failed report is free and does not re-bill.
  • This applies equally to in-plan usage and overage. An overage extract that fails still records the overage charge (matching what the doctor authorized); reprocess is free.

  • Upgrade: immediate. New quota available instantly. Stripe issues a prorated charge on the next invoice for the remainder of the current period.
  • Downgrade: at period end. Doctor keeps their current plan and quota until the renewal date, then switches.
  • Upgrades handled via Stripe Customer Portal (no custom UI required) or an in-app “Upgrade” button.
  • Overage toggle carries across plan changes.
  • New prices apply from the next billing cycle for existing subscribers — no mid-cycle price increases, ever. Applies equally to base plan pricing and overage rates.
  • Existing subscribers receive at least 30 days’ advance notice by email before the new price applies to their renewal. The T&C names this notice window explicitly (§7 of the T&C-rewrite bundle in phase-6).
  • Doctors who cancel before their next renewal avoid the new price entirely — the paid period continues at the old price.
  • Mechanism: Stripe Price versioning. A new Price object is created for the new amount; existing subscribers migrate at their next renewal with proration_behavior="none" and the billing-cycle anchor preserved. Old Price objects are retained until no subscribers reference them — never deleted while live.
  • No code change required in this rollout — the subscription row already references a Stripe price id, which is what changes. The commitment is operational (procedure + notice) and contractual (T&C clause), not code.

  • On a declined payment, the account becomes read-only immediately. No grace period.
  • Read-only = can view existing data, cannot upload records or generate reports.
  • Stripe Customer Portal handles payment method updates; account unlocks as soon as payment succeeds.
  • Doctor keeps full access through the end of the paid period.
  • After period end: account is read-only indefinitely — all data retained, no auto-archive, no deletion.
  • Returning doctors reactivate by picking a plan again.
  • No prorated refunds on cancellation.
  • Data export remains available on any read-only account (cancelled, payment-failed, or Free Trial exhausted). Doctors always retain the ability to pull their own data out. No time limit on this access.

  • No credit card required.
  • Lifetime cap: 100 pages (record parsing) and 1 report.
  • No time limit — account stays on Free Trial until caps are hit.
  • Once either cap is hit: account becomes read-only, must upgrade to continue.
  • No overage option, no reset. Parse failures are recovered via free reprocessing per §5 (no page/report refund; reprocess replays the same charge).
  • Free Trial does not count as an Enterprise or paid tier for any entitlement purposes.

9. Existing User Migration (Prepaid → Subscription)

Section titled “9. Existing User Migration (Prepaid → Subscription)”
  • All current users are trial-level — none are paying customers with meaningful prepaid balance. No balance-credit logic required.
  • Hard migrate every existing user to the Starter plan at cutover with a charge_exempt flag flipped on. They live in the system as full Starter subscribers with all normal user functionality — real subscription row, real quota enforcement, full app access, standard billing UI. Migrated users happen to have no Stripe customer/subscription yet because they haven’t gone through Checkout (no payment method at cutover); that absence is orthogonal to charge_exempt.
  • charge_exempt is a narrow flag on the overage billing path only. When true, billing-service suppresses the Stripe metered-usage post for overage charges. It does not disable base-plan invoicing, quota enforcement, or any user-facing functionality — a charge_exempt=true user with a live Stripe subscription continues to be invoiced for the base plan as normal; only overages are waived.
  • charge_exempt is an admin-controlled flag (not time-bounded, no auto-expiry). Ops flips it off in the admin dashboard when they want a specific user to start being billed for overage usage. For migrated users (no Stripe subscription yet) flipping it off also sets status = incomplete, the ReadOnlyBanner surfaces with a “Finish setting up your subscription” CTA, and the normal pick-a-plan → Stripe Checkout flow kicks in — without Checkout there’s no Stripe subscription item to post overages against, so enforcement wouldn’t be meaningful yet. No automated cohort-wide trigger; individual, admin-driven transitions only.
  • Any residual prepaid-wallet balance is zeroed out at cutover. (If this changes later — e.g. if we acquire paying customers before cutover — we’ll revisit credit mechanics.)
  • Legacy pay-as-you-go is retired at cutover (no parallel systems).
  • charge_exempt is also the mechanism for ongoing overage-waived accounts (internal team, partners, demo accounts) — keep it as a permanent feature, not a migration-only hack. Note: it waives overage only, not the base plan. A fully-comped account (no base charge) requires a separate mechanism (Stripe coupon, custom plan) and is out of scope for this rollout.

  • Enterprise is “Contact sales” only at launch — no published quota, overage, or price.
  • Each Enterprise deal is negotiated individually (quota, overage treatment, contract terms, invoicing cadence).
  • A published Enterprise spec will only be defined after the first 2–3 real Enterprise deals, once patterns emerge.

  • Persistent in-app indicators visible wherever upload/generate actions live:
    • “X pages left this month”
    • “Y reports left this month”
  • Counters update in real time as uploads complete.
  • Quota exceeded, overage OFF: “You’ve hit your page/report limit. Upgrade your plan or enable extra usage to continue.”
  • Quota exceeded, overage ON: One-time confirmation “You’ve hit your limit. Additional usage is billed at $X/page and $Y/report. Continue?” — then continues silently.
  • Read-only (payment failed or cancelled): Banner across the app with update-payment CTA.
  • Payment failed.
  • Quota reset (receipt for the new period).
  • Upgrade / downgrade confirmation.
  • Invoice with overage charges (itemised).

12. Rollout — Dependency Stages, Single Cutover

Section titled “12. Rollout — Dependency Stages, Single Cutover”

The rollout is decomposed into five phases as a dependency structure, not a release schedule. All five ship together in one deploy — phases describe what builds on what, so the work has a clean order within the delivery.

Detailed engineering specs: subscription-rollout-master.md and phase-1.mdphase-5.md.

Phase 1 — Usage counters + upload review

Section titled “Phase 1 — Usage counters + upload review”

Page count on every upload, stored on record_requests.page_count. Parse decoupled from upload — the doctor sees a review screen with per-file page counts and explicitly clicks Extract to commit. Foundation for every downstream phase.

Phase 2 — Plan & Subscription model + usage ledger + quota display

Section titled “Phase 2 — Plan & Subscription model + usage ledger + quota display”

plans + subscriptions + quota_events tables. Every extract click calls /quota/charge, which writes one immutable quota_events row. Billing-service owns usage totals via SUM(quota_events) — no cross-service aggregation call. All existing users are hard-migrated to Starter with charge_exempt = true at cutover — full subscription row, quota enforced normally; the flag suppresses overage Stripe posts only. Admin endpoint lets ops flip charge_exempt off per-user in the admin dashboard. Frontend renders “X of Y” from a unified Contract B.

Phase 3 — Paid plan enforcement + Stripe + overage

Section titled “Phase 3 — Paid plan enforcement + Stripe + overage”

Paid-plan branches added to /quota/charge (quota check under SELECT FOR UPDATE, 429 on exhaustion, overage when toggled on). New signups land on a pick-a-plan screen → Stripe Checkout. Stripe webhooks keep the subscription row in sync with state changes + period rolls. Overage posted to Stripe metered billing at period end. Parse failures recovered via free reprocessing (idempotency-key replay). Existing migrated users continue to hit the Starter quota branch — the charge_exempt flag narrowly suppresses the overage Stripe post; in-quota enforcement and every other path run identically.

Phase 4 — Portal + emails + read-only banner

Section titled “Phase 4 — Portal + emails + read-only banner”

Stripe Customer Portal for self-serve plan changes. Four transactional email templates (receipt, payment-failed, plan-changed, subscription-canceled) wired into the Stripe webhook handlers. ReadOnlyBanner explains non-active subscription states with a one-click Portal CTA.

Public landing “Start Free Trial” (no card) → 100 pages + 1 report lifetime. Lifetime-cap branch added to /quota/charge. Trial banner + upgrade-on-cap modal drop users into the Phase 3 Checkout flow on cap-hit, preserving their data. Abuse guards: email verification, per-IP signup rate limit, 1 concurrent parse per trial user, daily LLM-spend alert.


For reference only — detailed engineering plan comes later.

  • billing-service — new Plan/Subscription models, append-only quota_events table, Stripe subscription mode, overage metering, single /quota/charge API, payment-failure webhook handling.
  • authentication-service — registration webhook provisions a default subscription (Starter, charge_exempt = false for new signups); no JWT claim changes.
  • admin-dashboard — checkbox on the subscription detail view for flipping charge_exempt per user (Phase 2 work).
  • api-backend — page counting on /records/add and /records/add/images (Phase 1), decouple parse-queue from upload endpoint, new /records/batch-extract that calls /quota/charge then queues parse, /records/{id}/reprocess that replays the same charge idempotency key. Same pattern on /reports/generate.
  • parser-router — no changes required; optional future enhancement to return MinerU-measured page count for reconciliation.
  • react-frontend — new Subscription page, plan picker modal, persistent pages-left/reports-left counters, overage toggle, payment-failed banner, quota-exceeded modal.

All initial open questions have been resolved and folded into the spec above. Remaining items are process/validation, not product decisions:

  1. Legal / ToS review — overage disclosure wording, data retention on cancellation.
  2. Finance review — overage rates vs real LLM cost per page, collection risk on immediate read-only policy.
  3. Support runbook — draft responses for: payment failed, wrong quota shown, cancelled-but-charged, upgrade not reflected, data-export-on-read-only.

This spec is verified complete when:

  • Every cell of the pricing table is filled with a committed number.
  • All initial product decisions resolved (subscription ownership, cap behaviour, overage opt-in, quota units, reset cadence, rollover, failure refunds, plan changes, payment failure, cancellation, free trial, migration, notifications, data export, Enterprise handling).
  • Legal / finance review completed on items in §14.
  • Stripe products and prices defined in sandbox matching the pricing table (dry run only, no production wiring yet).
  • A 5-doctor shadow run through Phase 1 (counters only) shows accurate page and report counts for 2 weeks of real traffic.
  • Support runbook drafted per §14 item 4.