Ask any deal team what their CRM's confidence number means and you will get a shrug. It means somebody set a stage, somebody typed a percentage, and the software multiplied them together. The number describes how diligently the pipeline was maintained, not how interested the counterparty is. That is a strange thing to run a business on, and it is the gap this work set out to close.
01 · The number, and where it comes from
A deal in Meridian usually has one or more data rooms attached to it, because that is how the documents were shared in the first place. The room already records what happened inside it: who opened it, how recently, how many sessions, how many pages, which documents, whether they signed the NDA, whether they asked anything. None of that is self-reported. It is the counterparty's own behaviour.
So the deal desk had a source of truth available to it that a standalone CRM simply does not have. The work was to use it honestly: to measure rather than infer, and then to show the measurement rather than hide it behind a dial. A score you cannot interrogate is decoration. A score that opens into five numbered factors, each with the points it contributed, is evidence.
That principle drove the rest of the build. Where the product suggests something, it names the fact that produced it. Where it cannot measure something, it says so instead of showing a zero.
02 · What existed, and what was missing
It is worth being precise about this, because the honest description of the work is not "we built a CRM". The pipeline engine already ran: configurable pipelines with editable stages, a drag and drop board, deal health drawn from room engagement, team sharing with roles, a permanent audit trail, forecasting, connectors to HubSpot, Pipedrive and Salesforce, event webhooks, and a follow-up engine with a reminder ladder.
What did not exist was the product around it. The CRM pages were standalone documents, each carrying its own copy of the chrome and its own hard-coded palette. There was nowhere for a customer's identity to live. There was one shared bot with our name on it. Every deal had the same shape. And the intelligence layer, the part that turns a record into a prompt to act, was not there at all.
Five phases, each shipped live and verified before the next began.
| Phase | What it delivered |
|---|---|
| Shell | One application frame across every page, and a theme layer in which no component names a colour. |
| Tenancy | Organisations, seats and white-label branding, with resource ownership left exactly where it was. |
| Channels | Each organisation's own Telegram bot and, optionally, its own Slack app. |
| Modelling | Custom fields, deal types, and full table and forecast views. |
| Intelligence | Explainable health, risk flags on cards, and next best actions with their evidence attached. |
03 · One frame, no colour in a component
The first phase is the least glamorous and the one everything else depended on. Every colour, radius, spacing step and type size in the product is now declared in a single token file, and nothing downstream names a colour. The parchment palette KXCO runs on is simply the default theme rather than a built-in assumption.
That is what makes white-label a change of about a dozen custom properties instead of a rewrite, and it is why phase two could ship a working branding page in an afternoon. Around it sits one frame: a sidebar covering the whole product, a top bar with global search across deals, companies, people and rooms, and a footer whose status indicator reports an actual API call rather than asserting good health.
Every surface has an empty state that explains what to do next. One small detail matters more than it looks: a brand-new account shows its win rate and average cycle as blank, never as zero. A fresh account claiming a nought per cent win rate is a lie about its own data, and a product that tells small lies about small things is not trusted with large ones.
04 · Organisations, and the seat that grants nothing
Every account now belongs to an organisation. The migration ran on live data and moved nothing: 195 accounts became 195 organisations of one, each named from the company already on the account and seeded with the brand colour and logo it already carried. The organisation is where identity lives, which is to say where a customer's name, logo, palette and seat list belong.
The rule that governs it is deliberately blunt. A seat grants nothing. Adding somebody to your organisation gives them membership and not one deal, room or document. Even an organisation admin, who can rename the organisation and manage its people, sees no deal they were not individually given. Access is still granted deal by deal through the existing share model, and there is a test that adds a person as an admin and then asserts they still cannot see the deal. It fails the moment that stops being true.
Two structural properties support it. No function and no route anywhere accepts an organisation identifier, so a caller can only ever act on their own. And the whole phase was additive: new tables, one nullable column, no ownership moved, and no existing permission check altered. The full test suite passed with every pre-existing test file untouched, which is a stronger claim than passing tests that were edited to fit.
05 · Your own bot, your own Slack app
A Telegram bot is inseparable from its token, so there is no honest way to give a customer a bot that is genuinely theirs except to have them create it. The setup page walks through BotFather in four steps, and it takes about two minutes. What happens to the token afterwards is the part that matters.
- Encrypted at rest with AES-256-GCM, never written to a log, and never returned by any endpoint once saved. There is no screen anywhere that shows it back to you, because there is no reason to.
- Revocable without us. The customer can regenerate it in BotFather at any moment and alerts simply stop. If the server's own signing secret is ever rotated, stored tokens stop decrypting, and rather than quietly falling back to the platform bot and sending under the wrong name, delivery fails and the page asks them to reconnect.
- Delivered by webhook, not polling. Polling one bot every sixty seconds is tolerable; polling fifty is the wrong shape. Each bot gets an unguessable callback path and its own secret header, compared in constant time, and failing either returns the same response as a path that does not exist.
- Codes are bound to their organisation. A link code minted inside one organisation is refused by another organisation's bot, so a leaked code is worthless anywhere but home.
Slack offers two routes, and the difference is worth being precise about because it is usually blurred. Installing the platform app takes one click, and the workspace is already entirely separate: installs are keyed per workspace and no message crosses between them. But the app carries our name. An organisation that wants its own name and icon on every message registers its own Slack app and stores the credentials here, which is roughly a ten-minute job at api.slack.com. Request verification tries the platform signing secret first and then each organisation's, so a customer's own app verifies without weakening anything.
Your own bot if you have connected one, the platform bot only if you have not. That is stated on the setup page rather than left to be discovered, and a test message button proves the path works before anybody trusts it with a live deal.
06 · Modelling the deals you actually run
Custom fields come in nine types: text, long text, number, currency, date, dropdown, multi-select, checkbox and URL. They belong to the organisation, so two customers on the same server model completely different transactions and neither sees a field belonging to the other.
Values are typed on the way in and on the way out. A number comes back a number and a date stays sortable, and a bad value fails the write naming the offending field rather than half-saving and leaving a mess to discover later. One thing is deliberately impossible: a field's type never changes once it exists, because values already stored under it would quietly stop meaning what they meant. Delete it and make another.
Deal types sit above the fields. Each carries its own default stages and its own set of fields, so an investment and a partnership do not have to pretend to be the same object. A field with no type applies everywhere; a field pinned to a type appears only there. A type still in use cannot be deleted out from under its deals, which is the sort of guard that costs an afternoon and saves a support conversation.
None of this is required. A new account has name, company, value, probability, stage and close date without any setup at all, and the suggested stage sets are offered as starting points rather than imposed.
07 · The table and the forecast
The board is the default because deals are a flow. The table is for the days when they are a list. It sorts on any column, hides and shows columns, resizes by dragging with the widths remembered per browser, pins the first column while the rest scrolls, edits stage, value, probability, close date and any custom field inline on a double click, and runs bulk stage, type and archive actions across a selection.
Two engineering details keep it calm at scale. Everything a row needs arrives in a fixed number of queries rather than one per deal, so hundreds of rows cost what ten do. And a bulk action runs every identifier through exactly the same per-deal permission check as a single edit, then reports partial success honestly: twenty updated, three skipped, rather than a cheerful message that hides the three.
The forecast groups expected close dates by month or quarter and shows weighted value against total value, filterable by deal type, stage and ownership. The honest part is at the bottom of the page. Deals with no expected close date are listed separately, by name, instead of being silently excluded. A forecast that quietly drops the deals it cannot place is how a pipeline appears to shrink for no reason.
08 · A health score that shows its working
Here is the part that justifies building a CRM on top of a data room rather than beside one. Each buyer-side reader in each attached room is scored on five measured factors. The formula records its raw inputs and its weights alongside every score it computes, so the console can report arithmetic rather than opinion.
| Factor | What is measured |
|---|---|
| Recency | How long since this reader last opened the room, decaying over days rather than switching off at a threshold. |
| Frequency | Sessions opened in the last fourteen days. |
| Depth | Pages viewed in the last fourteen days, and the reading time that implies. |
| Breadth | How much of the document set has been opened, weighting the term sheet more heavily than the rest. |
| Progression | Whether the NDA is signed, how many questions have been asked, and whether full clearance was reached. |
Open a deal and the panel shows, for every reader, a line per factor: what was measured in plain words, and beside it the points that factor contributed out of the points available to it. "Last opened 3 days ago" and "7 of 12 documents opened, including the term sheet" are sentences a person can argue with, which is the entire point. A test asserts that no factor can ever contribute more than its weight, so the explanation always adds up to the number it explains.
When a deal has no data room attached, the panel says exactly that in words. It does not show a zero. Nothing has been measured, and reporting nought out of a hundred would read as a failing counterparty rather than an absent measurement.
09 · Suggestions that carry their evidence
There is no model in this path, and that is a design decision rather than a limitation. Nine detectors run over data the platform already holds, and every one produces a suggestion carrying the evidence that produced it and the action that answers it.
A deal that has gone quiet. Reader engagement cooling or cold. A close date approaching, or passed. Overdue follow-ups. No next step recorded. No data room attached. Invited readers who have not signed the NDA past the chase window. Reader questions nobody has answered. Consistency findings nobody has triaged.
On the dashboard each one reads like this: a severity, then the finding, then the evidence line, then the action. "Two invited readers in Project Vellum have not signed the NDA. Two invitations outstanding, oldest sent 19 days ago, threshold is 7 days. Open the room." If the suggestion is wrong, you can see immediately which fact was wrong.
Three properties make it trustworthy rather than decorative. The thresholds are published alongside the answers, so you can disagree with the rule and not merely the result. The room signals count NDAs, questions and findings and never open a page, which is asserted by a test that plants question text and checks it appears nowhere in any signal. And signals go through the same access check as everything else, so a suggestion can never describe a deal the reader could not already open.
The same rules feed the flags on the board, computed once on the server so a deal cannot look calm on the card and at risk in the table. Flags carry their measurement in the label, are capped at three so the board stays scannable, and a closed deal raises none at all.
10 · The limits, stated plainly
An article that lists only capabilities is a brochure. These are the honest boundaries of what shipped.
- Health exists only where a data room is attached. A deal you are running over email has no engagement signal, and the product says so rather than inventing one.
- Thresholds are global today. Quiet after fourteen days is the same number for every organisation and every stage, though silence in diligence plainly means something different from silence at prospect. Making them configurable per organisation and per stage is the next refinement, and it is not done.
- Sweeps run hourly. A reminder lands within the hour of its time, not to the minute. That is right for deal follow-ups and would be wrong for anything time critical.
- Nothing contacts your counterparty automatically. The engine creates tasks, escalates and puts an alert in front of a person, and the person decides what to send. The one exception is the signing chase on documents you deliberately sent for signature, which is the expected behaviour of any signing product.
- Your own Slack app costs you ten minutes. Slack ties an app to whoever owns it. Anybody promising your logo on their app without that step is describing their app in your workspace, not your app.
- Chat platforms sit outside the perimeter. Messages are content-free by construction, but the chat itself lives on Telegram's or Slack's infrastructure under their security model. Treat both as signal channels, never as a place to discuss what a document says.
- Assignment transfers ownership. Handing a deal to a colleague is a real transfer, restricted to people in your organisation and separately audited. The previous owner keeps access only if the deal is shared back to them.
- Archiving is a flag, not an outcome. An archived deal keeps its open, won or lost status so that win rate, conversion and forecast stay honest. Archiving is not a quiet way to lose a defeat.
11 · Questions people ask
Is Meridian CRM a separate product?
No. It is the deal desk built into every KXCO Meridian account, alongside document signing and data rooms, at meridian.kxco.ai. There is nothing extra to buy to use it, and a new account starts completely empty.
What does the health score actually measure?
Reading behaviour inside the data rooms attached to a deal. Each buyer-side reader is scored on five measured factors: how recently they opened the room, how often they visited in the last fortnight, how much they read, how much of the document set they covered, and how far they progressed through the NDA and their questions. The deal score averages those readers, and the console shows each factor with the points it contributed.
Can a colleague see my deals if I add them to my organisation?
No. A seat grants membership and nothing else. Even an organisation admin sees no deal, room or document by virtue of being a member. Access to a deal is granted deal by deal through sharing, and there is a test that fails the moment that stops being true.
Whose bot sends the alerts?
Your own, if you have connected one. An organisation creates a Telegram bot with BotFather and pastes the token, which is encrypted before it is stored and never shown again. Until you connect your own bot, alerts come from the platform bot, and the setup page says so rather than leaving you to guess.
Can I model different kinds of deals?
Yes. Custom fields come in nine types and belong to your organisation. Deal types carry their own stages and their own fields, so an investment and a partnership need not look alike, and a field pinned to one type never appears on another.
Does the CRM ever show document content?
No. Every alert, timeline entry and webhook is built from the platform's event record, which never contains document text. The room signals count NDAs, questions and findings; they never open a page. A message can name a deal, a stage or a count, and can never carry a clause.
Is a forecast in Meridian a prediction?
No. Weighted value is value multiplied by probability, and probability is your judgement. The forecast makes your assumptions visible and adds them up correctly. Deals with no expected close date are listed separately rather than quietly dropped.
Meridian CRM runs inside KXCO Meridian at meridian.kxco.ai, alongside document signing and data rooms, with the data rooms user guide at kxco.ai/developers/blog/meridian-data-rooms-guide and the product overview at kxco.ai/meridian. KXCO Meridian is operated by Knightsbridge Financial Ltd, trading as KXCO. KXCO is a software company and is not a party to any transaction conducted through the platform, nor a law firm, and nothing here is legal, financial or investment advice.