Plugs into what you already run, with nothing in between you cannot audit.

Records come in through connectors your firm can read, from databases, web APIs, files and spreadsheets, and are checked against official registers. They go out through a published API, a change feed, webhooks and scheduled pushes, each saying who is asking and where every value came from. AI agents ask the same way, through the same checks.

A connector is a settings file, and nothing is written until a rehearsal has run.

A connector written as software becomes software your firm has to maintain. A connector written as a settings file is a document your firm can read, compare and approve. An implementation consultant, not a platform engineer, builds one in days.

  1. Describe

    The settings file: which system, which fields, how to tidy each one, and what it is.

  2. Validate

    Check it makes sense. Every field is either mapped or deliberately ignored; nothing is silently dropped.

  3. Rehearse

    Run it against real data and write nothing. It shows what would change. A connector that has never been rehearsed cannot write.

  4. Run

    In pieces, resumable. Retries, failures queued, and a record of the run kept.

What a settings file can point at

Databases

SQL Server, PostgreSQL and Oracle, read as a table or a query. Always a replica or a nightly restored copy, never the live production database, because that is the access a practice management vendor will actually grant.

Web APIs

REST endpoints, signing in with basic credentials, OAuth 2.0 or an API key. The shipped CRM connector reads one, picking up from the last change it saw.

Files

A file share or an SFTP drop. The same settings file, the same rehearsal, the same record of the run.

Spreadsheets

A guided import: upload, detect, map, check, preview, commit. Mapping templates are reused. The file's checksum is shown, so the commit provably reads what was previewed. A sheet can go out to Excel and come back with each row keyed.

Supplied for every connector, so nobody writes it twice

Only what changed

An incremental load reads from a watermark with an overlap window. The watermark advances from the data rather than the clock, so a source with a slow clock loses nothing. Rows whose content has not changed are recognised and skipped.

Loaded once, whatever happens

A record that arrives twice is stored once. That is enforced by a database constraint, not by the connector remembering to check.

Drift is caught, not absorbed

If a source column disappears or changes type, the load is quarantined and nothing is applied. A half-applied load is the one no re-run can reproduce.

Rejects come with reasons

A record that cannot be conformed is listed with what was wrong with it. The rehearsal reports coverage three ways. A wrong mapping, a required field that is empty in reality, and a column nobody looked at each show up as themselves.

Secrets never sit in the file

A credential is a reference to the firm's vault. A password typed into a settings file is refused before it can reach version control or the audit trail.

Tidy-ups are named, not coded

Fourteen named transformations: trim, upper, dates to ISO, digits only and their kind. An escape hatch into code exists for what they cannot express, and every use is flagged for review and counted.

Northgate Wells LLP
Home Data management Bulk import
as at now
Priya Raman Data steward
Work queues
Match review1,274
Data quality exceptions17
Schema drift quarantine1
Data
Search
Bulk import
Reference data
Taxonomy
Hierarchies
Insight
Dashboards
Administration
Bulk import
1 Upload
2 Map columns
3 Validate
4 Commit
northgate-client-matter-extract-2026-09.csv 18,412 rows, 11 columns, UTF-8, delimiter ,
Checksum 9f2c1ae4b77d0351 The commit reads these exact bytes. Compare it if the file has been open elsewhere.
Valid rows 18,181
Rows with errors 231
Rows with warnings 167
Would be written 18,181
Every row was checked, not a sample.
File row
Code
What was wrong
214
LON000914
registration_number: expected 8 characters, got 7
386
—
client_identifier is required and was empty
512
MAN000233
country: “United Kingdom” is not a mapped code — map it in reference data
903
LON001204
client_since: “31/02/2019” is not a date
1,140
JHB000118
owning_org_unit “Cape Town — Tax” matches no unit in this firm
2,077
LON000412
duplicate file row: ClientID LON000412 appears twice
225 more, each with its own reason
Commit 18,181 rows Download the error report
mapping template: elite3e client extract v3
Bulk import step 3 of 4
northgate-client-matter-extract-2026-09.csv 18,412 rows, 11 columns, UTF-8 Checksum 9f2c1ae4b77d0351
Valid 18,181
Errors 231
Warnings 167
Every row was checked, not a sample.
Rejects, with reasons
row 214 LON000914
registration_number: expected 8 characters, got 7
row 386 —
client_identifier is required and was empty
row 512 MAN000233
country: “United Kingdom” is not a mapped code
row 903 LON001204
client_since: “31/02/2019” is not a date

