Legal
Privacy Policy
Last updated: October 11, 2026
This policy describes the personal information OpenChart LLC, a Virginia limited liability company doing business as open-chart (“we,” “us,” “our”), collects through the Service, how we use it, who we share it with, and the choices you have. Please read it together with our Terms of Service and Security disclosure. If a conflict exists between this policy and the Security disclosure, the Security disclosure controls for matters of cryptographic architecture.
1. Plain-English summary
- Your password and master encryption key never reach our servers. We could not decrypt your source documents even if we tried.
- We cannot read the content of your health records. Lab values and their names, conditions, medications, allergies, immunizations, recommendations, per-document digests, chart-review insights, and the health-bearing parts of your demographic profile are all encrypted under your key before they are stored.
- What we can read is the shape around that content: the date of each item, its category, its status, its severity or priority, and how many rows there are. That tells us when you had care, how often, and roughly how much of it — never what was measured, prescribed, diagnosed, or written. We keep those columns readable so the database can sort, filter, and paginate your chart.
- The other things we can read, stated up front: your email address, your display name, your profile photo if you uploaded one, and your audit log. And the plaintext passes through our servers twice by design — while we extract a document you uploaded, or one imported from your health system that you ask us to analyze, and while an AI feature runs — both described below, neither stored in that form.
- If you connect a health system, we fetch records from it on your behalf and encrypt them to your key before storing them. We also keep an access token from that health system under a key on our servers rather than yours. It is the one part of this we could use ourselves. See Records imported from a health system below.
- We do not sell your data, ever. We do not use Your Content to train AI models. Our AI provider (Anthropic) does not train on data sent through their API.
- We use a small number of sub-processors (listed below). We disclose each one. Our AI provider (Anthropic) processes data transiently; for the batch jobs behind extraction and chart review, we delete the job from Anthropic as soon as the result is stored — see the Security disclosure.
- You can delete your account at any time. A self-service full-export endpoint is on the roadmap; until it ships you can email privacy@open-chart.com and we will package your data within 30 days — noting that the clinical content reaches you as the ciphertext we hold, because we cannot decrypt it. An export that unlocks in your own browser is what the self-service endpoint is for.
2. What we collect
Account identity
- Email address. Used to identify your account and (rarely) to send transactional notices.
- Cryptographic material derived from your password. Specifically: a 16-byte Argon2id salt, the Argon2id parameters (memory, iterations, parallelism), an HMAC-peppered authentication verifier, and your ciphertext-wrapped master key. We cannot derive your password from any of these.
- Recovery code material. Where you opted in: a ciphertext-wrapped copy of your master key and an HMAC of a recovery-derived authentication value. We never see the recovery code itself.
- Demographic profile if you filled out the welcome wizard or Profile page: display name, birth year and month, sex assigned at birth, height, units preference, race / ethnicity (multi-select), country/countries lived in, smoking / alcohol / pregnancy status. All fields except birth year are optional. We use these to help the AI interpret age-adjusted and sex-adjusted reference ranges. The health-bearing fields — birth year and month, sex assigned at birth, height, race, ethnicity, countries, and your smoking, alcohol, and pregnancy status — are encrypted under your master key. Your display name and units preference stay readable to us, because the server renders your name in the app header before any JavaScript runs. If your account predates that change, the older plaintext copy is converted and cleared the next time you sign in.
- Profile photo if you uploaded one. Stored as plaintext bytes in our database — the largest of the few deliberate exceptions to our BYOK posture, alongside your display name. Served only to you and to recipients of share links you create. Max 2 MiB; the client resizes to ~50 KB on upload.
Source documents
- The encrypted blob of every record you upload. Plus the encrypted filename and MIME type, the unencrypted file size, and the wrapped-DEK envelope.
- Document metadata that the AI extractor pulls out and we use to organize your records: the document’s kind (e.g. “lab report”, “MRI brain”), provider name, facility name, and clinical specialty. These are encrypted under your key along with the rest of the extracted content; your browser decrypts them to draw the records list’s filters and the per-record badges. The document’s date stays readable to us, because the database sorts and paginates your records by it.
- A per-user HMAC of each document’s plaintext (using a key derived from your master key). Same file uploaded twice by you produces the same hash and we offer a dedup prompt; the same file uploaded by two different users produces different hashes. The hash is not reversible to the file contents.
Structured clinical data (encrypted under your key)
Every row below is stored as ciphertext. The values are encrypted with AES-256-GCM under a key wrapped to your account’s public key, whose private half exists only sealed under your master key — so we hold these rows without being able to open them. Your browser decrypts them to draw your chart and your trends.
- Observations. Each lab value, vital sign, imaging measurement, or other finding the extractor pulls out: code (LOINC / SNOMED / RxNorm / UCUM), display name, value, unit, reference range, abnormal flag, body site, and the model’s self-reported confidence. All of that is encrypted.
- Conditions, medications, allergies, immunizations, recommendations. One table per FHIR-shaped resource. The clinical content — the condition name, the drug and dose, the substance and reaction, the vaccine and lot, the text of a recommendation — is encrypted. Each row also carries a source field distinguishing entries you typed in the welcome wizard from entries the AI extracted or an import brought in.
- Per-document narrative digest. A small JSON blob per record holding the AI’s 1-3 sentence summary, structured imaging findings, genetic test findings, procedure outcomes, the raw provider impression paragraph copied verbatim, and AI-suggested questions for your doctor. Encrypted.
- Chart reviews and chart insights. When you run a Chart Review, we store the AI’s emitted insights and themed clusters of your recommendations and questions. The titles, bodies, cited record IDs, suggested actions, and proposed conditions are encrypted. The severity, category, and the status edits you make (acknowledged / resolved / dismissed) stay readable, so the app can sort and filter them without decrypting.
- What stays readable on every one of these rows. The dates (effective, onset, start and end, administered, recommended, document date), the category, the status, the severity, the priority, the source, the row counts, and the internal keys that join rows together. We keep those in the clear because the database has to order, filter, and paginate on them, and because a handful of fixed enum values is not meaningfully hidden by encrypting it. A reader of our database can tell that a panel of labs was drawn on a given date and that a condition is active. They cannot tell which analytes, what the values were, or what the condition is.
“Ask your record” chat history (encrypted)
- Your saved conversations with the assistant. Each message is encrypted in your browser under your master key before it reaches us, exactly like your documents. We store only the ciphertext, the message order, and timestamps — we cannot read your chat history. To generate each answer we transiently send the conversation and your chart context to Anthropic (see the sub-processor table); we do not persist that plaintext.
Subscription billing
- Plan tier and subscription status. Whether your plan is Free, Standard, or Plus; the subscription period end; whether cancellation is pending at period end; and the opaque Stripe customer ID + Stripe subscription ID. We do not store your card number, billing address, name on card, or receipt history — those live exclusively with Stripe.
- Webhook audit trail. We persist the full Stripe webhook payload of every billing event we receive (subscription create / update / cancel, payment failures) for forensics and dispute defense. The payloads come from Stripe; we do not introspect them beyond the fields we need to set your plan.
User-generated content visible to other users
- Feedback board posts, comments, and votes. If you submit a feature idea, comment on another user’s idea, or upvote/downvote one, your display name (from your demographic profile) is shown next to your post. If you haven’t set a display name we show “anonymous”. We never expose your email address on the feedback board.
- Patient identity shown to share-link recipients. When you generate a share link, the recipient sees the patient’s display name and profile photo (if set) so a clinician can keep track of which patient’s records they’re looking at. If you don’t want this, leave the display name and photo blank.
API access (Plus tier)
- API tokens. When you create an API token we store its label, creation date, last-used timestamp, and a SHA-256 hash of the token value — never the raw token. The token addresses the FHIR-shaped endpoints at
/api/v1/fhir/*. Because your clinical rows are encrypted under a key we do not hold, those endpoints cannot serve them: a request that would return encrypted rows returns an error saying so, rather than a bundle that silently omits them. A browser-mediated export, which decrypts in your own session, is the path we are building for third-party access.
Collected automatically
- Authentication metadata. Session timestamps, user-agent strings, the HMAC of your IP address. We do not store the raw IP.
- Audit log entries. Each sign-in, upload, download, extraction run, chart review, share creation, share open, account-recovery event, billing transition, and API-token action is logged with timestamps and the same hashed IP indicator.
- Operational logs. Web-server access logs scoped to error states, retained for 30 days, with IPs truncated to a /24 (IPv4) or /48 (IPv6) for diagnostics.
What we explicitly do not collect
- Your password.
- Your master encryption key. Your recovery code. Any URL-fragment grant secret you use for sharing.
- The plaintext bytes of your source documents on our servers after the extraction request returns. The plaintext exists in a single in-process buffer for the duration of one HTTP request and is zeroed before the request handler exits. The one extension of that window: if you start a chart review while documents are still processing, the decrypted context your browser sent is held in our server’s memory until the job runs — single-use, expiring, and never written to a database, a log, or a disk. Important caveat: the plaintext is processed by our AI provider (Anthropic) to produce the extraction; for batch jobs we delete the job from Anthropic once the result is stored, so it isn’t retained there for the Batch API’s 29-day maximum. See the Security disclosure for detail.
- Your card number, billing address, or any payment-method data. Stripe handles those on Stripe-hosted pages; we never see them.
- Cookies for advertising, analytics tracking, or session replay. We use only one cookie — your session cookie.
- Browser fingerprinting signals beyond the user-agent string already noted above.
3. Records imported from a health system
You can connect open-chart to your health system — Epic and Oracle Health systems today — and have your records imported instead of hunting for PDFs. This section describes that path specifically, because it is the one place where we fetch health information about you from a third party rather than receiving it from you.
What we ask for, and what we can do with it
- Read-only access to five kinds of record: results and vitals, conditions, medications, allergies, and immunizations. You sign in on your health system’s own site and approve the connection there. We never see your MyChart username or password.
- Notes and reports, from Oracle Health systems. We also fetch clinical documents such as visit notes and imaging reports, and store them sealed the same way. They appear on your Records page. Nothing is sent to our extraction service until you choose to analyze one; when you do, your browser decrypts it and its text passes through exactly as an uploaded file’s does.
- We can never write anything into your medical record. The access we request is read-only, and open-chart has no code that writes to a health system. Nothing you do here changes what your clinicians see.
- We check about once a day. You can import at any time by pressing the button, and once you have confirmed a connection is yours we also check it on a schedule while you are away. Anything that arrives is encrypted to your key before it is stored, so it is unreadable to us either way, and we email you that something came in — never what it was.
- What arrives may not be everything. A health system returns what it chooses to expose through its API, and nothing from anywhere else you have had care. Treat your chart here as a copy, not the official record.
You confirm whose record it is before anything is imported
One MyChart login can open more than one person’s chart — a parent’s login can open a child’s, an adult child’s can open a parent’s. What a health system hands back for one of those proxy sessions is indistinguishable from what it hands back for your own, so nothing in it tells us whose chart we have been given. We therefore show you the name and date of birth behind the connection and import nothing at all until you confirm it is yours. If it is not, one button disconnects and no records are fetched.
What we store, and in what form
- Encrypted before it is written down. Our server fetches over its own connection, at a moment when your master key is nowhere near it. It generates a fresh encryption key, encrypts what came back, and wraps that key to your account’s public key — whose private half exists only sealed under your master key. The result is a record we wrote and cannot read back.
- The original bundle too. The raw data your health system sent is stored the same sealed way, so you keep the source behind every row — and do not have to take our interpretation of it on trust — without us being able to open it either.
- An import refuses to run for an account with no key to seal to. There is no path in the product that writes imported clinical content in readable form.
- What stays readable to us is the same as for the rest of your chart: the date of each item, its category, and its status. We can see that a lab panel came back on a date and that a medication is listed as active. We cannot see which analytes, what the values were, or which drug.
The access token we keep, stated plainly
So that you are not sent back to your health system’s login every time you import, we keep the OAuth refresh token it issues. That token is encrypted — but under a key held in our server environment, not under yours. It has to be: an import runs on our server, over our own connection to the health system, and your master key never reaches our server in any flow — so a token sealed to your key would be one we could never use. The consequence, without hedging: someone with access to both our database and our server configuration could decrypt that token and use it to pull your records from your health system directly. Encrypting your clinical rows does not close that path.
Every application that connects to a health system this way and stores a refresh token has the same property. We kept it deliberately, because the alternative is re-approving the connection on your health system’s site every time you want new results — and because the daily check that brings those results in while you are away runs on it. So this is a credential we hold and use, not one we hold and promise not to touch. What that job fetches is sealed to your key as it arrives, and the token is the only thing the server-held key opens. We would rather say that plainly than leave you to discover it.
Disconnecting deletes it. When you disconnect, we erase the stored credentials rather than only marking the connection inactive — the token is gone and our server can no longer reach your health system. Separately, you can revoke open-chart’s access from your health system’s own portal at any time, and that works whether or not you disconnect here.
For completeness, this is not the only thing protected by a key we hold rather than one you hold. When you dismiss an insight or a suggested question, we store a keyed fingerprint of it so the same suggestion does not come back — keyed with a secret in our server environment, not with yours. It is not recoverable from a copy of the database alone, but we are the ones holding the key, and the honest description is that rather than “we cannot read it”.
Disconnecting keeps your records; removing them is a separate step
Disconnecting ends the connection. The records it already imported stay in your chart, because they are yours and you may still want them after the connection is gone. If you want them out — most often because the identity check above was answered too quickly and someone else’s chart came in — Remove these records on the Import records card deletes every row that connection created: the results, conditions, medications, allergies, and immunizations it brought in, together with the stored source bundles. It is a deletion, not a hidden flag. Deleting your account removes them as well, along with everything else.
A connected health system is a source we read from, not a sub-processor we send your data to. We send it the authorization request and nothing about your open-chart account beyond what that flow requires.
4. How we use what we collect
- To provide the Service. Authenticate you, serve your encrypted records, render your trend charts, and process share links.
- To run AI extraction on records you upload. We send the decrypted plaintext to our sub-processor (Anthropic), receive structured observations back, and persist only those structured observations — encrypted under your key, which is why we cannot read them back afterwards.
- To answer your questions in “Ask your record.” When you chat with the in-app assistant, we send your extracted chart context and your questions to Anthropic to generate a grounded answer, then store the conversation encrypted under your master key so you can return to it. We can’t read your saved history.
- To secure the Service. Detect abuse, investigate incidents, rate-limit endpoints, surface suspicious activity in your audit log.
- To communicate with you. Transactional messages about your account (e.g., a security alert, a change to these terms). We do not send marketing email without a separate opt-in.
- To comply with legal obligations. Respond to lawful subpoenas, court orders, and regulatory requests — with the limitations described in the Security disclosure.
We do not use Your Content to train AI models. We do not sell Your Content to third parties. We do not share Your Content with advertisers, data brokers, or analytics providers.
5. Sub-processors
We use the following sub-processors, each of which receives only the data necessary for the function it performs:
| Sub-processor | Purpose | Data it sees |
|---|---|---|
| DigitalOcean (or equivalent hosting) | Application hosting | Encrypted-in-transit HTTPS traffic, server logs scoped to error states |
| Managed Postgres (e.g., DigitalOcean Managed DB, Neon) | Primary database | Hashed authentication verifiers and wrapped key material; the encrypted clinical rows (observations, conditions, medications, allergies, immunizations, recommendations, chart reviews + insights, themes) together with the dates, categories and statuses we keep readable to sort and filter them; the encrypted digest and document metadata for each record; the encrypted source bundle of every imported record; encrypted demographics; your display name and profile photo bytes; provider OAuth tokens encrypted under a key held in our server environment; audit log entries; billing audit trail |
| Cloudflare R2 (or equivalent object storage) | Encrypted record storage | Ciphertext blobs only — useless without your master key |
| Anthropic | AI extraction, chart-level review, and the 'Ask your record' assistant | The plaintext of one document during extraction; your full extracted chart (records' digest summaries + observations + recommendations + demographics) during a chart review; and your extracted chart context plus your questions during an 'Ask your record' chat. Because those rows are encrypted under your key, your browser decrypts the chart and sends it with the request — our server assembles the prompt and discards it. Extraction and standard chart reviews use Anthropic's Batch API (which can retain inputs/outputs up to 29 days for retrieval), but we delete each batch from Anthropic as soon as the result is stored — minutes, not weeks. Plus-tier chart reviews and all chat use the synchronous Messages API (configurable zero retention at the account level). Anthropic does not train on this data. (Your saved chat history is separately encrypted under your master key before storage — see the Security disclosure.) |
| Email provider (e.g., Postmark / Resend) | Transactional email | Your email address and the contents of any account notice we send you |
| Stripe | Subscription billing | Card data, billing email, billing address, name on card, receipt history — collected by Stripe on its own pages and never seen by open-chart. We only store an opaque Stripe customer ID and your plan status. |
We will update this table when we change sub-processors and will give material notice of changes that expand the categories of data shared.
A health system you connect is not on this list, because it is not a sub-processor: we read records from it, we do not send your data to it. See Records imported from a health system above.
6. Sharing and disclosure
- Share links you create. When you generate a share link, anyone who possesses the link can request (and decrypt locally) the corresponding record until the link expires, is fully used, or is revoked. The recipient also sees your display name and profile photo if you set them, so a clinician can keep track of whose records they’re looking at. We do not control what recipients do with decrypted content.
- Feedback board. Posts, comments, and votes you make on the in-app feedback board are visible to other authenticated open-chart users. Your display name (not your email) appears next to your contributions. If you haven’t set a display name, posts show as “anonymous”.
- Legal process. We comply with lawful subpoenas, court orders, and regulatory demands. Where permitted, we will notify you in advance and give you an opportunity to challenge the request. The Security disclosure describes what we could produce.
- Corporate transactions. If we are acquired, merged, or sold, your account and Your Content may transfer to the successor entity. We will give you notice and an opportunity to delete your account before any such transfer.
- Protect rights and safety. We may share limited information where reasonably necessary to enforce our Terms, prevent fraud, or protect the safety of users or the public.
7. Data retention
- Account and content. Retained until you delete your account, or until you delete the specific record. Deletion is immediate from our primary database and propagates to our object storage within 24 hours.
- Audit log entries. Retained for at least 12 months after the event for your reference, or longer if required by law.
- Database backups. Our managed database provider takes automated daily backups with point-in-time recovery, retained on a rolling basis (currently up to seven days) before being rotated. The data in those backups remains in the same form it was in when stored: encrypted blobs and encrypted clinical rows stay encrypted, and the readable columns — dates, categories, statuses, your email and display name, your profile photo — stay readable.
- Imported records and connections. Records imported from a health system are retained like the rest of your chart: until you delete your account, or until you remove them from the connection that brought them in. Disconnecting erases the stored access token immediately; the connection row itself is kept, without credentials, as history of a link that once existed.
- Anthropic batch data. The Batch API can retain inputs and outputs for up to 29 days, but we delete each batch from Anthropic as soon as the result is stored, so it isn’t retained for that window. Any residual retention after deletion is governed by Anthropic’s data policy. See the Security disclosure.
- Stripe billing data. Card numbers, billing addresses, receipts, and payment history are retained by Stripe per Stripe’s own retention policy. Their privacy notice applies.
- Operational logs. Retained for 30 days and then deleted.
8. Your rights
Depending on where you live, you may have rights to access, correct, delete, export, or restrict our processing of your personal information. These include rights under the EU General Data Protection Regulation, the UK GDPR, the California Consumer Privacy Act (as amended by the CPRA), and similar laws. You can exercise these rights by:
- Downloading individual records you uploaded from the records list (one click per record), and viewing every extracted observation, condition, medication, etc. on the record-detail page and the trends view. The Plus tier also exposes read-only FHIR-shaped endpoints at
/api/v1/fhir/*, though they cannot serve clinical rows that are encrypted under your key — we hold no key that opens them, so those requests return an error rather than an incomplete bundle. A browser-mediated export that decrypts in your own session is the replacement we are building. - Using the in-app account-deletion control to terminate your account and erase your data. (A unified “export everything as one archive” endpoint is on the roadmap; until it ships, email privacy@open-chart.com and we will package your data within 30 days — the clinical content in the encrypted form we hold it in, since we have no key that opens it.)
- Emailing privacy@open-chart.com with any other request. We will respond within 30 days.
We will not discriminate against you for exercising any of these rights.
9. International transfers
We process data on servers located in the United States. Where personal information is transferred from the European Economic Area, the United Kingdom, or Switzerland to the United States, we rely on the Standard Contractual Clauses adopted by the European Commission (and equivalent UK IDTA) with our sub-processors.
10. Children
The Service is intended for adults. We do not knowingly collect personal information directly from children under 16. If you believe a child has provided personal information to us, contact us at privacy@open-chart.com and we will delete it. Parents and guardians may upload a minor child’s records to their own account where legally authorized to do so.
11. Security
See our Security disclosure for the architectural detail. In short: source documents and the clinical rows extracted or imported from them are encrypted with keys we do not hold; passwords and recovery codes are never transmitted to us; and the places where plaintext does briefly touch our servers — document extraction, AI features, and a queued review held in memory — are each documented there rather than glossed over.
No system is perfectly secure. If we discover an incident affecting your account, we will notify you within seven days of confirming the scope and provide a post-mortem describing what happened and what we’ve changed.
12. Changes to this policy
We may update this policy from time to time. Material changes will be communicated to you by email or in-app notice with reasonable advance notice where practicable. Your continued use of the Service after the effective date of a change constitutes acceptance of the updated policy.
13. Contact
Questions, requests, or complaints? Email privacy@open-chart.com. For security-specific issues, please use security@open-chart.com.