Billing manages organization subscriptions, plan tiers, monthly credits, and current-month usage through Stripe checkout, billing portal, and signature-verified webhook flows. BillingController creates Checkout and Portal sessions and returns plan, credit-balance, and usage summaries, while BillingService maps checkout keys to configured Stripe prices. PlanGuard and RequiresPlan gate routes or controllers by required plan level, and credit-cost constants meter AI and technical-documentation operations.
24 entities in atloria-monorepo/apps/api/src/billing. 9 other subsystems depend on it, which makes it the 5th most depended-upon part of this codebase.
What it is made of
Its 24 entities sit in 8 files under atloria-monorepo/apps/api/src/billing: 11 constants, 4 HTTP endpoints, 3 services, 2 type aliases and 4 more.
billing.constants.ts holds 10 of them — more than any other file here.
BillingService declares 4 methods, the widest surface here.
Where work enters
1 controller publishes 4 HTTP endpoints — 2 POST and 2 GET. They answer under /billing. Every one of them sits behind JwtAuthGuard.
BillingController—atloria-monorepo/apps/api/src/billing/billing.controller.ts:23checkout—atloria-monorepo/apps/api/src/billing/billing.controller.ts:29portal—atloria-monorepo/apps/api/src/billing/billing.controller.ts:41summary—atloria-monorepo/apps/api/src/billing/billing.controller.ts:49webhook—atloria-monorepo/apps/api/src/billing/billing.controller.ts:57BillingModule—atloria-monorepo/apps/api/src/billing/billing.module.ts:14
How work moves through it
mermaidflowchart LR BillingController0["BillingController"] BillingService10["BillingService"] BillingController0 --> BillingService10 PrismaService20["PrismaService"] BillingService10 --> PrismaService20 AIUsageService21["AIUsageService"] BillingService10 --> AIUsageService21 stop["refused"] BillingService10 -. "NotFoundException" .-> stop
Work enters at BillingController and passes through 3 other components. Each step below is a dependency edge between two entities in this repository, followed outward in order.
BillingControllertakes the work first —atloria-monorepo/apps/api/src/billing/billing.controller.ts:23.- Next,
BillingControllerhands off toBillingService—atloria-monorepo/apps/api/src/billing/billing.service.ts:23. - Finally,
BillingServicecallsPrismaServiceandAIUsageService.
Where the work stops
BillingServicestops the work withNotFoundExceptionwhen!org— “Organization not found”, in 3 places.BillingServicestops the work withBadRequestExceptionwhen!envVar.AIUsageServicestops the work withBadRequestExceptionwhen!Number.isFinite(amount) || amount <= 0— “Credit deduction amount must be a positive number”.AIUsageServicestops the work withPaymentRequiredExceptionwhenresult.count === 0.
When a step fails
BillingServicehandles failure in 1 place: it lets it reach the caller in all 1.PrismaServicehandles failure in 1 place: it lets it reach the caller in all 1.AIUsageServicehandles failure in 1 place: it logs it and continues in all 1.
How it refuses and fails
3 of its components record a refusal or a failure handler.
All 3 of them refuse work outright, under a condition written into the component itself.
Their catch blocks handle a failure that already happened in 1 place.
Boundaries
9 other subsystems depend on this one — Api, Auth, Branding, Documentation, Platform, Project, Reader Access, Reader Account, Scim. Changing what it exposes changes them.
Those 9 hold 15 edges between them, unevenly: Branding reaches in across 2 edges, while 3 of them hold one each. 15 edges arrive against 6 leaving — more of this repository reaches into it than it reaches out to. What they reach is narrower than the folder: 2 of its 24 members carry every inbound edge — BillingModule (9) and PlanService (6). Of the 6 it sends out, 3 go to Database — more than to any other.
It depends on Database, Auth, Ai, and on nothing else in this repository.
Was this page helpful?