Nothing is written until the commit, and the commit reads the bytes this checksum names.

The guided import at its check step, on the demonstration firm. Every row is checked, not a sample. Each rejected row is listed with what was wrong with it, and the checksum names the bytes the commit will read, so the run that writes is provably the run that was previewed.

Working examples included

Elite 3E comes as a working connector: five streams over the client, matter, timekeeper and organisational unit tables. The client table is read twice, because the client relationship and the organisation behind it are different things. A generic CRM connector shows the same shape over a web API.

An agent can draft one

A separate set of twelve tools lets an AI assistant explore a source, profile its columns by pattern rather than value, and draft the settings file. It can rehearse the file and run the contract tests. That assistant is kept apart from mastered data by the code's own import structure, so a connector-authoring agent can never read a client record.

Loads that survive a bad night

Work is done in pieces, with save points and retries. A load that fails at three in the morning picks up where it stopped. Anything it could not process is queued for a person, and the whole run can be replayed.

"Verified" means a date and a source, not a tick in a box.

Every check against Companies House, CIPC or OpenCorporates is kept on file: what was checked, against which authority, when, and what came back. Re-verification is scheduled, and a registration number that stopped matching last month becomes a data quality problem to deal with, not a value that quietly goes stale.

Companies House

United Kingdom. Legal names, registration numbers and registered offices, with the date each was confirmed.

CIPC

South Africa. The Companies and Intellectual Property Commission register, checked the same way.

OpenCorporates

Multi-jurisdiction. Used where a national register has no usable interface, and recorded as the source it is.

Northgate Wells LLP
Home Legal operations Registry verification
as at now
Priya Raman Data steward
Work queues
Match review1,274
Data quality exceptions17
Data
Search
Reference data
Hierarchies
Legal operations
Party register
Registry verification4
Retention
Due for re-verification
4 of 24
Ashcombe Logistics Limited Re-verify after 4 Aug 2026
Kelsall Trading B.V. Re-verify after 4 Aug 2026
Saltire Technologies A/S Re-verify after 11 Aug 2026
Eastgate Partners Pty Ltd Re-verify after 18 Aug 2026
Wexford Pharma Pte Ltd Re-verify after 1 Sep 2026
Ashcombe Logistics Limited
Verify now
Differs from the registry companies_house · 03 Sep 2026, 02:41 Re-verify after 30 Jun 2027
Registered name differs from the name the firm bills under.
What came back
Authority Companies House · GB
Registration number 04471902
Company status Active
Incorporated 14 Jun 2002
Registered office 1 Ropemaker Street, London EC2Y 9AW
Retrieved 03 Sep 2026, 02:41
These are proposals. Nothing is written to the record until a steward decides.
Attribute
Ours
Registry
legal_name
Ashcombe Logistics Limited
Ashcombe Logistics (Holdings) Limited
registered_address
14 Bishopsgate, London EC2N 4AY
1 Ropemaker Street, London EC2Y 9AW
previous_names
—
Ashcombe Logistics Limited
Accept as a proposal Reject
confidence 0.42 · 24 checks
Registry verification
Ashcombe Logistics Limited
Differs from the registry companies_house · 03 Sep 2026
Re-verify after 30 Jun 2027
These are proposals. Nothing is written to the record until a steward decides.
What the registry says
legal_name
Ours Ashcombe Logistics Limited
Registry Ashcombe Logistics (Holdings) Limited
registered_address
Ours 14 Bishopsgate, London EC2N 4AY
Registry 1 Ropemaker Street, London EC2Y 9AW
previous_names
Ours —
Registry Ashcombe Logistics Limited

Companies House · GB · 04471902 · active · retrieved 03 Sep 2026, 02:41

