Contracts, invoices and client status
Active client, recurring split from one-off and pass-through
MRR by client and month with movement, NRR and GRR
Month-end close, partners' meeting and AI agent
What it solves
- One answer to how many active clients the agency has and what the MRR is.
- Every MRR change has a name: new, expansion, contraction, churn or reactivation.
- The agreed contract matches what was invoiced, and whatever does not match shows up on a list.
Business questions it answers
Ask your agent these questions once the case is live.
What you need
- The contract control connected to Nekt (spreadsheet, portal database or ERP)
- The service invoices from the finance ERP
- The active-client and contract-type rule agreed with the partners
What you get
- A client x month table with recurring MRR, one-off equivalent, phase and movement
- Active portfolio, NRR and GRR by month, quarter and 12 months
- A list of unmatched items between contracts and invoices
- An AI agent that answers about the portfolio with the right rule
Where to activate
MRR waterfall with new, expansion, contraction and churn, and the active portfolio alongside.
Answers about portfolio and revenue with the strict active-client definition already applied.
Invoices without a contract and contracts without an invoice, for finance to resolve before the close.
There are few rules, but contract control usually lives in a spreadsheet with names that do not match the invoice. Matching by CNPJ (company tax ID) and the exceptions list take most of the time. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
The contract control stores each client's current value and overwrites it when the scope changes. The invoice goes out under the legal name, which does not match the contract name. Whoever sums the whole registry mixes retainers with one-off projects, exempt clients and the agency itself; whoever sums the invoices mixes fees with pass-through media. The result is a different MRR at every meeting and a churn that erases the client from every past month.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
Active paying client = active status and a recurring contract type (retainer), excluding one-off projects, exempt clients and the agency's own account. The current portfolio is broader: active, onboarding and paused. The question 'how many clients do we have' gets the strict definition; the broad one always comes with its name. Late payment does not change client status: that belongs to finance.
MRR is monthly recurring retainer only. One-off projects, setup and training stay out; when they need comparing, they go in as a 12-month moving sum divided by 12, in a separate column, never added to MRR. Pass-through media budget and third-party production billed on the client's behalf are not agency revenue; media commission is.
Sum the installment amount of each accrual month, never the total contract value or the header value repeated on each row. Semiannual or annual contracts are divided by the months in the cycle. Contracts with no monthly value filled in are counted and shown, so nobody reads the MRR as complete.
Compare the client's recurring MRR in the month with the previous month. No MRR before and some now: new, or reactivation if they have paid before. Some before and none now: churn. Higher: expansion. Lower and above zero: contraction. In agencies' churn spreadsheets, 'partial churn' is contraction and 'scope swap' is not churn: the client stays.
A client marked as churned was still a client in the reference month if the exit date is on or after the first day of that month. Date precedence: churn date, then contract end, then status change date. With no date at all, keep the client. Active contracts run up to the current month; do not project the future as actuals.
The invoice uses the legal name and the contract uses the trade name. Match on the recipient's CNPJ (company tax ID); when only a name exists, normalize it (lowercase, no accents, letters and digits only) and keep an alias table for groups with several CNPJs. Publish the list of both unmatched sides: invoices without a contract and active contracts without an invoice. In a real base, the residue was close to 4% of 12-month billing.
Use invoices with issued status, not canceled, and with a value above R$ 1 to drop test invoices. Exclude the group's own CNPJs (intercompany). When the agency is a client of another company in the group, separate the row without deleting it.
Recurring contracts and charges are generated through the end of the term, sometimes more than a year ahead. Flag future-month rows instead of cutting them, and filter on read. Summing the whole table adds the schedule to what was delivered.
The registry only holds the current value and overwrites it when scope changes. Save a monthly MRR snapshot per client or read the adjustment history. When MRR falls and the client count does not move, check the history before calling it churn: it is usually a registry correction.
Count the client's month of life from the first month with recurring MRR. Months 1 to 3 are onboarding, 4 to 12 first year, 13 onward renewed. Contracts with no start date use the client's first contract.
How each status enters the metrics
Status and contract type from the client registry.
Definitions
Pitfalls that already happened
The registry total was above the real value because a contract had changed scope and the old value was still there. It was not churn, it was the registry.
Save the monthly snapshot and check the adjustment history.
The renewals consolidation combined retainer contracts, separately contracted solutions and manual renewals. A client with a retainer and two solutions appeared three times.
Count distinct clients, never contract rows.
A column created in the portal database did not appear in Nekt after a full sync, because the source's field selection had been saved in its configuration.
Redo the source's column selection step and run it again.
A sale's 'invoiced' flag switched to 'paid' after payment. Measuring billing by it returned only a small fraction of the sales that had been charged.
Invoiced = has a charge, whether invoiced or paid.
Revenue was joined to deliveries by client and month with an inner join. More than half of the money sat in months with no recorded delivery and disappeared without warning.
Full join, with flags for which side exists on the row.
A charge appeared in one unit's billing ERP and in the other unit's finance system. Summing both tables duplicated revenue.
One official source per business unit, never the sum of both.
Acceptance test
The case is done when every item passes.
- The count of active paying clients and the month's MRR match the contract registry on the same date (zero difference).
- For each client and month, previous MRR + new + reactivation + expansion - contraction - churn = current MRR.
- 12-month billing allocated by client plus the unmatched list adds up to the total of valid invoices in the ERP.
- No churned client disappears from the months before the exit date.
- GRR never exceeds 100%.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
Agency revenue and portfolio - Active paying client = active status and a recurring contract (retainer). Out: one-off, closed, exempt and the agency's own account. 'How many clients do we have' gets this definition. - Current portfolio = active + onboarding + paused. Use it only when asked for the portfolio. - MRR = sum of the accrual month's recurring installments. One-off enters only as 12-month total / 12, in a separate column. Pass-through media budget and on-behalf billing are not revenue. - Movement per client and month: new, reactivation, expansion, contraction, churn or flat, from the MRR difference against the previous month. Partial churn is contraction; a scope swap is not churn. - A churned client counts in a month until the exit date (churn date, then contract end, then status change). - Contract and invoice match on CNPJ. Whatever does not match is on the unmatched list; do not estimate. - Future-month rows are schedule, not revenue. - An MRR drop with no change in client count: check the adjustment history before calling it churn. Client exceptions: - <client>: group with CNPJs <list>, consolidated as one client. - <client>: annual contract of <value>, MRR = value / 12.
Build the "Agency revenue and portfolio" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/agencias/receita-carteira-agencia.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
When each client is a top-level task in a list (ClickUp), count only tasks without a parent, not archived, by task status.
PDF contracts extracted with AI for scope, MRR and term, always checked against the invoice before entering MRR.
Split each CNPJ's billing by the share of each service line in the contract's MRR, with a 'no breakdown' row for clients without a split.