How ninedot calculates revenue.
Monthly revenue in ninedot is subscription revenue normalised to a month, plus one-off sales over the last 30 days, read from your payment provider. Here is exactly how each part is worked out.
Monthly revenue
Revenue / mo = recurring revenue from live subscriptions + one-off sales in the last 30 days, in the account's main currency. It's read from the payment provider on every sync (at least hourly), never typed in.
Which subscriptions count
- Active subscriptions count. So do past-due ones (the latest payment failed but the subscription isn't cancelled yet); they're flagged as failing payments.
- Trials don't count until they convert. Cancelled, expired, paused and incomplete subscriptions don't count.
- Each price is normalised to a month: yearly ÷ 12, weekly × 52 ÷ 12, daily × 365 ÷ 12, and a price billed every 3 months ÷ 3. Quantity multiplies it.
- Usage-based (metered) prices count as zero, because they can't be known in advance, and mark the figure as measured.
- A discount or coupon marks the figure as measured, since the list price may not be what's collected.
One-off sales
- Paid one-time purchases in the last 30 days are added: a shop's items, lifetime deals, one-off courses. Tax is taken off.
- Payments that start or renew a subscription aren't counted again: they're already in recurring revenue.
- Stripe: paid Checkout Sessions in payment mode, by product (refunds aren't subtracted). Lemon Squeezy: paid and partly refunded orders, net of tax and refunds. Polar: one-time purchases, net of discounts and refunds. Paddle: completed transactions without a subscription, net of tax and adjustments.
- Because sales are a rolling 30-day window, a figure that includes them is measured rather than exact.
Currencies
- Each account is reported in its main currency: the one most recurring revenue is in, or most sales if there are no subscriptions.
- Amounts in other currencies are left out and the service says so. ninedot never converts currencies, so a business in USD and one in AUD are never added together.
Only real money counts
- Stripe test-mode keys, Paddle sandbox keys and Lemon Squeezy test-mode keys are refused, and test-mode records are ignored, so made-up payments can never become revenue.
- Keys are read-only wherever the provider allows it, and ninedot never changes anything in a provider account.
Trust levels
- Exact: read directly from the provider's subscriptions or billing.
- Measured: derived from usage or a rolling window (30-day sales, AI API spend, discounted or metered subscriptions, RevenueCat's own MRR).
- Only exact and measured figures from a connected provider are verified. The database refuses anything else in totals and history.
- Every figure shows its trust level, its source and how fresh it is.
Products and the business
Each product you sell through Stripe, Lemon Squeezy, Polar or Paddle can sit on the business that sells it, so a shared payment account splits correctly across businesses. On a business's map, its products fold into one node per payment account. An account is linked whole or product by product, never both, so revenue can't be counted twice.
Costs and margin
- Costs come from each provider that reports them: for example Vercel's billing, OpenAI and Anthropic API spend over the last 30 days, and Stripe's fees over the last 30 days.
- Plan list prices are only ever estimates to confirm, never counted as verified.
- A cost you confirm yourself (for something no provider reports) counts in your own totals and margin, labelled “Confirmed by you”. It never counts as verified and stays out of history.
- Margin = monthly revenue minus monthly cost, per business, only when both are in the same currency.
RevenueCat
For apps on RevenueCat, ninedot shows the MRR RevenueCat reports for each project (in USD), labelled measured, because RevenueCat works it out from App Store and Google Play receipts that ninedot can't check one by one.
History
Every sync records verified revenue and cost per service. Charts show each day's closing figure, each service's last value carried forward until it changes, and each month's figure is its value at the month's close, with the current month live.
Per provider details: integrations. For AI agents: MCP server.