A Companies House check on the demonstration firm. The badge carries the authority that answered and the moment it answered, what came back is kept on file, and where the register disagrees the difference waits as a proposal for a person to decide.

A register's answer arrives as a proposal. If the register disagrees with the record, the difference goes to a person to decide. Nothing is written on the register's say-so.

Six ways in, and each says who is asking.

Looking up "which client is this, really?" is the busiest request, and the one that makes Datum useful to every other system in the firm. Nineteen times in twenty it answers in under 200 ms, measured on our test set.

RouteWhat it answers
GET /v1/xref/{system}/{key}Turn one system's reference into the master one
GET /v1/records/{master_id}The full record, as at any date you choose
GET /v1/searchSearch, with permissions applied as it runs
GET /v1/changesWhat has changed, for systems keeping in step
GET /v1/extracts/{entity}Bulk extracts, saying which columns were withheld
GET /v1/schemaThe data model, filtered to what you may see

Looking up a client: the request

GET /v1/xref/elite3e/LON000412
Authorization: Bearer ••••••

Response

{
  "master_id": "01936f2a-…",
  "entity": "party_organisation",
  "attributes": {
    "legal_name": "Pemberton Holdings Ltd",
    "country": "GB"
  },
  "provenance": {
    "legal_name": {
      "source": "elite3e", "record": "LON000412",
      "rule": "highest_trust", "pinned": false,
      "selected_at": "2026-08-24T02:14:07+00:00"
    }
  },
  "as_at": "2026-08-24T09:00:00+00:00",
  "contract_version": "1.0"
}

Saying where a value came from is not optional

Every field, on every response. Without it, the system reading has no way to judge how far to trust a value. Datum refuses to send a response that is missing it.

"Not found" does not mean it is not there

It means it is not available to you. A matter that does not exist and a matter behind an ethical wall look exactly the same, because telling them apart would give the game away.

Totals are the totals you may see

Every list carries suppressed and complete. If complete is false, that total is not the firm's total, and no system should present it as one.

Three questions about time

A record can be read three ways: as at the moment permissions are judged, as at when a fact was true in the world, or as at when the firm believed it. Who was the client in March, and what did we know in March, are different questions. They are the pair a professional indemnity claim needs years later. A store that cannot answer one says so rather than handing back today's values.

Merges never strand a reader

Identifiers are never reused. After a merge, asking for the retired one returns the surviving record with a note naming what you asked for. A system holding an old reference is told where to point it.

Errors are structured and stable

Every failure is a machine-readable problem report with a code that does not change between versions. "Erased" is a distinct answer from "never existed", because a system holding a copy needs to be told to erase its own.

Contracts carry their dates

Ten contracts are published in all, from the cross-reference lookup and the change feed to the write path with change requests, jobs, lineage and notifications. A consuming system reads the list and sees each one's introduction, deprecation and sunset dates, rather than discovering a change when something breaks.

One permission never implies another. An administrative permission does not grant a read permission. Every system that connects gets its own credentials, including the AI integration. A role can also withhold particular fields, and a withheld field is named in the response, never silently left blank.

Other systems keep in step without a copy of the wall.

Four ways to keep a downstream system current, from a feed it reads to a push Datum makes. Every one is screened for the identity that receives it, at the moment it receives it.

The change feed

A numbered sequence of everything that changed, with no gaps and one order for the whole firm. Delivery is at least once, with a key to drop duplicates on. A cursor that has expired is refused with a pointer to re-baseline from a bulk extract, never skipped over quietly. Thirty days are kept by default.

Permissions are applied when an event is read, not when it was written. A wall raised this morning hides an event from last week for the people it screens. The same event is visible to one consumer and not another, and that is correct.

Webhooks

Datum calls your endpoint when something you subscribed to changes. A subscription names the identity it delivers as and receives only what that identity may see, because a delivery has no person behind it to check against. Endpoints must be HTTPS, subscriptions filter by event and by entity, and every delivery attempt is recorded.

Scheduled push

For a system that cannot reach in, and a firm's own data centre is exactly that, Datum initiates the connection outbound on the firm's schedule. The firm can see what left and can stop it leaving without the other side's cooperation. Rows whose content has not changed are not sent again. A batch that fails marks the run partial and is re-sent next cycle, and nothing is sent at all without a credential.

