well_measure_customer_ltv

shallow

io.github.WellApp-ai/well-mcp · Verify this server

Measure the revenue lifetime value (LTV) of every customer the workspace invoiced over a window of whole months, with the portfolio churn and lifespan it rests on. It draws nothing. Use it to rank customers by lifetime value, or to state what a customer is worth over its life. Do not use it for revenue in a period (`well_sum_invoices`), for recurring revenue (MRR), or for what customers still owe (receivables aging). Do not page `well_query_records` to rebuild this figure: this read covers every invoice in the window, unless `partial` is true (a month with very many customers can be cut short; see below). **The rule is fixed, and `rule` echoes it on every call.** LTV = average order value x monthly purchase frequency x lifespan in months. It is a REVENUE LTV: no margin or cost is applied, so say "revenue lifetime value" and never present it as profit. - Revenue: the billing documents the workspace ISSUED and did not cancel (a draft is not issued, so it is left out), net of tax (`items_total`), credit notes netted. Payment status plays no part. - Per customer and currency: `aov` = `net_revenue` / `invoice_count`; `monthly_frequency` = `invoice_count` / `active_span_months`, where the span runs from the customer's first invoice month to the last month of the window, for every customer including a churned one. `net_revenue` is what the customer was billed over the window: give it beside the LTV. - A churned customer's LTV: A churned customer's LTV can be lower than its billed net revenue, because its frequency counts the months after it churned, and it moves with the window end. Do not present it as what the customer was worth: net_revenue is what it was billed. State that limit when you name a churned customer's LTV (`churned: true`), and name the window end it depends on. - Churned: no invoice for 2 x the customer's usual interval (the median gap between its invoice months), and at least 3 months. A customer invoiced in one month only takes the 3-month floor. - Portfolio: `monthly_churn` = churned customers / `observed_customer_months`, the months customers were at risk of churning (a customer counts from its first invoice month until it churns, or until the window ends if it has not churned; a churned customer adds no month after its churn); `lifespan_months` = 1 / `monthly_churn`, capped at 60. `cap_applied: true` means the lifespan IS the cap (zero churn, or a churn so low its inverse passes the cap): state that the cap applied, and give the churned count beside it. - A window with no invoiced customer gives `rows: []` and a null `monthly_churn` and `lifespan_months`. Say the window holds no invoiced customers. State no LTV, lifespan or churn for it, and do not call it zero churn. - A customer flagged `young` has an active span under 12 months: its frequency is normalised per month over that short span. Say so when you name one. **The window is whole, COMPLETE months, given one of two ways, never both.** - By its length: `last_complete_months` (1 to 60). The server reads that many complete months, ending with the last complete month. Use it for "the last N months" and for the default window, `last_complete_months: 60`, rather than working the dates out yourself. - By its bounds: `from` and `to`, both the first day of a month, as YYYY-MM-01; `from` is inclusive and `to` is EXCLUSIVE. Use them for a named period, such as a calendar year. The window may not reach the running month, so `to` is at most the first day of the current month, and it covers at most 60 months. The result's `window` echoes the `from` and `to` read and `month_count`, the complete months they cover. State the window from that echo: `month_count` months, from `from` to the month before `to`. **Amounts are never converted.** Each row is one customer in ONE currency, and `currencies` summarises each currency apart. Never add rows of two currencies without converting them first at a rate you can state. A customer billed in two currencies has two rows; converted, they add up. **`counterparty_alias_sets` folds company rows that are one customer.** Pass the sets the own-company step confirmed, as arrays of company ids; each set folds into its first id, and `alias_company_ids` lists what was folded. Without it nothing is folded. **The workspace's own company should be set.** Without it Well cannot tell what the workspace issued: the call still returns, but `party_scope.side_unknown` is true, no side filter was applied and the ranking covers invoices on both sides. Say the side is unknown, never that these are the customers' figures; resolve the own company, then call again for a true ranking. **What the figure cannot reach, stated beside it:** - `unattributed_count`: billing documents Well could place on neither side. They may belong to a customer; state the count when it is above zero. `null` means the count failed, which is not `0`. - `excluded_draft_count`: drafts in the window. They are in no row, and a connector or document import can keep a real invoice at draft, so state the count when it is above zero. `null` means the count failed. - `excluded_no_customer`: issued documents with no identified customer. They are in no row. - `excluded_malformed`: issued documents with no readable net amount or no currency. `null` means the count failed. - `credit_note_only_count`: customer and currency pairs with credit notes and no invoice in the window. - `corrected_or_consolidated_count`: corrected or consolidated invoices among the rows, which may count billing twice with the invoices they replace. - `omitted_row_count`: rows past the first 100 of a currency. They still count in `currencies` and `portfolio`. - `partial: true` means a monthly read was cut short, so some customers' invoices are missing. That can move a customer's churn, the lifespan and every LTV in either direction: the figures are not bounds. Name the truncation in the reply and do not present any figure as a minimum or a maximum. When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass `workspace_id` on the call.

100.0/100

1 trials · measured 2 days ago

well_measure_customer_ltv scores 100.0/100 on Vouch's measured behaviour index, from 1 real invocation trials against io.github.WellApp-ai/well-mcp, measured 18 Oct 2026 under methodology v0.2.0. Every measured component scored 100.

Component breakdown

ComponentWeightValue
Reliability35%not applicable
Schema integrity25%100.0
Failure behaviour15%not applicable
Latency15%not applicable
Concurrency10%not applicable

Tool details

Transport
remote
Credential class
gated
Input schema
not declared
Output schema
not declared
Side-effect classification
unclassified

Score history

DayScoreTierMethodology
2026-10-18100.0shallowv0.2.0

Probe evidence

ProbeOutcomes
schema_integritypass: 1

Raw request/response logs are not archived yet — the outcome counts above are drawn directly from every recorded trial.

Embed this score

Available for every tool, scored or not — not a verification perk. Always links back to this page.

Vouch score: well_measure_customer_ltv
[![Vouch score](https://vouch.tools/api/tools/0cfa35c7-f863-4e97-b119-90b5e7caaa0b/badge.svg)](https://vouch.tools/tools/0cfa35c7-f863-4e97-b119-90b5e7caaa0b)
well_measure_customer_ltv — Vouch