Whisper · Docs
Health

Platform integrations

Whisper sits beside the health-IT stack you already run and anchors exactly one thing: a routable, verifiable identity at the endpoint/device↔cloud IP boundary. This is the layer where a stolen bearer token, a replayed FHIR credential, or a copied device string today looks identical to the real thing.

Everything below is a proposed integration pattern (our design, not a vendor endorsement), and every one is written the same way: Whisper complements the mechanism you have; it never replaces it. We do not authenticate HL7 v2 messages on the clinical VLAN, we do not touch an unauthenticated DICOM C-STORE flowing between two nodes on the same segment, and we do not sit on a device's on-board command path. Those are segmentation and protocol-authentication problems, on a different layer with a different owner, and they are already someone's job. Whisper's job is the network identity of whatever is talking across an IP boundary: a FHIR server, a connected device, a QHIN participant, a SMART client. It's expressed as an IPv6 /128 that DNSSEC, DANE and RDAP can prove and one call can revoke.

One spine under all of them. Each integration below reuses the same shipped primitive: a deterministic /128 derived from a device or endpoint's public key plus a native identifier it already carries, such as a FHIR Endpoint.identifier, an FDA UDI, or a DICOM AE Title, passed as device_id (Device & FHIR-endpoint identity). It's published with a DANE-EE 3 1 1 pin and an RDAP record, verifiable by anyone with no account. The integrations differ only in where in your stack that identity is bound and checked.

Anchor the boundary, not the LAN

A hospital runs tens of thousands of networked machines that were designed to be trusted, not to prove who they are. Several trust mechanisms already cover the layers below the network: message authentication on the clinical bus, segmentation between zones, the device's own secure boot. The mistake is to imagine a new identity system has to displace one of them. It doesn't. Whisper is deliberately confined to the one place none of them cover: the moment a network endpoint claims to be a particular device, FHIR server, or sanctioned exchange participant, and the receiver has only a bearer token, a shared secret, or a private-CA certificate to go on.

Layer Owner / mechanism Whisper's role
Clinical-LAN messaging (HL7 v2) network segmentation + protocol context none: never authenticates the interface-engine feed
On-segment imaging (DICOM C-STORE) PS3.15 TLS + AE-Title config + VLAN none: a same-segment transfer, a segmentation problem
Device on-board command path secure boot / firmware / IEC 62443 zones none: the vendor's silicon, not the network
Endpoint / device ↔ cloud (IP) UDAP / OAuth bearer / vendor mTLS / UDI string anchors here: an out-of-tenancy /128 the caller is, provable without anyone's private CA

Read the last row as the whole thesis: at the IP boundary, identity today is a claim carried in a header: a bearer token, or a certificate only a private community anchor can validate. Whisper turns it into a network fact: the source address itself, forward-confirmed in DNS, pinned in DANE, registered in RDAP.

owned by segmentation / protocol auth: Whisper never here the IP boundary: the one layer Whisper anchors HL7 v2 on the clinical VLAN segmentation · interface engine · MLLP DICOM C-STORE, same segment PS3.15 TLS · AE-Title config · VLAN Device on-board command path secure boot · IEC 62443 zones the fence: Whisper stops here endpoint / device ↔ cloud: IP boundary UDAP · OAuth bearer · vendor mTLS · UDI derive + publish device /128 · DNSSEC · DANE-EE 3 1 1 bound to an identifier it already carries ✓ Whisper anchors here
The clinical bus, the on-segment transfer and the device's own firmware stay theirs. Whisper never crosses the fence. It anchors one layer: the identity of the endpoint on the IP fabric, provable without anyone's private CA.

FHIR Endpoint: the keystone

The FHIR Endpoint resource is where a directory publishes which URL reaches this organization or service. Its Endpoint.address is a real url, DNS-addressable by construction, and Endpoint.identifier is a stable business id. But the resource carries no trust model of its own: no key, no signature, no certificate. Nothing in the resource stops Endpoint.address pointing anywhere; trust is delegated entirely to TLS and to out-of-band configuration. A directory entry ages, and its authenticity rests on whatever CA the community happens to trust, not on anything self-verifying at the address.