Where the receiving system already holds a different value, the difference is recorded and shown, not overwritten. The resolution belongs to a person.

Bulk extract and search

An extract is built by the same permission check as every other read; there is no separate export query where the wall could be forgotten. It reports how many rows and which columns were withheld. Search, over legal-aware analysers, applies permissions inside the query, so facets and counts are over what the caller may see. It is fed from the same change stream as everything else.

Every value says where it came from, and every source column says what it feeds.

Provenance is on every response. Lineage is recorded on every run, in the open OpenLineage format, and published through the API and the stewardship screens. With the model, the code lists and the taxonomy, it answers what a data team asks a catalogue: what exists, what it means, who may see it, and where it came from.

EXTRACT STANDARDISE · CONFORM SURVIVE · PUBLISH HBM.ClientClientName · Elite 3E Standardiseorganisation_name party_organisationlegal_name · golden record Every readerAPI · feed · webhook · agent IMPACT · WHICH GOLDEN FIELDS DOES THIS COLUMN FEED? PROVENANCE, ON THE RESPONSE elite3e · LON000412 · highest_trust ONE CHAIN PER FIELD PER RUN. THE JOIN TO THE GOLDEN RECORD ANSWERS WHICH SOURCE RECORD FED THIS VALUE.

Provenance, on every field

Which source, which record, which rule chose it, whether a person pinned it, and when. Four kinds of origin are kept apart: a source system, an external register, a steward's assertion, and an inference from matching. They are never presented as the same kind of claim.

Lineage, on every run

Each of the six stages (extract, standardise, conform, match, survive, publish) records an event in the OpenLineage format, the open standard lineage tools read. The stages that produce values also record which source column fed which golden field. Recording is not optional and cannot be switched off, because lineage that is off by default is off in production.

The API answers "where did this value come from?" for any field of any record, permissions applied, as a chain a person can read: source column, transformation, golden field. The stewardship application shows the same chain beside the value. A chain that is incomplete is reported as a connector defect, not shown as "unknown".

Impact, before a change

The same record answers the reverse question: which golden fields does this source column feed? It is the question a data lead has before a practice management upgrade retires a column, and without it that change is made blind.

The model, as a document

The data model is published as a JSON Schema, with every field annotated: how sensitive it is, its role in matching, whether it is derived, and its SALI classification. Each entity says whether it is mastered and what its natural key is, the two things a data architect looks for first. It is filtered to what the caller may read, and names what was withheld. The stewardship application's own model diagram is drawn from it.

Code lists and the taxonomy

Reference data is a catalogue of code lists with a mapping from each source system's codes onto the firm's canonical ones. Unmapped codes queue for a person, every value shows where it is used, and a code still in use cannot be retired. The SALI Legal Matter Standard Specification is the taxonomy spine, with the firm's own extensions in their own namespace and crosswalks to what the firm already uses.

Bring your own catalogue

Datum ships no separate catalogue product. A firm running its own catalogue or lineage store points it at these endpoints and forwards the OpenLineage events unchanged; Marquez is the one they are shaped for. No third-party component's own screens are ever shown to a firm's users, because none of them knows what an ethical wall is.

Seven questions an agent can ask, and one thing it can propose.

An AI agent asks through the Model Context Protocol (MCP), the open standard AI tools use to call other systems. It reads with its own identity, through the same checks as a person, and gets the same record with the same source attached. The only write is a proposal into the review queue. Any agent that speaks the protocol can be pointed at it; Trovato is the first.

