FHIR Operation Framework
In addition to the standard API endpoints for creating, reading, and updating resources, FHIR offers a variety of
RPC-like Operation APIs to expose arbitrary functionality as a FHIR API.
Each API endpoint is defined by an OperationDefinition resource,
which provides information about how to call the API and what to expect in response.
Operation Definition
For example, consider the ValueSet/$validate-code operation,
which is summarized below:
OperationDefinition JSON
{
"resourceType": "OperationDefinition",
"url": "http://hl7.org/fhir/OperationDefinition/ValueSet-validate-code",
"status": "active",
"kind": "operation",
// Endpoint configuration
"code": "validate-code",
"resource": ["ValueSet"],
"system": false,
"type": true,
"instance": true,
"parameter": [
// Input Parameters
{
"use": "in",
"name": "url",
"documentation": "Value set canonical URL",
"min": 0,
"max": "1",
"type": "uri"
},
{
"use": "in",
"name": "valueSet",
"documentation": "The value set is provided directly as part of the request",
"min": 0,
"max": "1",
"type": "ValueSet"
},
{
"use": "in",
"name": "code",
"documentation": "The code that is to be validated",
"min": 0,
"max": "1",
"type": "code"
},
{
"use": "in",
"name": "system",
"documentation": "The system for the code that is to be validated",
"min": 0,
"max": "1",
"type": "uri"
},
{
"use": "in",
"name": "display",
"documentation": "The display associated with the code, if provided",
"min": 0,
"max": "1",
"type": "string"
},
{
"use": "in",
"name": "coding",
"documentation": "A coding to validate",
"min": 0,
"max": "1",
"type": "Coding"
},
{
"use": "in",
"name": "codeableConcept",
"documentation": "A full codeableConcept to validate",
"min": 0,
"max": "1",
"type": "CodeableConcept"
},
// Output Parameters
{
"use": "out",
"name": "result",
"documentation": "True if the concept details supplied are valid",
"min": 1,
"max": "1",
"type": "boolean"
},
{
"use": "out",
"name": "message",
"documentation": "Error details, if result = false; otherwise may contain hints and warnings",
"min": 0,
"max": "1",
"type": "string"
},
{
"use": "out",
"name": "display",
"documentation": "A valid display for the concept if the system wishes to display this to a user",
"min": 0,
"max": "1",
"type": "string"
}
]
}
This definition supplies the information needed to correctly call the operation API endpoint:
- All operation requests can be made using the
POSTHTTP method - The
validate-codeoperation is available as type- and instance-level endpoints forValueSetresources, i.e.[baseUrl]/ValueSet/$validate-code[baseUrl]/ValueSet/[id]/$validate-code
- Input parameters are passed via a
Parametersresource in the request body
Invoking an Operation
Given the information from the OperationDefinition, we can construct a request to the operation API endpoint. For
each in parameter, corresponding entries may appear in the request Parameters.parameter array. Value types must
match the OperationDefinition.
Request:
- TypeScript
- cURL
const result = await medplum.post(medplum.fhirUrl('ValueSet', '$validate-code').toString(), {
resourceType: 'Parameters',
parameter: [
{ name: 'url', valueUri: 'http://hl7.org/fhir/ValueSet/condition-severity' },
{ name: 'coding', valueCoding: { system: 'http://snomed.info/sct', code: '255604002' } },
],
});
curl 'https://api.medplum.com/fhir/R4/ValueSet/$validate-code' \
-X POST \
-H "Content-Type: application/fhir+json" \
-H "Authorization: Bearer $MY_ACCESS_TOKEN" \
-d '{"resourceType":"Parameters","parameter":[{"name":"url","valueUri":"http://hl7.org/fhir/ValueSet/condition-severity"},{"name":"coding","valueCoding":{"system":"http://snomed.info/sct","code":"255604002"}}]}'
Response: (200 OK)
{
"resourceType": "Parameters",
"parameter": [
{ "name": "result", "valueBoolean": true },
{ "name": "display", "valueString": "Mild (qualifier value)" }
]
}
Via GET Request
In some cases, it may be simpler to invoke an operation with a GET request and encode the input parameters in the query string of the request URL. For example, the following operation requests are equivalent:
curl 'https://api.medplum.com/fhir/R4/ValueSet/$validate-code' \
-X POST \
-H "Content-Type: application/fhir+json" \
-H "Authorization: Bearer $MY_ACCESS_TOKEN" \
-d '{"resourceType":"Parameters","parameter":[{"name":"url","valueUri":"http://hl7.org/fhir/ValueSet/condition-severity"},{"name":"system","valueUri":"http://snomed.info/sct"},{"name":"code","valueCode":"255604002"}]}'
curl 'https://api.medplum.com/fhir/R4/ValueSet/$validate-code' \
--get \
-H "Authorization: Bearer $MY_ACCESS_TOKEN" \
-d 'url=http://hl7.org/fhir/ValueSet/condition-severity' \
-d 'system=http://snomed.info/sct' \
-d 'code=255604002'
This is possible when the request is idempotent and contains only simple input parameter types, i.e.
- The
OperationDefinitionmust not contain"affectsState": true - The request may only contain
inparameters with a simpletype(one starting with a lower-case letter, likestringorpositiveInt— but notCoding)
Reading the Response
For each out parameter in the response, the typed value(s) are recorded in the Parameters.parameter array. Multiple
values for a given output parameter will appear as multiple entries in the array, not a nested array in the value[x]
field.
Many operations return a specific resource type, instead of the usual Parameters resource. These cases are marked by
a single, required return output parameter with type specifying the returned resource type.
Error Responses
In case of an error, the server will return an HTTP status code in the 4xx-5xx range. The response body will contain
an OperationOutcome resource with details about the error.
For example, if the specified ValueSet could not be found by URL:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error"
"code": "invalid",
"details": {
"text": "ValueSet http://example.com/ValueSet/missing not found"
},
}
]
}
Operation Documentation
Details about the FHIR Operations supported by Medplum server are linked below. For information about other available operations, see the complete list from the FHIR specification.
📄️ Resource $validate
The $validate operation checks whether a FHIR resource conforms to the base specification and any applicable profiles without actually creating or updating it. This is essential for catching data quality issues early, providing real-time feedback in forms, and testing integrations before committing data to the system.
📄️ GraphQL
The FHIR GraphQL API allows you to query and retrieve FHIR resources using GraphQL syntax, enabling precise data fetching with a single request. Unlike traditional REST endpoints that return fixed resource structures, GraphQL lets clients specify exactly which fields and related resources they need, reducing over-fetching and minimizing network round trips.
📄️ ValueSet $expand
The $expand operation returns all codes contained in a ValueSet, making it ideal for populating dropdown menus, typeahead search fields, and code pickers in clinical applications. Instead of storing and managing large code lists client-side, you can dynamically fetch the allowed values for any coded field.
📄️ Patient $everything
The $everything operation retrieves a complete bundle of all resources associated with a patient in a single API call. This provides a comprehensive view of a patient's clinical record-including encounters, observations, medications, conditions, and related resources-without requiring multiple queries.
📄️ Resource $set-accounts
Medplum implements a custom $set-accounts operation to manage account references. This is the recommended way to manage account references for all resources.
📄️ User $update-email
This operation updates both the User resource (for authentication) and optionally the associated profile resource (Patient, Practitioner, or RelatedPerson) with the new email address.
📄️ Bot Execute
Invoke a Medplum Bot using the custom $execute operation.
📄️ Bulk FHIR API
Medplum supports the Bulk FHIR API 2.0.0. The Bulk FHIR API uses Backend Services Authorization.
📄️ Resource $resend
The $resend operation manually triggers subscription notifications for a specific resource. This is invaluable for debugging subscription workflows, recovering from failed notifications, and replaying events during development or after system issues.
📄️ Project $init
The $init operation creates a new Medplum Project with an admin user in a single API call. Projects provide isolated environments for different applications, organizations, or tenants-each with their own users, access policies, and FHIR resources.
📄️ ConceptMap $translate
Code translation enables seamless data exchange between systems that speak different "clinical languages," ensuring that a diagnosis recorded in one system can be understood and processed correctly by another.
📄️ Patient $ccda-export
The $ccda-export operation generates a Consolidated Clinical Document Architecture (C-CDA) document for a patient. C-CDA is the industry-standard XML format for exchanging clinical summaries between healthcare systems, making this operation essential for interoperability and regulatory compliance.
📄️ Measure $evaluate-measure
The $evaluate-measure operation executes a defined clinical quality measure against your patient population and returns aggregated results. This enables healthcare organizations to programmatically calculate quality metrics, track clinical outcomes, and generate reports for regulatory compliance without manual data extraction.
📄️ Resource $expunge
The $expunge operation permanently deletes a resource and all of its history from the database. Unlike a standard FHIR delete (which creates a "tombstone" record by marking it as deleted), expunge completely removes all traces of the resource.
📄️ PlanDefinition $apply
Medplum implements the FHIR $apply operation for PlanDefinition resources.
📄️ Parameters $ai
The $ai operation provides an interface for calling AI language models (like OpenAI's GPT) through Medplum. This operation supports both standard request/response and streaming modes.
📄️ Resource $csv
The $csv operation exports FHIR resources as a CSV (Comma-Separated Values) file, which is useful for exporting data for analysis in spreadsheet applications, reporting tools, or data pipelines.
📄️ AsyncJob $cancel
The $cancel operation allows you to cancel a running asynchronous job. This is useful when you need to stop a long-running operation that is no longer needed.
📄️ ConceptMap $import
The $import operation allows you to import code mappings into a ConceptMap. This is useful for bulk loading terminology mappings from external sources or programmatically adding mappings to an existing ConceptMap.
📄️ ChargeItemDefinition $apply
The $apply operation applies a ChargeItemDefinition resource to a specific ChargeItem, calculating the appropriate pricing based on the definition's property groups and applicability rules.
📄️ Claim $export
The $export operation exports a Claim resource as a CMS-1500 PDF document. This is useful for generating standardized claim forms for healthcare billing.
📄️ ClientApplication $smart-launch
The $smart-launch operation initiates a SMART on FHIR app launch sequence for a ClientApplication. This creates a SmartAppLaunch context resource and redirects the user to the application's launch URI.
📄️ Patient $summary
The $summary operation generates an International Patient Summary (IPS) document for a patient. This creates a comprehensive clinical summary following the IPS Implementation Guide.
📄️ Refresh Reference Display Strings
The $refresh-reference-display operation updates the Reference.display strings within a resource to reflect the
📄️ Project $clone
The $clone operation creates a complete copy of a Medplum project, including all its resources. This is useful for creating test environments, project templates, or migrating projects.
📄️ Resource $graph
The $graph operation fetches all resources related to a given resource as defined by a GraphDefinition. This allows you to retrieve a complete graph of related resources in a single request.
📄️ StructureDefinition $expand-profile
The $expand-profile operation expands a StructureDefinition profile by recursively loading all nested StructureDefinition resources referenced in the profile's element type definitions. This is useful for obtaining a complete set of profiles needed to validate or render resources conforming to a profile.
📄️ Bot Deploy
Medplum Bots can be deployed using the $deploy operation.
📄️ CodeSystem $import
Large standard terminologies like SNOMED CT
📄️ CodeSystem $lookup
The $lookup operation retrieves detailed information about a specific code from a code system. This is essential for applications that need to display human-readable descriptions, validate code properties, or understand the relationships and metadata associated with clinical terminology codes.
📄️ CodeSystem $subsumes
The $subsumes operation tests whether one code is a parent (more general) or child (more specific) of another code within a hierarchical code system. This is crucial for clinical decision support, where you need to determine if a specific diagnosis or procedure falls under a broader category.
📄️ CodeSystem $validate-code
Validating codes at the point of entry is necessary to prevent data quality issues that can cascade through analytics, clinical decision support, and interoperability workflows. Invalid codes can cause workflow failures, incorrect reports, and missed clinical alerts - all of which degrade clinical experiences.
📄️ QuestionnaireResponse $extract
The $extract operation transforms completed questionnaire responses into structured FHIR resources. This bridges the gap between form-based data collection and your clinical data model-automatically converting patient intake forms, assessments, or surveys into Observations, Conditions, Procedures, and other FHIR resources.
📄️ ClientApplication $rotate-secret
The $rotate-secret operation securely rotates client application credentials with zero downtime. It uses a two-phase rotation process: first moving the current secret to a "retiring" state while generating a new primary secret, then later removing the retiring secret—ensuring that active clients aren't immediately locked out during credential updates.
📄️ ValueSet $validate-code
The $validate-code operation checks whether a code is a valid member of a specific ValueSet. Unlike CodeSystem validation (which checks if a code exists anywhere in a code system), ValueSet validation confirms that a code is within the specific subset of codes allowed for a particular use-such as the list of valid allergy severity codes or permitted procedure types.