The integration adds the missing binding without changing your FHIR server. Give the host behind Endpoint.address a Whisper /128, publish a DANE TLSA record over DNSSEC that pins the endpoint's exact leaf key, and record the address's registry object in RDAP. Publish the /128 (or its DNSSEC-anchored name) as an Endpoint.identifier under a Whisper identifier system. Now a relying party resolves the directory entry and confirms the address is the endpoint it claims to be. It's trustless, verified against the IANA DNS root, with no change to the FHIR REST interface, the connectionType, or the resource model.

# A relying party confirms a FHIR endpoint at the address it was handed:
# no FHIR-server change, no community anchor pre-provisioned, just DNSSEC + DANE.
dig +dnssec TLSA _443._tcp.fhir.<tenant>.agents.whisper.online
;; flags: qr rd ra ad          ← ad = DNSSEC-authenticated
;; _443._tcp....agents.whisper.online. 300 IN TLSA 3 1 1 b653a4ef...fcb82d1d

# the address IS the endpoint: forward-confirmed reverse DNS names it
dig -x 2a04:2a01:fee5:cae::b17 +short
fhir.<tenant>.agents.whisper.online.

The keystone is also where the shipped spine attaches. The endpoint host, or a connected device, already holds a key: a UDAP server certificate key, a TPM, an in-device secure element, or a manufacturer-issued device leaf. Submit its public SubjectPublicKeyInfo, pass the Endpoint.identifier (or the device's native id) as device_id, and Whisper mints the forge-proof address. The private key never leaves the device; only the public SPKI is ever presented. The derivation is deterministic and tenant-bound: the same key and identifier always yield the same /128 (idempotent re-provisioning), the mapping is unlinkable to outsiders so a fleet can't be enumerated from its addresses, and the identifier alone yields nothing without the key.

# The spine: derive an endpoint or device /128 from the key it already holds
# + a native identifier as device_id. identity_public_key is the PUBLIC SPKI.
CALL whisper.agents({op:'connect', args:{
  tier:                'wireguard',
  identity_public_key: '<base64 SPKI of the endpoint/device key>',
  device_id:           'urn:example-hie:endpoint:main'   // the Endpoint.identifier value
}}) YIELD op, ok, status, result, error
   RETURN op, ok, status, result, error

Send it with stock tools. The control plane is one HTTP endpoint, and the key travels only in the header:

curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d @connect.json | jq .      # connect.json = {"query":"CALL whisper.agents({op:'connect', ...})"}
{"ok": true, "status": 200, "result": {
   "address": "2a04:2a01:fee5:cae::b17",
   "wireguard": { "…": "…" }}}          # → the deterministic /128 + a WireGuard config

The behaviour is honest and predictable, which is the point:

Re-provision with…Result
the same key + identifier200: the same /128 returns (idempotent)
a different identifier on the same tenant's key409: the identity is already bound; no silent rebind
a non-string device_id400: a clear input error, never an opaque 500

Tear it down worldwide at DNS-TTL speed with one call. The /128, its PTR, and its DANE pin all go together:

CALL whisper.agents({op:'revoke', args:{agent:'2a04:2a01:fee5:cae::b17'}})
  YIELD op, ok, status, error RETURN op, ok, status, error

As forge-proof as the device's key custody. A /128 is exactly as strong as where the private key lives: a TPM or secure element makes it hardware-anchored; a device with weak key storage inherits that weakness. Whisper consumes only the public SPKI and can't fix custody it never sees. State it plainly to your assessor. The full derivation, unlinkability property and DANE mechanics are on Device & FHIR-endpoint identity.

UDAP: a public anchor for endpoint trust

UDAP (the HL7 Security for Scalable Registration, Authentication, and Authorization IG, at the heart of the FAST security profile) is the closest existing thing to real FHIR endpoint identity: it puts X.509 endpoint trust on FHIR through a community anchor. Its central assertion is precise: the identifying URI is the FHIR base URL, and that URL "SHALL match a uniformResourceIdentifier entry in the SubjectAltName of the server's certificate" and "SHALL equal the server's {baseURL}." The /.well-known/udap document returns signed_metadata, a JWT signed by the server key with its certificate chain in the JWS x5c header.

That binding is excellent. Its only limit is who can check it: UDAP trust is rooted in a private, community-scoped anchor. You validate the chain against whichever anchor you were configured with (a TEFCA anchor, a DirectTrust anchor, a state-HIE anchor). The certificate's SAN is a URI, but nothing anchors that URI in DNS: no DANE, no DNSSEC. A relying party outside your community, with no pre-provisioned anchor, cannot verify the very base-URL↔key binding UDAP so carefully asserts.

Whisper publishes that same binding in the open. A DANE TLSA record over DNSSEC pins the exact certificate UDAP presents, keyed to the endpoint's DNSSEC-signed name, so the base-URL↔key binding becomes verifiable by anyone, in any trust community or none, with nothing but the IANA root. It is a second, orthogonal proof beside the community chain: additive, never a replacement for it.

One FHIR endpoint cert SAN URI == {baseURL} · key sealed on server UDAP chain DANE-pin · publish Private community trust anchor TEFCA · DirectTrust · state-HIE CA verifiable INSIDE the community Public DNSSEC + DANE-EE pin _443._tcp.fhir.<tenant>… TLSA 3 1 1 verifiable by ANY relying party needs the community anchor pre-provisioned needs nothing but the IANA DNS root
Both verifications share one certificate: the endpoint's own. UDAP's community chain stays the authority inside the community; the public DANE pin is the identity a party who has never joined the community can confirm, using nothing but the DNSSEC root.
# Verify a UDAP endpoint's identity from outside its trust community: trustless.
whisper verify --trustless fhir.<tenant>.agents.whisper.online
dnssec   pass   DNSSEC-root   AAAA, PTR and TLSA(3 1 1) all DNSSEC-validated to the IANA root
dane     pass   DNSSEC-root   served leaf SPKI-SHA256 == TLSA pin  (== the UDAP x5c leaf)
ledger   pass   DNSSEC-root   entry present, signature verifies
CRYPTOGRAPHICALLY PROVEN, trust anchor: DNSSEC root (IANA) + DANE-EE

Complements UDAP, does not replace it. Trusted Dynamic Client Registration, tiered OAuth, JWT client authentication and the community chain stay UDAP's. Whisper publishes the same base-URL↔key binding in open DNS so it is verifiable across communities and independent of any single community's registration authority, and revocable at DNS-TTL: a second orthogonal kill-switch beside CRL/OCSP. See DANE & TLSA for the byte-for-byte record.

TEFCA · QHIN · the national directory

TEFCA's Common Agreement binds each QHIN, and the RCE Directory Service is how participants discover one another's endpoints, increasingly FHIR-native, with Facilitated FHIR requiring UDAP, Provenance and US Core. The founding pain is documented by ONC's own FAST taskforce: "there is neither an authoritative source for digital contact information nor a consistent method for locating it." Directories go stale; a listed FHIR address's authenticity rests on the community CA, not on anything the address can prove about itself. Trust is a top-down legal-and-PKI hierarchy, and a QHIN participant still has to answer TEFCA's own hard question: "verify who is asking."

Whisper gives each participant endpoint a public trust anchor the directory entry can be cross-checked against, and one the participant can revoke at DNS-TTL. Publish the participant's DANE-pinned /128 as an Endpoint.identifier (it drops straight into an NDH NDH-Endpoint profile), and an initiating node confirms the endpoint at the address before it ever presents a query, turning a blindly-trusted directory row into a self-verifying one. Nothing in the RCE Directory, the QTF, or the UDAP registration flow changes.

# A QHIN participant confirms a directory-listed endpoint at its address: keyless.
curl -s https://whisper.online/verify-identity/2a04:2a01:fee5:cae::b17
{"is_whisper_agent": true, "dane_ok": true, "jws_ok": true, "evidence": { … }}

# RDAP registry object for the address: who holds it, since when.
curl -s https://whisper.online/ip/2a04:2a01:fee5:cae::b17 | jq '.handle, .parentHandle'

See who's enumerating your directory presence before a request lands. Because every participant endpoint resolves through Whisper's own authoritative DNS and RDAP, the owner can ask who looked: a reconnaissance tripwire a top-down directory never gave you. op:'lookups' returns who resolved or RDAP-queried an endpoint's identity, so you catch a party iterating your listed addresses in recon, not in the post-mortem:

# who has been resolving / RDAP-querying this participant endpoint, and when
CALL whisper.agents({op:'lookups', args:{agent:'2a04:2a01:fee5:cae::b17', window:'24h'}})

Complements TEFCA / QHIN trust, does not replace it. The Common Agreement, the QHIN onboarding and the RCE Directory stay the framework for who may exchange under whose accountability. Whisper adds a DNS-anchored second proof of endpoint identity that any counterparty can verify without joining, an enumeration tripwire on your own listings, and cross-org revocation at DNS-TTL. The cross-organization attribution angle (naming the operator behind a request across rotating egress) is worked in full on Device/API-abuse cure.

FDA UDI & Device.url

The FDA UDI is the universal, regulator-mandated device identifier: a Device Identifier (DI, the labeler-and-model half, in GUDID and queryable through AccessGUDID / openFDA) plus a Production Identifier (serial, lot, expiry). It is the best semantic anchor for a fleet, but it is a barcode and a catalog row, not a network identity: it is not IP- or DNS-addressable, it is trivially copyable, and trust in it is trust that the registry is well-run. FHIR R5 models a connected device as network-addressable: Device.url is "a network address on which the device may be contacted directly" and Device.endpoint references an Endpoint, but nothing cryptographically binds the UDI or the identifier to that address. Nothing stops Device.url pointing anywhere.

The integration binds the UDI to a routable, verifiable identity. Derive the device's /128 from its existing key, pass the UDI DI (or a per-instance Device.identifier) as device_id, and point Device.url / Device.endpoint at the DANE-pinned address. The physical device now has an identity that is cryptographic and routable, keyed to the regulatory ID already in its labeling and GUDID, and revocable in one call. A DICOM AE Title, an ISO/IEEE 11073 device's EUI-64, or any other native identifier the device already carries is exactly the kind of value you pass as device_id; the AE-Title→IP mapping that today is "set by installation personnel" and unauthenticated becomes DNSSEC/DANE-verifiable.

# Bind a device's /128 to the UDI Device Identifier it already carries.
CALL whisper.agents({op:'connect', args:{
  tier:                'wireguard',
  identity_public_key: '<base64 SPKI of the device key>',
  device_id:           '00860001680123'          // the UDI-DI (GUDID / GS1)
}}) YIELD op, ok, status, result, error RETURN op, ok, status, result, error

# Device.url now points at the DANE-pinned /128: the address IS the device.
dig -x 2a04:2a01:d0c:a1d::e70 +short
dev-9f3c1a.<tenant>.agents.whisper.online.

Honest bridge: many devices can't present their UDI on the wire. GUDID stores only the DI; the PI lives on the label, and a lot of fielded equipment simply has no way to assert its UDI over the network. In that common case the UDI→/128 binding needs a join: the IoMT inventory platform that already carries UDI ↔ device supplies it. That is a partnership seam, not a blocker, and it is exactly the next section.

SMART-on-FHIR & OAuth2

SMART on FHIR authenticates the caller, not the endpoint. SMART App Launch is OAuth2 authorization-code; SMART Backend Services / Bulk Data uses a client-confidential-asymmetric flow: a one-time JWT signed with the client's private key (RS384/ES384), which sensibly avoids a shared secret. All of that governs which app may act, discovered through /.well-known/smart-configuration and a JWKS URL. What it does not do is prove where the token-bearing caller is on the network: a bearer minted or lifted for a Backend Services client is portable, and replayed from rotating cloud or residential egress it still authenticates. The last IP your logs recorded was never the caller.

Whisper adds attribution and a network allowlist beside the OAuth model, changing nothing in the flow. When a token-bearing caller looks suspicious, the read-only attribution graph names whoever is really behind the source, stitched across the Amazon → Google → Azure hops a raw last-IP loses, with a residential-proxy swarm collapsed by a stable JA3/JA4 client fingerprint that rides with the tooling even as IPs rotate. And where the client is one of yours, source-bind its egress to a /128 and allowlist the address, so a replayed JWT from anywhere else has no network identity to present.

# Name the operator behind a suspicious token-bearing caller, across rotating egress.
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.identify(\"34.90.x.x\")"}' | jq .
# -> operator fingerprinted across AWS / GCP / Azure; residential swarm collapsed by JA4

# For a client of yours: source-bind its egress and allowlist the /128, not a portable bearer.
whisper policy set --agent 2a04:2a01:d0c:a1d::e70 --default deny \
  --allow fhir.<tenant>.agents.whisper.online

Complements SMART / OAuth2, does not replace it. The authorization-code and Backend Services flows, the scopes, and the JWKS stay SMART's: they decide which app may act. Whisper attributes the network identity behind a token and lets you allowlist it, so a stolen or replayed bearer is enforced against a network fact. See Egress governance and Graph & cognition.

IoMT inventory platforms

Claroty xDome for Healthcare (Medigate), Armis Centrix, Cynerio (Axonius), Ordr, Forescout 4D, and Palo Alto Medical IoT are the leading IoMT visibility platforms. They're excellent at what's on your network and whether it's behaving: they discover every connected device passively, attribute deep attributes to it, and drive segmentation. But their device identity is observational: inferred from behavior, scoped to the one organization's network vantage, carried by no credential on the device, and non-revocable off their own appliance. The industry has converged on the premise that IP addresses are insufficient for identity; they can be spoofed, and solves it with inference inside one org's console.

Whisper is the verifiable identity layer beneath the device they already secured, and the integration runs both ways. Consume their inventory: the platform already carries the join the wire can't (UDI ↔ device ↔ serial ↔ attributes), so take that device_id and mint each device a forge-proof, publicly verifiable /128 from its existing key, no new appliance. Feed attribution back: the cross-organization operator fingerprint and the op:'lookups' enumeration tripwire are exactly the layer a single-org sensor structurally can't see (its vantage stops at one hospital's edge), delivered as a signed enrichment feed. And for the device that can't take a NAC agent (the EOL-OS pump or monitor), a governed /128 egress policy is agentless L3 segmentation, and op:'revoke' cuts a compromised unit off worldwide with no re-imaging and no truck-roll.

# Take the inventory's UDI/serial as device_id → a forge-proof /128, no new sensor.
CALL whisper.agents({op:'connect', args:{tier:'wireguard',
  identity_public_key:'<base64 SPKI>', device_id:'00860001680123'}})

# Agentless L3 segmentation for the device that can't take a NAC agent:
# default-deny egress, allow only the clinical destinations it needs.
CALL whisper.agents({op:'firewall', args:{agent:'2a04:2a01:d0c:a1d::e70',
  default:'deny', allow:['ehr.<tenant>.agents.whisper.online','ota.vendor.example']}})

# Contain one compromised device worldwide: no re-image, no truck-roll.
CALL whisper.agents({op:'revoke', args:{agent:'2a04:2a01:d0c:a1d::e70'}})

Complements the IoMT platform, does not replace it. Discovery, clinical-protocol DPI, MDS2/SBOM/CVE scoring and anomaly detection stay theirs: none of that is Whisper's layer. Whisper adds the publicly verifiable, DNS/DANE-anchored identity, the cross-org attribution their vantage can't reach, and revocation at DNS-TTL, and it plugs into their console rather than adding one your analysts babysit. Today the signed findings feed back over the public API and the Splunk connector; native console connectors are on the roadmap.

The SIEM feed: Splunk, Sentinel & OpenCTI today

Identity and attribution are only useful to a health SOC if they land in the tools it already runs. Whisper emits every finding as a signed JSON evidence chain: a whisper.identify attribution result, an op:'lookups' enumeration alert, an identity mint or revoke from the transparency log, so it is machine-readable enrichment for your IoMT platform and threat-intel, not another console an analyst babysits.

The Splunk connector is shipped today. It maps each signed finding onto CEF and ECS fields and forwards it into Splunk, so an endpoint-enumeration tripwire or a rotating-egress attribution becomes a correlatable event beside your Claroty / Armis / Forescout telemetry:

# The signed finding the Splunk connector maps to CEF / ECS and forwards.
curl -s https://graph.whisper.security/api/query \
  -H "X-API-Key: whisper_live_xxx" \
  -H "content-type: application/json" \
  -d '{"query":"CALL whisper.identify(\"34.90.x.x\")"}' | jq '.result.evidence'
# -> a replayable, signed evidence chain -> CEF: deviceVendor=Whisper cs1=operator …
#    (the connector emits one event per finding; the chain re-verifies offline)

Nothing issued in the dark. Every identity mint and every revoke is written to a public, append-only Merkle transparency log (RFC 6962 tlog-tiles, Ed25519-signed, anchored to Bitcoin via OpenTimestamps): an auditable, non-repudiable issuance-and-revocation trail your SIEM, an OCR investigator, and an FDA reviewer can replay. Honest status: the log is tamper-evident, signed and Bitcoin-anchored today, but it is not yet independently witnessed: our two authoritative nodes co-signing is availability, not independence. It already speaks the C2SP tlog-witness protocol, so any external witness can co-sign; that step is on the roadmap and we label it as such rather than overclaim.

The Microsoft Sentinel connector and OpenCTI threat-intelligence integration ship today, mapped onto Sentinel's connector framework and OpenCTI's knowledge graph for continuous-monitoring workflows. STIX 2.1 over TAXII with Health-ISAC (H-ISAC) machine-readable export is on the roadmap, not shipped. It is listed honestly under On the roadmap below.

Because each device's telemetry can also be signed under its forge-proof /128, the readings a downstream system trusts carry non-repudiable provenance: the numbers came from the real device, not a spoofed feed on the same segment.

Shipped today vs proposed

Honesty about what runs matters more here than anywhere. The identity primitive under every integration is live and provable right now; the integration guides themselves are proposed patterns for wiring that primitive into each platform.

Building blockStatus
Deterministic /128 from a device/endpoint's public key + a native id (as device_id)shipped, live
Provision via the control plane (op:'connect', WireGuard tier)shipped, live
Keyless verify: whisper verify --trustless, /verify-identity, dig -x, RDAPshipped, live
DANE-pin an existing endpoint's certificate (FHIR / UDAP host) over DNSSECshipped, live
Revoke: /128 + PTR + DANE torn down at DNS-TTL speedshipped, live
Egress governance: op:'lookups', op:'firewall', op:'budget', policyshipped, live
Attribution graph over the public API (CALL whisper.identify(…))shipped, live
Splunk connector: signed findings mapped to CEF / ECSshipped, live
The six integration guides on this page (FHIR Endpoint, UDAP, TEFCA/QHIN, FDA UDI, SMART-on-FHIR, IoMT inventory)proposed (our design, not a vendor endorsement)

A dedicated --endpoint-id / --udi CLI flag is on the roadmap, not shipped. Device and endpoint provisioning today goes through the control-plane call shown in the keystone section above, which is live, with the identifier passed as the generic device_id. The CLI verbs that exist are whisper verify --trustless, whisper create --register, whisper kill --revoke, whisper policy and whisper logs.

On the roadmap

These feed device- and endpoint-security evidence into the tools an HDO SOC, an HTM team, and an OEM PSIRT already run. They are roadmap, not yet shipped, listed here so you can see where this goes:

Next