Customer Revenue
Morse already attributes traced LLM cost to each customer_id you send with
set_context(). Customer Revenue adds the other half: what each customer paid you
for a calendar month. Next to each customer you then see Revenue − traced AI cost and the same
amount as a % of revenue.
It lives on the Cost page, in the Segments tab, under Customer revenue.
What the number is, and is not
The figure is revenue minus traced AI cost: the revenue you entered for the month minus the LLM
cost Morse traced for that customer_id in the same month. It is not a profit margin.
Traced LLM cost only; infra, eval and untraced calls excluded.
That sentence is printed under the table on purpose. Hosting, eval runs, untraced model calls and anything else outside your traces are not in the cost, so the amount is an upper bound on what is left after AI cost. Morse never estimates or allocates those costs for you.
Above the table, a basis line names exactly what was left out of the month’s cost, for example “Revenue minus traced AI cost so far this month · left out: $18.40 on 212 traces with no customer_id (not spread over customers); 4 model calls with no price; spend that was never traced”. Untraced spend is always on the list.
What you see
Month and totals
Pick a calendar month (UTC). The current month is labeled month to date; cost is the whole
month so far, never a rolling window. There is no month-over-month change on this view. The strip
above the table shows revenue entered, traced AI cost, and the share of that cost that carries a
customer_id.
Customer table
One row per customer, with revenue, traced AI cost, Revenue − traced AI cost, % of revenue and a link to that customer’s traces for the month.
- A customer with traced cost but no revenue shows cost only and — add revenue. Morse shows no revenue-minus-cost value for them, never an implied one.
- A customer with revenue but no traces that month shows cost
$0and the label no traced cost. - Cost with no
customer_idappears once, as Unattributed. It is never spread across customers. - Every row links to the Traces list filtered to that
customer_idand month, so you can check the cost behind the number.
Partial rows
A row is flagged partial, with a lower bound note next to the value, when:
- fewer than 95% of that customer’s spans were priced, or
- fewer than 80% of the month’s traced cost carries a
customer_id(then every row is flagged).
A partial figure is not a confident one: some cost is missing from it.
Add revenue
Choose Add or upload revenue.
- One customer: enter the
customer_id, month and USD amount. Entering the same customer and month again replaces the earlier amount. - CSV: upload a file with the header
customer_id,month,revenue_usd, with month asYYYY-MM(for exampleacme,2026-09,1200.00). Amounts are USD, 0 or more.
Only organization owners and admins can add, change or remove revenue; every member can read it.
Keys must match exactly
customer_id values are compared as text after trimming spaces: 42 matches 42, but Acme does not
match acme. There is no fuzzy matching. If your trace values and your CSV differ in case, both
appear in the reconciliation summary and neither is matched.
Upload checks
Every row is validated before anything is saved. If any row is invalid, no rows are saved and the error names the line. After a successful upload Morse shows a reconciliation summary: how many keys matched traced customers, which revenue keys have no traces for the uploaded months, and which traced customers have no revenue.
Before you have data
- No traced cost and no revenue for the month: the view says so and offers Add or upload revenue.
- No
customer_idon your traces: add it once withset_context(customer_id=...); until then all cost shows as Unattributed.
Related
- Cost — the Segments tab and how traced spend is priced.
- Set context — how traces get a
customer_id. - Budgets and Forecast — spend limits and alerts for the same traced cost.