# Billing

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`:23
- `checkout` — `atloria-monorepo/apps/api/src/billing/billing.controller.ts`:29
- `portal` — `atloria-monorepo/apps/api/src/billing/billing.controller.ts`:41
- `summary` — `atloria-monorepo/apps/api/src/billing/billing.controller.ts`:49
- `webhook` — `atloria-monorepo/apps/api/src/billing/billing.controller.ts`:57
- `BillingModule` — `atloria-monorepo/apps/api/src/billing/billing.module.ts`:14

## How work moves through it

```mermaid
flowchart 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.

1. **`BillingController`** takes the work first — `atloria-monorepo/apps/api/src/billing/billing.controller.ts`:23.
2. **Next**, `BillingController` hands off to `BillingService` — `atloria-monorepo/apps/api/src/billing/billing.service.ts`:23.
3. **Finally**, `BillingService` calls `PrismaService` and `AIUsageService`.

### Where the work stops

- `BillingService` stops the work with `NotFoundException` when `!org` — “Organization not found”, in 3 places.
- `BillingService` stops the work with `BadRequestException` when `!envVar`.
- `AIUsageService` stops the work with `BadRequestException` when `!Number.isFinite(amount) || amount <= 0` — “Credit deduction amount must be a positive number”.
- `AIUsageService` stops the work with `PaymentRequiredException` when `result.count === 0`.

### When a step fails

- `BillingService` handles failure in 1 place: it lets it reach the caller in all 1.
- `PrismaService` handles failure in 1 place: it lets it reach the caller in all 1.
- `AIUsageService` handles 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.
