The door out has to work as well as the door in. What commvita hands over, in which standard, what it doesn’t, and how the audit survives the move.
I want customers who stay because they want to. That means the door out has to work as well as the door in, and it has to work without me. This page says exactly what commvita hands over, in which standard, and what it doesn’t hand over. Where a screen is a demonstration rather than a wired capability, it says so.
The clinical record leaves as FHIR R4. A capability statement describes what the server holds, and the resources are readable individually or as everything held about one patient in a single bundle: patient, conditions, encounters, observations, medication and care plans.
Everything held about one person in one call, and the same content the person can pull themselves from the portal. Categories with no records are listed by name, so “nothing recorded” is told apart from “nothing to report”.
Populated common data model tables for a study cohort, de-identified, with a data quality summary and a ledger entry. This is the analytic export and it’s wired end to end.
Most operational tables in the platform download as CSV from the screen they sit on. Useful, unglamorous, and the thing people reach for first.
That console is a demonstrated surface. The bulk asynchronous export it describes, NDJSON output, backend-services authentication, polling and file retention, is the shape of the capability instead of a running job queue: the jobs and their file counts are seeded content held in the page. The live path today is the FHIR R4 read of a patient or a resource type, and the cohort export in the next section. Saying that plainly is what this document is for.
Pick a study cohort and the platform runs a real transformation to OMOP common data model version 5.4, returns a data quality summary against the tables it just built, and offers each table as CSV or Parquet. The screenshot below was produced by pressing the button.
Three things in that picture matter more than the row counts. The result says REVIEW instead of PASS, because 62.4 per cent of source values mapped to a standard concept and the platform won’t present that as clean. Every table is offered in both an open text format and a columnar one. And the extract is de-identified before it’s written: a surrogate person identifier, a per-person date shift, birth month and day suppressed, small counts suppressed and a cohort under ten people blocked outright. The de-identification is described in more depth in the OMOP explainer.
An export that leaves no trace isn’t a governed export. Every extract writes a ledger row: an identifier, who took it, the anonymisation tier, the row count, the disclosure decision, a file hash, the destination and the sharing agreement it was taken under.
The blocked row is the useful one. Seven people is under the disclosure threshold, so no file was produced and no hash exists, and the refusal is on the record next to the releases. A leaked file can be matched back to its row by hash. The ledger itself is read-only and gated to governance roles, because a list of what has left the platform and where it went is disclosive in its own right.
Sign-ins, role changes and other security events are appended with each row hashed over the one before it, and the chain is verified when the log is read. If a historic row were altered, the read says so.
The export catalogue resolves what a given person may request instead of listing everything to everyone, and refusals carry their reason. It’s an interface capability with no screen of its own today.
A per-patient bundle carries the national identifier and local identifiers, which is what makes it loadable into a receiving system. The cohort extract doesn’t: it carries surrogate identifiers and shifted dates, so it can’t be re-linked from the file alone.
The honest half of a portability promise is the list of things it doesn’t cover. All of these are true of this build.
What that adds up to for a buyer: the clinical record and the analytic dataset leave in published standards with an audit trail, and the operational and governance surfaces leave as tables. If a receiving system needs more than that, it’s an integration project, and it should be priced as one not assumed.
Coming in is a job with a shape: agree the source systems, map the fields, run it in dry-run, look at what failed, then run it for real and keep the ability to reverse it. commvita holds that job as a record instead of as a project plan.
A migration job carries a name, the source system, the data types in scope and whether it’s a dry run. Field mappings are held per source system. Running a job records what it did, including failed records and validation issues, and a completed job can be rolled back to a recorded state. The job register and its statistics are wired; the transfer itself isn’t performed by this build, so treat the record counts on a run as the shape of the reporting and not as data that moved.
Feeds are the other half. Message routes, a queue, a dead-letter queue with replay, and a mapper from HL7 v2 to FHIR are present as control surfaces with seeded content, as is the batch adapter registry above. They show how a deployment would be wired and what an operator would see. No live message engine is running behind them in this build. The FHIR R4 interface described in section two is the live route in as well as out.
The Flow Edition is self-hosted at £1 per instance. The deployment runs on the buyer’s own infrastructure, so the data never leaves it, and leaving is a matter of switching off a service you already run instead of asking somebody to release your record.
That edition exists for a specific reason, and the argument for it’s set out in the exit and continuity explainer, which deals with what a continuity programme looks like when a national platform is withdrawn. This document is the narrower question: what physically comes out, and in what shape.
| Capability | Route | Model / API | Status |
|---|---|---|---|
| FHIR R4 capability statement and resource reads | API only | /fhir/r4/metadata · Patient, Condition, Encounter, Observation, MedicationStatement, CarePlan | ● Live |
| Everything held about one patient, as one bundle | API only | /fhir/r4/Patient/{id}/$everything | ● Live |
| The person’s own record, downloaded by them | /portal | API /portal/fhir-export · names empty categories · written to the export record | ● Live |
| OMOP CDM v5.4 extract, CSV and Parquet | /omop-cdm · /clinical-studies | API /studies/{id}/cohorts/{id}/omop-cdm · de-identified · disclosure gated · DQD | ● Live |
| Extract ledger | /clinical-studies | API /studies/extracts · hash, destination, sharing agreement, blocks under n=10 | ● Live |
| Export catalogue resolved per caller | API only | /export/catalogue · /export/requests · no screen | ● Live |
| Tamper-evident account log | API only | /auth/login-audit · hash chained, verified on read | ● Live |
| Migration jobs: dry run, run, rollback, statistics | /nhs-integrations | API /migration/jobs · /migration/field-mapping/{system}; the run doesn’t move data in this build | ● Live |
| Bulk asynchronous export console (NDJSON) | /fhir-bulk | Seeded job queue and history held in the page | ☉ Demonstrated |
| Message routes, queue, dead-letter replay, HL7 to FHIR mapper | /hl7-engine · /transformation-studio | Fixed responses behind /hl7/; no live engine | ☉ Demonstrated |
| Batch file adapters (SFTP, AS2, MESH) | /batch-adapters | Seeded registry and processing log | ☉ Demonstrated |