> ## Documentation Index
> Fetch the complete documentation index at: https://docs.marginfront.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Types Reference

> Every canonical TypeScript interface the SDK returns, in one place

# Types Reference

Every canonical type the SDK exports, with the full interface definition and a plain-English description of what it represents and when you'd see it.

Money rule: **every dollar amount is `number`, not `string`.** Values come back at full precision. Round at render time, never before.

Null rule: **a `null` means "not applicable here," not zero.** Most commonly: `marginPercent: null` means "revenue was zero, so margin cannot be computed." Render as a dash, not `0%`.

***

## RevenueMetrics

The canonical revenue shape. Returned by `analytics.revenue`, embedded inside the revenue block of `customers.getWithRevenue` and `subscriptions.getWithRevenue`.

```typescript theme={null}
interface RevenueMetrics {
  revenue: number;
  cost: number;
  margin: number;
  marginPercent: number | null;

  usageRevenue: number;
  recurringRevenue: number;
  seatRevenue: number;
  onetimeRevenue: number;

  eventCount: number;
  eventCountWithNullCost: number;

  bySubscription: SubscriptionRevenue[];
  byStrategy: StrategyRevenue[];
}
```

**In plain English:** the whole revenue picture for a scope (org, one customer, one subscription, whatever you filtered by). Revenue is the full number including fees and prorations. Cost is what you paid to providers. Margin is revenue minus cost. The four xRevenue fields add up to the `revenue` total and tell you WHERE it came from (usage events, recurring fees, seats, or one-time charges). `eventCount` is every event; `eventCountWithNullCost` is the subset whose cost couldn't be calculated yet.

**When you'd see it:** any canonical analytics call, plus the revenue blocks on customer and subscription detail pages.

***

## SubscriptionRevenue

One row per active subscription inside `RevenueMetrics.bySubscription`.

```typescript theme={null}
interface SubscriptionRevenue {
  subscriptionId: string;
  customerId: string;
  agentId: string;
  planId: string;
  revenue: number;
  cost: number;
  margin: number;
  usageRevenue: number;
  recurringRevenue: number;
  seatRevenue: number;
  onetimeRevenue: number;
  eventCount: number;
}
```

**In plain English:** how one specific subscription contributed to the overall revenue. Useful for sorting "who are my biggest-revenue subscriptions" or drilling into a specific sub's margin.

**When you'd see it:** inside `RevenueMetrics.bySubscription`, returned by `analytics.revenue` and the two `getWithRevenue` overlays.

***

## StrategyRevenue

One row per pricing strategy inside `RevenueMetrics.byStrategy`.

```typescript theme={null}
interface StrategyRevenue {
  strategyId: string;
  chargeType: ChargeType;
  pricingModel: PricingModel | null;
  signalId: string | null;
  revenue: number;
  quantity: number;
}
```

**In plain English:** how one specific pricing rule contributed to the overall revenue. `chargeType` tells you whether this was a usage rate, a recurring fee, a seat fee, or a one-time charge. `pricingModel` tells you the shape of usage rates (flat/graduated/volume/credit\_pool). For usage strategies, `quantity` is the total quantity that ran through the rate in the window; for non-usage strategies it's `0`.

**When you'd see it:** inside `RevenueMetrics.byStrategy`.

***

## CostMetrics

The canonical cost shape. Returned by `analytics.costBreakdown`.

```typescript theme={null}
interface CostMetrics {
  cost: number;
  eventCount: number;
  eventCountWithNullCost: number;
  byAgent: CostByAgentRow[];
  byCustomer: CostByCustomerRow[];
  bySignal: CostBySignalRow[];
  byDay: CostByDayRow[];
  byPlan: CostByPlanRow[];
  byModel: CostByModelRow[];
  prior?: Omit<CostMetrics, "prior">;
}
```

**In plain English:** your total service cost in a window, sliced six different ways so you can find where the money is going. `prior` is a same-length window immediately before `startDate`, populated only when you asked for it with `includePriorWindow: true`.

**When you'd see it:** `analytics.costBreakdown`.

***

## CostByAgentRow

