Verifiable Health Link
0.0.2-current - ci-build
Verifiable Health Link, published by IHE IT Infrastructure Technical Committee. This guide is not an authorized publication; it is the continuous build for version 0.0.2-current built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/IHE/ITI.VHL/ and changes regularly. See the Directory of published versions
The Retrieve Manifest transaction enables a VHL Receiver to retrieve a manifest (searchset Bundle) of available health documents from a VHL Sharer using a previously obtained and validated Verified Health Link (VHL).
This transaction occurs after the VHL Receiver has received a VHL from a VHL Holder (via ITI-YY4 Provide VHL) and validated the VHL signature.
FHIR Search Transaction: This transaction uses a standard FHIR search on the List resource, following the same pattern as MHD ITI-66 Find Document Lists. The manifest URL from the VHL payload contains all necessary FHIR search parameters. No custom operation is required.
Authentication: Implementations SHALL support at least one of the following authentication mechanisms. Participants MAY use HTTP Message Signatures (RFC 9421) or OAuth with SSRAA depending on their deployment context. The VHL Sharer authenticates the requesting VHL Receiver before processing the request.
OAuth with SSRAA Option: Implementations MAY support the OAuth with SSRAA Option, which uses OAuth 2.0 tokens for authentication as defined in the HL7 Security for Scalable Registration, Authentication, and Authorization IG (SSRAA). When this option is supported, implementations use OAuth Backend Services with JWT client assertions for system-to-system authentication.
Include DocumentReference Option: A VHL Sharer that supports the Include DocumentReference Option SHALL process the _include=List:item parameter to retrieve both the List and the referenced DocumentReference resources in a single response. This optimization reduces the number of round trips required by the VHL Receiver. If a VHL Sharer does not support this option, it SHALL ignore the _include parameter, and the VHL Receiver SHALL retrieve each DocumentReference individually using separate read requests.
Both the VHL Receiver and VHL Sharer SHALL authenticate each other's participation in the trust network. The VHL Sharer validates that the requesting VHL Receiver is authorized to access the documents before responding.
Capability Statements:
| Actor | Role |
|---|---|
| VHL Receiver | Initiates FHIR search request to retrieve document manifest using validated VHL as authorization |
| VHL Sharer | Responds to search request after authenticating and authorizing the VHL Receiver |
Core Standards:
FHIR Specifications:
IHE Profiles:
OAuth with SSRAA (Optional):
SHL Specifications:
Figure X.X.X.X-5: Retrieve Manifest Interaction Diagram
The VHL Receiver SHALL initiate a request to retrieve a set of health documents from a VHL Sharer, using a previously received and validated Verified Health Link (VHL).
Both the Receiver and Sharer SHALL validate each other's participation in the trust network using PKI material published by the Trust Anchor.
Optional behaviors:
A VHL Receiver initiates the Retrieve Manifest Request when:
This transaction uses a standard FHIR search on the List resource. The request is sent to the manifest URL decoded from the VHL (from ITI-YY4). The manifest URL contains all necessary FHIR search parameters.
Manifest URL Structure
The VHL Receiver performs an HTTP POST to the _search endpoint with the manifest URL parameters from the VHL payload:
Example Manifest URL from VHL:
https://vhl-sharer.example.org/List?_id=abc123def456&code=folder&status=current&patient.identifier=urn:oid:2.16.840.1.113883.2.4.6.3|PASSPORT123&_include=List:item
FHIR Search Parameters
The following FHIR search parameters are extracted from the manifest URL:
| Parameter | Type | Cardinality | Description | Example |
|---|---|---|---|---|
| _id | token | [1..1] | The folder ID (with 256-bit entropy) from the VHL - primary authorization mechanism | _id=abc123def456 |
| code | token | [1..1] | The type of List (typically "folder") | code=folder |
| status | token | [1..1] | The status of the List (typically "current") | status=current |
| patient | reference | [0..1] | The patient whose documents are referenced; either patient or patient.identifier SHALL be included | patient=Patient/9876 |
| patient.identifier | token (chained) | [0..1] | FHIR chained search on the patient reference parameter; resolves the patient by identifier (system|value) without requiring a direct Patient resource reference; either patient or patient.identifier SHALL be included | patient.identifier=urn:oid:2.16.840.1.113883.2.4.6.3|PASSPORT123 |
| identifier | token | [0..1] | Business identifier for the List | identifier=folder-2024-001 |
| _include | special | [0..1] | Include referenced DocumentReference resources; SHALL be "List:item" if used. Only processed if VHL Sharer supports Include DocumentReference Option | _include=List:item |
SHL Manifest Request Parameters
In addition to the FHIR search parameters in the URL, the following SHL-specific parameters SHALL be included in the request body:
| Parameter | Type | Cardinality | Description |
|---|---|---|---|
| recipient | string | [1..1] | Identifier of the requesting organization or person (e.g., "Dr. Smith Hospital", "Emergency Department - General Hospital") |
| passcode | string | [0..1] | User-provided passcode if the VHL is passcode-protected (P flag present in VHL) |
| embeddedLengthMax | integer | [0..1] | Integer upper bound on the length of embedded payloads (optional optimization hint) |
Implementations MAY authenticate using HTTP Message Signatures per RFC 9421. This option is not required; participants MAY instead use OAuth with SSRAA (see Section 2:3.YY5.4.1.4). HTTP Message Signatures provide cryptographic proof of the receiver's identity, request integrity, and non-repudiation.
Request Structure:
POST /List/_search HTTP/1.1
Host: vhl-sharer.example.org
Content-Type: application/x-www-form-urlencoded
Content-Length: 234
Content-Digest: sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
Signature-Input: sig1=("@method" "@path" "@authority" "content-type" "content-digest");created=1735689600;keyid="receiver-key-123";alg="ecdsa-p256-sha256"
Signature: sig1=:K2qGT5srn2OGbOIDzQ6kYT+ruaycnDAAUpKv+ePFfD6...:
Accept: application/fhir+json
_id=abc123def456&code=folder&status=current&patient.identifier=urn%3Aoid%3A2.16.840.1.113883.2.4.6.3%7CPASSPORT123&_include=List%3Aitem&recipient=Dr.+Smith+Hospital&passcode=user-pin&embeddedLengthMax=10000
HTTP Signature Components:
sha-256=<base64-encoded-hash>@method, @path, @authority, content-type, content-digestcreated: Unix timestamp when signature was createdkeyid: Identifier of receiver's public key (used to locate key in trust list)alg: Signature algorithm (ecdsa-p256-sha256, ecdsa-p384-sha384, rsa-pss-sha256, rsa-v1_5-sha256)sig1=:<base64-encoded-signature>:Signature Base Construction:
The signature base is constructed per RFC 9421 from the signed components:
"@method": POST
"@path": /List/_search
"@authority": vhl-sharer.example.org
"content-type": application/x-www-form-urlencoded
"content-digest": sha-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
"@signature-params": ("@method" "@path" "@authority" "content-type" "content-digest");created=1735689600;keyid="receiver-key-123";alg="ecdsa-p256-sha256"
Signing Process:
Verification Process:
keyid from Signature-Input headerkeyidcreated timestamp is within acceptable range (±2 minutes recommended)Signature Algorithms:
The following signature algorithms SHALL be supported:
| Algorithm | Key Type | Description |
|---|---|---|
| ecdsa-p256-sha256 | ECDSA P-256 | Recommended - efficient and secure |
| ecdsa-p384-sha384 | ECDSA P-384 | Higher security level |
| rsa-pss-sha256 | RSA 2048+ | RSA with PSS padding |
| rsa-v1_5-sha256 | RSA 2048+ | RSA with PKCS#1 v1.5 padding (legacy support) |
Security Considerations for HTTP Signatures:
keyid MUST uniquely identify receiver's public key in trust listcreated) to prevent replay attacksImplementations that support the OAuth with SSRAA Option MAY use OAuth 2.0 access tokens for authentication instead of HTTP Message Signatures. This option provides interoperability with systems implementing the HL7 Security for Scalable Registration, Authentication, and Authorization IG (SSRAA).
Preconditions: SSRAA Discovery and Registration
Before an access token can be obtained, the VHL Receiver and VHL Sharer MUST complete SSRAA Discovery and Registration. These steps MUST take place at least once per VHL Receiver and VHL Sharer pair. They MAY take place in advance or just in time.
Discovery (SSRAA Section 2): Given the FHIR Base URL of the VHL Sharer (included in the VHL payload), the VHL Receiver performs UDAP Discovery per Section 2 of the HL7 Security for Scalable Registration, Authentication, and Authorization IG. The VHL Receiver validates that the VHL Sharer supports UDAP and determines the VHL Sharer's UDAP capabilities. If the VHL Receiver accepts the VHL Sharer's capabilities, it proceeds to Registration.
Registration (SSRAA Section 3): The VHL Receiver performs UDAP Dynamic Client Registration per Section 3 of the HL7 Security for Scalable Registration, Authentication, and Authorization IG. The VHL Receiver uses the X.509 certificate it obtained from the trust community PKI to register with the VHL Sharer and obtain a client ID. This client ID is required when requesting OAuth access tokens.
Option Requirements:
When both VHL Receiver and VHL Sharer support the OAuth with SSRAA Option:
Step 1: Obtain Access Token
POST /oauth/token HTTP/1.1
Host: authorization-server.example.org
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&scope=system/List.r system/DocumentReference.r system/Binary.r
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJlY2VpdmVyLWtleS0xMjMifQ.eyJpc3MiOiJodHRwczovL3ZobC1yZWNlaXZlci5leGFtcGxlLm9yZyIsInN1YiI6Imh0dHBzOi8vdmhsLXJlY2VpdmVyLmV4YW1wbGUub3JnIiwiYXVkIjoiaHR0cHM6Ly9hdXRob3JpemF0aW9uLXNlcnZlci5leGFtcGxlLm9yZyIsImV4cCI6MTczNTY4OTkwMCwiaWF0IjoxNzM1Njg5NjAwLCJqdGkiOiJyYW5kb20tdW5pcXVlLWlkIn0.signature-here
JWT Client Assertion:
{"alg":"RS256","typ":"JWT","x5c":["<base64-encoded-client-cert>","<base64-encoded-intermediate>"]}
x5c: The receiver's X.509 certificate (and optionally the full chain) from the trust community PKI, per the HL7 Security for Scalable Registration, Authentication, and Authorization IGiss: Client ID assigned to the VHL Receiver during SSRAA Registration (same as sub)sub: Client ID assigned to the VHL Receiver during SSRAA Registration (same as iss)aud: Authorization server token endpointexp: Expiration time (typically 5 minutes from iat)iat: Issued at timejti: Unique identifier for this JWT (prevents replay)extensions: An object containing an hl7-b2b member with the business-to-business identity context, per Section 5.2.1 of the HL7 Security for Scalable Registration, Authentication, and Authorization IGx5c headerToken Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGhvcml6YXRpb24tc2VydmVyLmV4YW1wbGUub3JnIiwic3ViIjoiaHR0cHM6Ly92aGwtcmVjZWl2ZXIuZXhhbXBsZS5vcmciLCJleHAiOjE3MzU2OTMyMDAsImlhdCI6MTczNTY4OTYwMCwic2NvcGUiOiJzeXN0ZW0vTGlzdC5yZWFkIHN5c3RlbS9Eb2N1bWVudFJlZmVyZW5jZS5yZWFkIHN5c3RlbS9CaW5hcnkucmVhZCJ9.token-signature-here",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "system/List.r system/DocumentReference.r system/Binary.r"
}
Step 2: Retrieve Manifest with Token
POST /List/_search HTTP/1.1
Host: vhl-sharer.example.org
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/fhir+json
_id=abc123def456&code=folder&status=current&patient.identifier=urn%3Aoid%3A2.16.840.1.113883.2.4.6.3%7CPASSPORT123&_include=List%3Aitem&recipient=Dr.+Smith+Hospital&passcode=user-pin&embeddedLengthMax=10000
OAuth Process:
OAuth Token Requirements:
client_credentialsprivate_key_jwt (JWT client assertion)system/List.r - Read List resourcessystem/DocumentReference.r - Read DocumentReference resourcessystem/Binary.r - Read Binary resources (document content)Security Considerations for OAuth:
jti claim SHOULD be checked to prevent replay attacksThe VHL Receiver SHALL:
application/x-www-form-urlencoded/List/_search endpoint at VHL Sharer's base URLapplication/x-www-form-urlencodedapplication/fhir+json_include was requested:
The VHL Receiver MAY:
Upon receiving Retrieve Manifest Request, the VHL Sharer SHALL:
keyid from Signature-Input headerkeyidcreated timestamp is within acceptable range (±2 minutes)_include=List:item parameter present:
_include parameter_include used:
The VHL Sharer MAY:
Supported Search Parameters:
Per the VHL Sharer Server Capability Statement, the VHL Sharer SHALL support:
_id (token) - Requiredcode (token) - Requiredstatus (token) - Requiredpatient (reference) OR patient.identifier (chained search on the patient reference parameter, token) - At least one requiredThe VHL Sharer that supports the Include DocumentReference Option SHALL additionally support:
_include=List:item (special)The VHL Sharer SHOULD support:
identifier (token) - Business identifier for ListError Responses:
| HTTP Status | Condition | OperationOutcome.issue.code |
|---|---|---|
| 400 Bad Request | Malformed request or missing required parameters | invalid |
| 401 Unauthorized | Signature verification failed, token invalid, or receiver not in trust list | security |
| 403 Forbidden | VHL expired, revoked, or doesn't authorize documents | forbidden |
| 404 Not Found | List resource with specified _id not found | not-found |
| 422 Unprocessable Entity | Invalid passcode or passcode required but not provided | invalid |
| 429 Too Many Requests | Rate limit exceeded | throttled |
| 500 Internal Server Error | Server-side error during processing | exception |
Example Error Response:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "security",
"diagnostics": "HTTP signature verification failed: signature does not match"
}
]
}
This message is sent when the VHL Sharer has successfully authenticated the VHL Receiver, authorized the VHL, and retrieved the requested document manifest.
The response is a FHIR Bundle of type "searchset" containing:
_include=List:item was used and supported (search.mode="include")Bundle Structure:
{
"resourceType": "Bundle",
"type": "searchset",
"total": 5,
"link": [
{
"relation": "self",
"url": "https://vhl-sharer.example.org/List/_search?_id=abc123def456&code=folder&status=current&patient.identifier=urn:oid:2.16.840.1.113883.2.4.6.3|PASSPORT123&_include=List:item"
}
],
"entry": [
{
"fullUrl": "https://vhl-sharer.example.org/List/abc123def456",
"resource": {
"resourceType": "List",
"id": "abc123def456",
"status": "current",
"mode": "working",
"code": {
"coding": [
{
"system": "https://profiles.ihe.net/ITI/MHD/CodeSystem/MHDlistTypes",
"code": "folder"
}
]
},
"subject": {
"identifier": {
"system": "urn:oid:2.16.840.1.113883.2.4.6.3",
"value": "PASSPORT123"
}
},
"date": "2024-01-15T10:30:00Z",
"entry": [
{
"item": {
"reference": "DocumentReference/doc001"
}
},
{
"item": {
"reference": "DocumentReference/doc002"
}
},
{
"item": {
"reference": "DocumentReference/doc003"
}
},
{
"item": {
"reference": "DocumentReference/doc004"
}
}
]
},
"search": {
"mode": "match"
}
},
{
"fullUrl": "https://vhl-sharer.example.org/DocumentReference/doc001",
"resource": {
"resourceType": "DocumentReference",
"id": "doc001",
"status": "current",
"type": {
"coding": [
{
"system": "http://loinc.org",
"code": "34133-9",
"display": "Summarization of Episode Note"
}
]
},
"subject": {
"identifier": {
"system": "urn:oid:2.16.840.1.113883.2.4.6.3",
"value": "PASSPORT123"
}
},
"date": "2024-01-15T09:00:00Z",
"content": [
{
"attachment": {
"contentType": "application/pdf",
"url": "https://vhl-sharer.example.org/Binary/doc001-content"
}
}
]
},
"search": {
"mode": "include"
}
},
{
"fullUrl": "https://vhl-sharer.example.org/DocumentReference/doc002",
"resource": {
"resourceType": "DocumentReference",
"id": "doc002"
},
"search": {
"mode": "include"
}
},
{
"fullUrl": "https://vhl-sharer.example.org/DocumentReference/doc003",
"resource": {
"resourceType": "DocumentReference",
"id": "doc003"
},
"search": {
"mode": "include"
}
},
{
"fullUrl": "https://vhl-sharer.example.org/DocumentReference/doc004",
"resource": {
"resourceType": "DocumentReference",
"id": "doc004"
},
"search": {
"mode": "include"
}
}
]
}
Key Elements:
Bundle.type: Always "searchset"Bundle.total: Total number of matching resources (List + included DocumentReferences)Bundle.entry[].search.mode:
_include parameterThe VHL Receiver SHALL:
The VHL Receiver MAY:
Secure transport is required for all communications in this transaction. Implementations SHALL comply with the IHE ATNA Profile (ITI TF-1: Section 9) for transport security requirements
All implementations SHALL support HTTP Message Signatures per RFC 9421:
@method, @path, @authority, content-type, content-digestkeyid MUST uniquely identify receiver's public key in trust listImplementations that support OAuth with SSRAA Option SHALL:
jti claim to prevent replay attacksVHL Sharer MUST validate VHL before returning documents:
Both VHL Receiver and VHL Sharer SHALL:
keyid (HTTP signatures) or the client key (OAuth JWT) to identify the client's keyBoth VHL Receiver and VHL Sharer SHOULD log:
VHL Sharer SHOULD implement rate limiting:
When VHL is passcode-protected (P flag):