ToolThe question it answers
get_entityLook up a record
search_entitiesSearch, with permissions applied as it runs
resolve_entityWhich client is this, really?
classifyClassify this piece of work
get_matter_contextEverything about a matter, as at a date
get_corporate_groupThe corporate group a company belongs to
propose_contributionPropose something new, into the review queue
Illustrative exchangeNorthgate Wells LLP · the demonstration firm
Request — from a Trovato agent
POST /mcp
Authorization: Bearer ••••••  (trovato-agent · mdm:read)
{
  "jsonrpc": "2.0", "id": 41,
  "method": "tools/call",
  "params": {
    "name": "get_matter_context",
    "arguments": {
      "matter_number": "24-0417",
      "as_at": "2026-03-14"
    }
  }
}
Response — as the firm held it on that day
{
  "result": {
    "matter_number":  "24-0417",
    "client":         "Pemberton Holdings Limited",
    "jurisdiction":   "England and Wales",
    "classification": "Corporate — Mergers & acquisitions",
    "restricted":     false,
    "parties": [
      { "name": "Pemberton Holdings Limited", "role": "client" },
      { "name": "Cavendish Technologies Ltd",  "role": "counterparty" }
    ],
    "personnel": [
      { "name": "A. Wainwright", "role": "responsible partner",
        "from": "2024-02-12", "to": null }
    ],
    "provenance": {
      "client":       { "source": "companies_house", "selected_at": "2026-08-14T02:14:07Z" },
      "jurisdiction": { "source": "elite3e",         "selected_at": "2026-08-24T02:14:07Z" }
    }
  }
}

A matter behind a wall and a matter that does not exist get the same reply, byte for byte. The transport cannot tell the agent the difference either.

{"result":{"isError":true,"content":[{"type":"text","text":"not found"}]}}
Datumpushes on the firm's schedule Directory identitylist of matters · walled ones flagged Detail identitymatter content · screened by every wall ETHICAL WALL 24-0417 · restricted not found Trovatosees the name only Trovatono walled content, ever NOTHING THAT COULD BE READ AS A CLEARANCE EVER LEAVES. A NAME CROSSES; CONTENT NEVER DOES.

Live in Trovato.

trovato.ai · legal operations platform · lawyers run matters with supervised AI agents

Intake, already filled

When a lawyer opens a matter in Trovato, the client, the parties and the governing jurisdiction come from Datum. Nobody retypes them, so nothing is mistyped. Retyping is where wrong data enters.

Agents ask back

Trovato's Matter Agents ask Datum for matter context as they work, with their own credentials. Every field comes back with its source, which is what Trovato's Citation Firewall needs before an answer can ship.

Findings return as proposals

What an agent learns from a document goes into Datum's review queue as a suggestion. A reviewer decides. The record never changes on an agent's say-so.

Datum pushes. Trovato never reaches into your network. The firm owns the schedule, can see what left, and can stop it leaving without asking anyone.

Two identities, screened differently. A directory identity publishes the list of matters, with walled ones marked restricted. A detail identity publishes matter content and is screened by every wall. A walled matter's name crosses; its content never does. Nothing that could be read as a clearance ever leaves.

Switch it off and the route does not exist.

Not disabled, absent. With the integration off there is no agent route in the software at all. The whole platform builds and passes every test that way, and proving it is one of the eight checks that block a release.

Runs wherever your firm needs it to run.

In your own data centre, or as a managed single instance. Neither is a lesser product.

In your own data centre, without a lesser product

The typefaces are served by Datum itself, and no screen fetches anything from an outside company. A machine inside your network has no route out, and the product does not quietly fall back to Arial.

A database doing real work

PostgreSQL 16, ninety-one tables. The rules that stop two conflicting versions of the same thing existing at once are enforced by the database itself, not by application code a simultaneous write can slip past.

Joins, not rebuilds

Scheduling, loading, transforming, search, sign-in, permissions, lineage, events, graph traversal and matching at scale are each a named seam with a working default behind it. Datum runs without any of them and gains from each your technology team already operates.

  • Airflow
  • dlt
  • dbt
  • OpenSearch
  • Keycloak
  • OpenFGA
  • Marquez
  • NATS
  • Apache AGE
  • Splink

Two AI connections, deliberately kept apart

One for the people building Datum and one for the running product, so a convenience for developers can never reach live data. A firm that wants no AI model near its client data runs Datum without one and loses nothing else.

Bring your systems to the walkthrough.

Tell us your practice management system in the form and we will have the right connector open. We will show the settings file, the rehearsal run, the feed another system reads, and the chain from a source column to a golden value.

Questions before booking? Use the contact form.