Trust & Data Handling
How we handle HL7 messages, FHIR resources, and the data you send to our validation API.
What we receive
When you (or our Bridge agent) call /api/v1/validate/<token>, your HL7v2 message or FHIR resource is transmitted to our servers over TLS. Once received, the message is parsed in memory, validated against your spec, and the result is serialized back to you in the HTTP response.
What we keep
We keep a small, fixed telemetry record per request. The full list of fields:
share_id— which shared spec was usedspec_slug— the spec's URL identifier (metadata only)client_ip_hash— a salted SHA-256 of your source IP, for abuse detectionmessage_type— the HL7 trigger event (e.g.ADT^A01) or FHIR resourceType (e.g.Patient)status— the overall outcome bucket (pass / fail / parse-error / ...)http_status,parse_okmessage_size_bytes— for volume-based billingrule_count,errors_count,warnings_countresponse_msagent_version— if the request came from our Bridge agentcreated_at— request timestamp
What we discard
The following data exists only in transient memory during the request and is never written to disk, our database, or application logs:
- The raw HL7v2 message or FHIR JSON body
- The parsed message AST (segments, fields, components, values)
- Every
actualValueandexpectedValuein the validation results - Every rule's human-readable message (because we interpolate field values into it)
- Any generated ACK content (in Bridge agent flows)
After the response is written back, all of these are released to the JavaScript garbage collector and no longer exist anywhere in our infrastructure.
How we enforce it
Our promise is enforced by code, not policy. Three technical controls:
- Typed telemetry boundary. The single function that writes to our database (
recordValidation) accepts a strictValidationTelemetrytype with a fixed list of fields. There is no path by which message content can reach the database — the type system rejects it at compile time. - Sanitized error logging. Errors thrown by HL7 parsers and validators sometimes embed fragments of the input message in their error text. Our
safeErrorLoghelper logs only the error class name — nevererror.messageorerror.stack. - Static-analysis guard. A pre-build check scans the validation hot path for risky logging patterns and blocks deployments if any are introduced. This is run automatically before every production build.
Source IPs and abuse detection
We never store raw client IPs. Instead we record a salted SHA-256 hash so we can detect repeated abuse from the same source without retaining a personally-identifiable network address. Because we don't pair IPs with user identities or message content, the information value of these hashes is intentionally limited.
The Bridge agent (local validation)
For customers who don't want HL7 traffic to leave their network at all, we offer an HL7 Bridge agent that runs on your infrastructure. The agent presents one or more local MLLP listeners, validates traffic against your specs, and returns proper HL7 ACKs — all without sending the message bodies to our servers. Pro-tier customers can run the agent in fully-local mode where validation logic itself runs in-process from signed compiled artifacts.
What we don't do
- We do not use customer messages for training, analytics, or research.
- We do not share telemetry with third-party analytics providers.
- We do not use Sentry or other external error tracking on the validation endpoint.
- We do not log message content to file, console, or any external sink.
- We do not retain message content even on failed/erroring requests.
Questions
If your security or compliance team has questions about our data handling, contact us at security@interoperall.com.