Billing & Invoicing
Engine that turns subscription state + usage data + AI cost line items into invoices charged to the clinic. Romania-aware via per-org provider resolution; switchable provider impls (Stripe, FGO, Netopia, Euplatesc, etc.) behind capability interfaces.
Feature design pending
This feature ships as F12 in the implementation plan. Foundation accommodates it via four Cat A capability skeletons declared in 1C.1; the engine itself is not yet built. This page documents the locked architectural decisions and the planned shape; detailed schema + endpoints + UI surfaces lock when the F12 design phase starts.
What this enables
Subscription billing — the clinic is on a plan; we charge them every month (or annually) based on their subscription + actual usage.
Romanian compliance — for Romanian clinics, invoicing flows through FGO with e-Factura submission to ANAF; RO VAT is computed by the invoicing provider, not by us.
International billing — Stripe handles invoicing + tax automatically for non-RO clinics.
Usage-based components — overages on soft-meter quotas (email, SMS, video minutes, AI tokens) are billed as line items; the platform's metering layer (1C.7) provides the raw data.
AI cost passthrough — every AI call's cost is captured at call time (1C.8 ai_model_pricing_history); the billing engine sums per period, applies the platform's markup, and surfaces as an invoice line item.
Provider switchability — the same engine works regardless of payment / invoicing provider; provider name lives in the impl package only (Cat A pattern).
How it works
┌──────────────────────────┐ ┌──────────────────────────┐
│ Subscription State │ │ Usage Summaries │
│ (1B.3) │ │ (1C.7) │
│ organization_subscriptions │ organization_id │
│ tier_id, status, period │ │ capability, period │
└────────────┬─────────────┘ │ total_units, cost_cents │
│ └────────────┬─────────────┘
│ │
│ ┌──────────────────────────┐
│ │ AI Cost Roll-up │
│ │ (1C.8) │
│ │ audit_ai_provenance → │
│ │ ai_model_pricing_history│
│ └────────────┬─────────────┘
│ │
↓ ↓
┌──────────────────────────────────────┐
│ Invoice Generation Cron (F12) │
│ - Pull subscription state │
│ - Pull usage summaries │
│ - Pull AI cost line items + markup │
│ - Assemble line items │
│ - Resolve invoicing.Provider per-org│
│ - Call Provider.IssueInvoice(...) │
│ - Store invoice metadata locally │
└────────────┬─────────────────────────┘
│
↓
┌──────────────────────────────────────┐
│ Per-org invoicing.Provider impl │
│ - Stripe Invoicing (international) │
│ - FGO (Romania, with e-Factura) │
│ - Future: SmartBill, others │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ Per-org payment.Provider impl │
│ - Stripe (international + RO) │
│ - Netopia (RO option, optional) │
│ - Future: Euplatesc, others │
└──────────────────────────────────────┘
↑ ↑
│ │
CreateSubscription HandleWebhook
Charge (subscription.updated, payment.succeeded, etc.)
Refund → updates organization_subscriptions.statusThe engine's day-to-day work:
- Period close cron rolls usage_records → usage_summaries.
- Invoice cron generates invoices for each active subscription at period end.
- Webhook handlers (Cat D, 1C.6) consume payment provider events to update subscription state.
- Dunning retries failed payments on a schedule; suspends subscription on chronic failure with notification to clinic admin via 1A.18.
- Admin actions (refund, plan change, override grant) trigger the appropriate provider calls.
Provider strategy
Foundation declares four capability interfaces in internal/core/billing/:
| Interface | Purpose | When implemented |
|---|---|---|
payment.Provider | Charge the clinic; manage subscription on payment provider side | F12 |
invoicing.Provider | Generate + deliver invoice; handle tax + e-Factura submission | F12 |
patient_payment.Provider | Patient → platform payment (marketplace mediation) | Future feature |
clinic_payout.Provider | Platform → clinic payout (marketplace mediation) | Future feature |
Implementations are selected per-org via the 1C.2 resolver (platform_service_providers table). NULL organization_id rows = platform default; specific organization_id rows = per-org overrides for clinics with specific provider needs.
Foundation seeds default rows for payment + invoicing capabilities when F12 ships; per-org overrides are added when individual clinics need them.
Default impls
- Stripe for international
payment.Provider+invoicing.Provider(Stripe Invoicing + Stripe Tax). - FGO for Romanian
invoicing.Provider(handles RO VAT + e-Factura submission to ANAF). - Stripe for Romanian
payment.Providerby default; Netopia or Euplatesc as per-org override for clinics that specifically need them.
White-label tier
White-label clinics may use isolated platform-managed accounts (separate Stripe Connect account, separate FGO sub-account) for brand isolation. Configured via per-org override rows in platform_service_providers. Same Cat A pattern as any other capability.
Tax handling
The platform never computes tax rates itself. All tax is delegated to the invoicing provider:
- Stripe Invoicing + Stripe Tax — handles VAT/sales tax for US/EU/etc. automatically based on customer location.
- FGO — handles RO VAT (19% standard, with reduced rates for specific service categories) and e-Factura ANAF submission.
- Future Romanian alternatives (SmartBill, e-Factura direct) — same delegation pattern.
The invoicing.Provider.IssueInvoice interface accepts:
- Line items with descriptions + amounts.
- Customer info (clinic's
organization_billing.tax_id_encrypted,country,currency). - Period start/end + invoice date.
The provider returns the assembled invoice with tax computed; we store the invoice metadata locally (invoice number, amount, status) but don't compute or validate tax.
Patient billing — out of platform scope at foundation
Two patterns coexist:
Option A — Clinic-BYO (supported today)
Clinic uses their own payment infrastructure for patient billing. Platform never sees the money. When a patient pays in the clinic's system:
- Clinic's payment provider sends a webhook to the platform via Cat D inbound webhooks configured by the clinic.
- Platform updates
patient_subscriptions.statusso feature gating reflects payment status.
patient_subscriptions (1B.7) is informational at foundation — it records subscription state for our gating; the clinic's own system is the source of truth for whether the patient actually paid.
Option B — Marketplace mediation (future)
Patient pays platform; platform pays clinic minus a fee. See Marketplace Mediation in Deferred Foundation Extensions for the full description and what makes it a strategic future feature.
Foundation accommodates Option B via the patient_payment.Provider + clinic_payout.Provider skeletons; the engine itself ships in the future Marketplace Mediation feature.
Schema (foundation today)
What's already shipped at foundation:
organization_billing(1B.2) — billing pointers, contact, encrypted tax_id, currency,payment_provider(TEXT — accommodates any provider name).organization_subscriptions+organization_subscription_overrides(1B.3) — current plan + sales overrides per org.organization_subscription_entitlements+organization_subscription_limits(1B.3 + 1C.9 rename) — per-org snapshots of plan-granted entitlements (boolean) and quotas.patient_subscriptions(1B.7) — patient's tier subscription at a clinic; informational.usage_records+usage_quotas+usage_summaries(1C.7) — runtime metering substrate.ai_models+ai_model_pricing_history(1C.8) — historical pricing for accurate AI cost reconstruction.platform_service_providers(1C.2) — Cat A resolver for which provider impl serves which clinic.
What F12 adds:
invoicestable — invoice metadata, status, provider's invoice ID.invoice_line_items— line items per invoice.payments— payment attempts + outcomes (linked to invoices).dunning_attempts— failed-payment retry tracking.- New column:
tier_limits.overage_cents_per_unitfor soft-meter overage billing. - Cat D webhook handlers per payment provider.
Detailed schema lands when F12 design phase starts.
Cross-references
- F12 in the implementation plan — build plan, exit criteria, dependencies, open design questions.
- Foundation 1C.1 — Capability Framework — where the four billing capability interfaces are declared.
- Foundation 1C.2 — Curated Providers + Resolution — the resolver that selects per-org provider impl.
- Foundation 1C.7 — Metering & Quotas — usage substrate the billing engine reads.
- Foundation 1C.8 — AI Capability Hooks — AI cost capture with historical pricing.
- Marketplace Mediation in Deferred Extensions — the patient-side billing future.
- Glossary → Marketplace mediation — taxonomy.
- Tiers & Subscriptions architecture — the subscription data model.