Skip to main content
Version: 9.2.0

Run view

This operation executes a ViewDefinition against FHIR data and returns the results as tabular data. This implementation follows the SQL on FHIR specification.

Endpoint

POST [base]/$viewdefinition-run

Parameters

NameCardinalityTypeDescription
viewResource1..1ResourceThe ViewDefinition resource.
_format0..1stringOutput format. Accepts application/x-ndjson (default) or text/csv.
header0..1booleanInclude header row in CSV output. Defaults to true.
_limit0..1integerMaximum number of rows to return.
patient0..*idFilter to resources for the specified patient(s).
group0..*idFilter to resources for patients in the specified Group(s).
_since0..1instantOnly include resources where meta.lastUpdated is at or after this time.
resource0..*stringInline FHIR resources as JSON strings. When provided, these are used instead of the server's stored data.

Request format

The operation accepts a FHIR Parameters resource with the ViewDefinition passed as a nested resource:

POST [base]/$viewdefinition-run HTTP/1.1
Content-Type: application/fhir+json
Accept: application/x-ndjson

{
"resourceType": "Parameters",
"parameter": [
{
"name": "viewResource",
"resource": {
"resourceType": "ViewDefinition",
"name": "patient_demographics",
"resource": "Patient",
"status": "active",
"select": [
{
"column": [
{
"name": "id",
"path": "id"
}
]
},
{
"column": [
{
"name": "family",
"path": "name.first().family"
}
]
},
{
"column": [
{
"name": "given",
"path": "name.first().given.first()"
}
]
}
]
}
}
]
}

Response formats

The response uses HTTP chunked transfer encoding, allowing clients to process results incrementally as they arrive rather than waiting for the complete response. This is particularly useful for large result sets.

NDJSON

When _format is application/x-ndjson (the default), the response is newline-delimited JSON with one row per line:

Content-Type: application/x-ndjson

{"id":"patient-1","family":"Smith","given":"John"}
{"id":"patient-2","family":"Jones","given":"Jane"}

CSV

When _format is text/csv, the response is comma-separated values:

Content-Type: text/csv

id,family,given
patient-1,Smith,John
patient-2,Jones,Jane

Set header=false to exclude the header row.

ViewDefinition structure

A ViewDefinition specifies which resource type to query and how to extract columns. Here is a more readable example:

{
"resourceType": "ViewDefinition",
"name": "patient_demographics",
"resource": "Patient",
"status": "active",
"select": [
{
"column": [
{
"name": "id",
"path": "id"
}
]
},
{
"column": [
{
"name": "family",
"path": "name.first().family"
}
]
},
{
"column": [
{
"name": "given",
"path": "name.first().given.first()"
}
]
},
{
"column": [
{
"name": "gender",
"path": "gender"
}
]
},
{
"column": [
{
"name": "birth_date",
"path": "birthDate"
}
]
}
]
}

The path values use FHIRPath expressions to extract data from resources.

Inline resources

The resource parameter allows you to execute a ViewDefinition against provided FHIR resources instead of the server's stored data. This is useful for testing ViewDefinitions or processing resources without importing them.

{
"resourceType": "Parameters",
"parameter": [
{
"name": "viewResource",
"resource": {
"resourceType": "ViewDefinition",
"...": "..."
}
},
{
"name": "resource",
"valueString": "{\"resourceType\":\"Patient\",\"id\":\"test-1\",\"name\":[{\"family\":\"Smith\"}]}"
},
{
"name": "resource",
"valueString": "{\"resourceType\":\"Patient\",\"id\":\"test-2\",\"name\":[{\"family\":\"Jones\"}]}"
}
]
}

Filtering

Patient filter

Use the patient parameter to restrict results to resources associated with specific patients:

{
"resourceType": "Parameters",
"parameter": [
{
"name": "viewResource",
"resource": {
"resourceType": "ViewDefinition",
"...": "..."
}
},
{
"name": "patient",
"valueId": "patient-123"
},
{
"name": "patient",
"valueId": "patient-456"
}
]
}

Group filter

Use the group parameter to restrict results to resources for patients who are members of the specified Group:

{
"resourceType": "Parameters",
"parameter": [
{
"name": "viewResource",
"resource": {
"resourceType": "ViewDefinition",
"...": "..."
}
},
{
"name": "group",
"valueId": "cohort-study-group"
}
]
}

Time filter

Use _since to only include resources updated after a specific time:

{
"resourceType": "Parameters",
"parameter": [
{
"name": "viewResource",
"resource": {
"resourceType": "ViewDefinition",
"...": "..."
}
},
{
"name": "_since",
"valueInstant": "2024-01-01T00:00:00Z"
}
]
}

Python example

The following Python script demonstrates the view run operation.

Run the script using uv:

uv run view_run_client.py

View run client

#!/usr/bin/env python3
# /// script
# requires-python = ">=3.10"
# dependencies = ["requests"]
# ///
"""Demonstrates the $viewdefinition-run operation."""

import json
import requests

BASE_URL = "https://pathling.example.com/fhir"


def create_patient_view():
"""Create a ViewDefinition for Patient demographics."""
return {
"resourceType": "ViewDefinition",
"name": "patient_demographics",
"resource": "Patient",
"status": "active",
"select": [
{"column": [{"name": "id", "path": "id"}]},
{"column": [{"name": "family", "path": "name.first().family"}]},
{"column": [
{"name": "given", "path": "name.first().given.first()"}]},
{"column": [{"name": "gender", "path": "gender"}]},
{"column": [{"name": "birth_date", "path": "birthDate"}]},
],
}


def run_view(view_definition, output_format="ndjson", limit=None):
"""Execute a ViewDefinition and return the results."""
url = f"{BASE_URL}/$viewdefinition-run"

# Build FHIR Parameters resource.
parameters = {
"resourceType": "Parameters",
"parameter": [
{"name": "viewResource", "resource": view_definition}
],
}

if output_format == "csv":
parameters["parameter"].append(
{"name": "_format", "valueString": "text/csv"}
)
else:
parameters["parameter"].append(
{"name": "_format", "valueString": "application/x-ndjson"}
)

if limit:
parameters["parameter"].append(
{"name": "_limit", "valueInteger": limit}
)

# Set Accept header based on format.
accept = "text/csv" if output_format == "csv" else "application/x-ndjson"

headers = {
"Content-Type": "application/fhir+json",
"Accept": accept,
}

response = requests.post(url, json=parameters, headers=headers, stream=True)
response.raise_for_status()

return response


def run_view_with_inline_resources(view_definition, resources):
"""Execute a ViewDefinition against inline resources."""
url = f"{BASE_URL}/$viewdefinition-run"

parameters = {
"resourceType": "Parameters",
"parameter": [
{"name": "viewResource", "resource": view_definition},
{"name": "_format", "valueString": "application/x-ndjson"},
],
}

# Add inline resources.
for resource in resources:
parameters["parameter"].append(
{"name": "resource", "valueString": json.dumps(resource)}
)

headers = {
"Content-Type": "application/fhir+json",
"Accept": "application/x-ndjson",
}

response = requests.post(url, json=parameters, headers=headers, stream=True)
response.raise_for_status()

return response


def main():
"""Execute the view run operation."""
view = create_patient_view()

print("Running ViewDefinition against server data...")
print("-" * 50)

response = run_view(view, output_format="ndjson", limit=10)

for line in response.iter_lines(decode_unicode=True):
if line:
row = json.loads(line)
print(
f"Patient: {row.get('id')} - {row.get('given')} {row.get('family')}")

print("-" * 50)
print("\nRunning ViewDefinition with inline resources...")
print("-" * 50)

# Test with inline resources.
test_patients = [
{
"resourceType": "Patient",
"id": "inline-1",
"name": [{"family": "Smith", "given": ["John"]}],
"gender": "male",
"birthDate": "1980-01-15",
},
{
"resourceType": "Patient",
"id": "inline-2",
"name": [{"family": "Jones", "given": ["Jane"]}],
"gender": "female",
"birthDate": "1990-06-20",
},
]

response = run_view_with_inline_resources(view, test_patients)

for line in response.iter_lines(decode_unicode=True):
if line:
row = json.loads(line)
print(
f"Patient: {row.get('id')} - {row.get('given')} {row.get('family')}")

print("-" * 50)
print("Done!")


if __name__ == "__main__":
main()