Skip to main content

Single-patient EHI export format

This page describes the file a practice receives when it exports one client's electronic health information (EHI) from MedSuite EMR. It is published openly so that anyone who is handed an export can read it, with no account, fee or agreement. It supports the ONC certification criterion § 170.315(b)(10)(i), single-patient electronic health information export, and its requirement that the export format be publicly documented.

Every export carries a link to this page in its README.txt.

What the export is​

One ZIP file holding everything the system stores about one client:

  • one CSV file for every table in the client's record, named for the table;
  • the client's stored documents and images, filed under assets/;
  • dictionary.json, which describes every file;
  • README.txt, a short orientation with the client's name, when the file was made and the link to this page.

The export is for one client at a time. It never contains another client's rows.

Who can run it, and how​

An administrator who has been given the export permission opens the client's chart, chooses Export EHI, and queues the export, or picks EHI Export (single client) on the Reports page and chooses the client. The export runs in the background. When it is ready it appears under Completed reports, and the person who may open it chooses Download.

A few rules apply to every export:

  • The person who asks for it, and the person who downloads it, must be allowed to open that client's chart. A user who has been restricted from the chart cannot export it or download it, even if someone else queued it.
  • Every download is recorded in the audit log before the file is sent.
  • The file name is neutral: it names the kind of report and the day it was made, never the client.

The files​

One CSV per table​

The first row of every CSV is a header with the column names. Every cell is written in double quotes, with a double quote inside a cell written as two. Rows are separated by a carriage return and a line feed. Text is UTF-8.

A file that has a header and no other row means the system holds nothing for this client in that table. This is normal: a client touches only some of the tables.

What is included. The export finds the tables itself each time it runs, so a table added to the system later is picked up without a change to this page. A table is in the export when its rows belong to the client in one of these ways:

  1. the row carries the client's identifier;
  2. the row has no client of its own but names a billing case or a charge of the client, as an insurance response matched to a case but to no named client does;
  3. the row names the client in a link that makes it the client's own record, such as an outside referral that created the client's chart;
  4. the row belongs to a row that is the client's, such as the answers on a clinical note, the lines of a charge, or the diagnoses of an order. This is followed from parent to child as far as it goes.

Deleted and hidden rows are included. Data that was deleted from the chart is still the client's health information, so a row that was marked deleted or hidden is exported with its deleted and hidden columns filled in. The export never filters on them.

What is not included. The dictionary lists every table that was left out and why. They are limited to:

  • records that belong to other clients and only name this client: a relationship entered on another client's chart that names this client as the related person, and merged duplicate charts;
  • files that cover many clients and cannot be limited to one: remittance documents, clearinghouse acknowledgements and responses for a whole batch, and eligibility request files;
  • import staging files that carry many clients;
  • stored report results and the list of clients a generated report contains, which can be produced again from the exported tables;
  • one credential column, which holds the secret used to sign in to a records-release recipient's system. It is not health information, and the dictionary names it.

Values​

Values are the stored values as text, with these conventions:

Kind of valueHow it appears
Encrypted columnsDecrypted. The system keeps names, notes, narrative answers, phone numbers, identifiers and similar columns encrypted. The export decrypts every one into a plain-text column named like the stored column without the word encrypted. The dictionary lists, for each column, the stored column it came from.
TimestampsThe practice's local time, as YYYY-MM-DD HH:MM:SS. The practice's time zone is named in the dictionary (time_zone) and in the README.
DatesThe stored date as YYYY-MM-DD, never converted.
Binary valuesBase64, with the prefix base64:.
Stored filesNot in the CSV. The column is named <name>_asset_path and holds the path of the file inside the ZIP, or is empty when the row has no file.
Yes/no, numbers, identifiersWritten as text: true or false, the number as stored, the identifier as stored.
An empty valueAn empty cell. The export does not distinguish a missing value from an empty text.

Hashes are not exported. A column whose name ends in _hash is derived from another column (a search key, an integrity digest or a digest of a token). It is not a stored fact, so it is left out. The dictionary lists every column that was omitted.

A leading quote protects against spreadsheet formulas. A value that starts with =, +, - or @, or with a tab or a carriage return, is written with one single quote in front, so that a spreadsheet shows the text instead of running it as a formula. This includes negative numbers: -5.00 is written '-5.00. To get the stored value, remove that one leading quote. A value that does not start with one of those characters is written exactly as stored.

Documents under assets/​

A stored document or image is filed at

assets/<table>/<row id>/<name>.<extension>

where <table> is the table the file belongs to, <row id> is the value of the row's identifier in that table's CSV, and <name> names the column the file was stored in. The extension follows the file's stored type (pdf, png, jpg, and so on, or bin when the type is not recorded). The name is neutral: it is never the name the file was uploaded under.

Each file is checked against its stored SHA-256 checksum when the export is built. If a file no longer matches its checksum, the export fails rather than shipping a file that may be damaged. For a file that was stored without a checksum, the dictionary records that no check was possible.

The assets directory is absent when the client has no documents. The dictionary states the count either way.

dictionary.json​

A JSON document that describes the rest of the archive. Read it first.

FieldMeaning
exportspec (the criterion), patient_id, generated_at and time_zone, format_documentation (the link to this page), and the totals file_count, row_count and asset_count.
notesThe conventions on this page, in short, for a reader who has only the archive.
filesOne entry per CSV: file, source, table, a description of the table, link (how its rows belong to the client), row_count, and its columns. Each column has its name, its type, the stored_column it was read from, and the rendering (how the value is written).
assetsOne entry per table and column that holds files: how many files, their total bytes, how many were checked against a stored checksum and how many had none.
omitted_columnsEach column that was left out of a CSV, with the reason.
excludedEach table that was left out, with the reason.
not_followed_linksThe links that were deliberately not followed, with the reason.
failuresAlways empty in a finished export. A table that cannot be read fails the whole export, so a finished archive is never silently incomplete.

README.txt​

The client's name and identifier, the date and time the file was made in the practice's time zone, the link to this page, and a short guide to the files.

How the export checks itself​

Before an export is marked ready, it is checked against itself:

  • every table in the client's record has a CSV file;
  • every file in the archive is described in the dictionary;
  • for every table, the row count in the dictionary equals the number of rows written, the number of rows read back out of the finished CSV, and the number of the client's rows counted in the database at the same moment;
  • the number of documents in the archive equals the count in the dictionary.

If any of these disagree, the export fails and no file is offered. A failed export shows a short reason on the Reports page, and can be queued again.

The export reads the client's record in one consistent snapshot, so the files agree with one another even if the chart is edited while the export is running.

Not yet included​

A FHIR bundle of the clinical record is not part of this export.