```typescript theme={null}
interface CostByAgentRow {
  agentId: string;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost attributed to one agent in the window.

***

## CostByCustomerRow

```typescript theme={null}
interface CostByCustomerRow {
  customerId: string;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost attributed to one customer in the window.

***

## CostBySignalRow

```typescript theme={null}
interface CostBySignalRow {
  signalId: string | null;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost attributed to one signal in the window. `signalId: null` covers orphan events that aren't tied to a signal.

***

## CostByDayRow

```typescript theme={null}
interface CostByDayRow {
  date: string;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost for one UTC calendar day. One row per day with activity. `date` is an ISO string (JSON doesn't carry Date objects); convert on your side if you need a `Date`.

***

## CostByPlanRow

```typescript theme={null}
interface CostByPlanRow {
  planId: string | null;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost attributed to one pricing plan in the window. `planId: null` covers events whose subscription isn't on a plan.

***

## CostByModelRow

```typescript theme={null}
interface CostByModelRow {
  model: string | null;
  cost: number;
  eventCount: number;
}
```

**In plain English:** cost attributed to one LLM model in the window. `model: null` covers non-LLM events and events whose model wasn't recognized yet.

***

## AgentEarned

The canonical shape returned by `analytics.agentEarned`.

```typescript theme={null}
interface AgentEarned {
  revenue: number;
  eventCount: number;
  bySubscription: AgentEarnedSubscriptionRow[];
  byStrategy: AgentEarnedStrategyRow[];
}
```

**In plain English:** activity-only revenue. Usage events × pricing strategy rates, summed up. No recurring fees, no seat fees, no one-time charges, no prorations. The earliest leading indicator that agents are doing billable work.

**When you'd see it:** `analytics.agentEarned`.

***

## AgentEarnedSubscriptionRow

```typescript theme={null}
interface AgentEarnedSubscriptionRow {
  subscriptionId: string;
  customerId: string;
  agentId: string;
  planId: string;
  revenue: number;
  eventCount: number;
}
```

**In plain English:** activity-revenue contribution from one subscription.

***

## AgentEarnedStrategyRow

```typescript theme={null}
interface AgentEarnedStrategyRow {
  strategyId: string;
  pricingModel: PricingModel | null;
  signalId: string | null;
  revenue: number;
  quantity: number;
}
```

**In plain English:** activity-revenue contribution from one pricing strategy. `quantity` is the total quantity that ran through the rate.

***

## InvoiceTotals

The canonical invoice-totals shape. Returned by `analytics.invoiceTotals`.

```typescript theme={null}
interface InvoiceTotals {
  billed: number;
  collected: number;
  draft: number;
  outstanding: number;
  overdueAmount: number;
  overdueCount: number;
  invoicesSentCount: number;
}
```

**In plain English:** finance-team numbers. `billed` is what you invoiced in the window (status issued or overdue), counted by invoice date. `collected` is the cash that landed in the window — payments that went through with a payment date in the window, net of refunds, counted by the day the money arrived (not the invoice date). `draft` is inventory of invoices not yet sent. `outstanding` is what's open right now — issued or overdue and not yet paid, a current-state number with no date window that's always zero or more. `overdueAmount` and `overdueCount` are current-state right now (not filtered by the date window). `invoicesSentCount` is how many non-draft invoices were dated in the window.

**When you'd see it:** `analytics.invoiceTotals`.

***

## Mrr

Returned by `analytics.mrr`.

```typescript theme={null}
interface Mrr {
  mrr: number;
  arr: number;
}
```

**In plain English:** last complete calendar month's billed total, plus its annualized version (`mrr × 12`). Stable across the current month (doesn't move until the next month rolls over).

**When you'd see it:** `analytics.mrr`.

***

## RunRateMrrResult

Returned by `analytics.runRateMrr`.

```typescript theme={null}
interface RunRateMrrResult {
  mrr: number;
  breakdown: RunRateMrrBreakdownRow[];
}
```

**In plain English:** what MRR would be if the last 30 days of activity kept going at this pace. Recurring + seat + actual usage, monthly-normalized. One breakdown row per active subscription.

**When you'd see it:** `analytics.runRateMrr`.

***

## RunRateMrrBreakdownRow

```typescript theme={null}
interface RunRateMrrBreakdownRow {
  subscriptionId: string;
  customerId: string;
  agentId: string;
  planId: string;
  recurring: number;
  seatBased: number;
  usage: number;
  total: number;
}
```

**In plain English:** per-subscription slice of run-rate MRR. `recurring` is the monthly-normalized recurring fees. `seatBased` is seat fees based on max(booked, minimum) seats. `usage` is actual last-30-days events run through the pricing rate. The three add up to `total`, and all the `total`s add up to the top-level `mrr`.

***

## CommittedMrrResult

Returned by `analytics.committedMrr`.

```typescript theme={null}
interface CommittedMrrResult {
  mrr: number;
  breakdown: CommittedMrrBreakdownRow[];
}
```

**In plain English:** contractual floor. The monthly revenue your contracts guarantee, regardless of whether customers actually use the product. By definition, this is always less than or equal to `RunRateMrrResult.mrr`.

**When you'd see it:** `analytics.committedMrr`.

***

## CommittedMrrBreakdownRow

```typescript theme={null}
interface CommittedMrrBreakdownRow {
  subscriptionId: string;
  customerId: string;
  agentId: string;
  planId: string;
  recurring: number;
  seatBased: number;
  usage: number;
  total: number;
}
```

**In plain English:** per-subscription slice of committed MRR. Same shape as the run-rate breakdown, but the `usage` column is `minimum_commitment × rate` (or `0` when the pricing strategy has no minimum set), not actual usage.

***

## SubscriptionDetailWithRevenue

Returned by `subscriptions.getWithRevenue`.

```typescript theme={null}
interface SubscriptionDetailWithRevenue {
  subscription: SubscriptionDetail;
  revenue: RevenueMetrics;
}
```

**In plain English:** a wrapper that pairs the normal subscription record with a canonical revenue block scoped to that subscription for a date window. Lets you build a subscription detail page in one round trip.

**When you'd see it:** `subscriptions.getWithRevenue`.

***

## CustomerDetailWithRevenue

Returned by `customers.getWithRevenue`.

```typescript theme={null}
interface CustomerDetailWithRevenue {
  customer: Customer;
  revenue: RevenueMetrics;
}
```

**In plain English:** a wrapper that pairs the normal customer record with a canonical revenue block scoped to that customer for a date window. Lets you build a customer detail page in one round trip.

**When you'd see it:** `customers.getWithRevenue`.

***

## Parameter types (for completeness)

All canonical analytics methods accept typed parameter objects. These are exported so you can use them in your own function signatures.

### RevenueMetricsParams

```typescript theme={null}
interface RevenueMetricsParams {
  startDate: string;
  endDate: string;
  customerId?: string;
  agentId?: string;
  signalId?: string;
  subscriptionId?: string;
}
```

### CostMetricsParams

```typescript theme={null}
interface CostMetricsParams {
  startDate: string;
  endDate: string;
  customerId?: string;
  agentId?: string;
  signalId?: string;
  subscriptionId?: string;
  includePriorWindow?: boolean;
}
```

### InvoiceTotalsParams

```typescript theme={null}
interface InvoiceTotalsParams {
  startDate: string;
  endDate: string;
  customerId?: string;
}
```

Invoice totals accept a narrower filter surface than revenue (only `customerId`). That's intentional: invoice math runs at the customer scope, not per-subscription or per-signal.

### MrrParams

```typescript theme={null}
interface MrrParams {
  customerId?: string;
  subscriptionId?: string;
}
```

MRR methods do not take a date window. `analytics.mrr` uses a fixed "last complete calendar month" window. `analytics.runRateMrr` uses a fixed "last 30 days" window. `analytics.committedMrr` is not window-dependent at all.

### AgentEarnedParams

```typescript theme={null}
interface AgentEarnedParams {
  startDate: string;
  endDate: string;
  customerId?: string;
  agentId?: string;
  signalId?: string;
  subscriptionId?: string;
}
```

***

## Rounding and precision

Every money field in every type above is a raw `number`. No pre-rounding, no string wrapping.

Round exactly once, at the UI boundary:

```typescript theme={null}
const metrics = await mf.analytics.revenue({ ... });

// Right
display(metrics.revenue.toFixed(2));

// Wrong: compounds rounding errors across downstream math
const rounded = Number(metrics.revenue.toFixed(2));
const later = rounded * someMultiplier;
```

***

## Next steps

* **[Analytics](/sdk/analytics)**: the seven methods that return these shapes
* **[Subscriptions](/sdk/subscriptions)**: where `SubscriptionDetailWithRevenue` comes from
* **[Customers](/sdk/customers)**: where `CustomerDetailWithRevenue` comes from
