Commure Structured Data Capture API

Release Date

The concept of Structured Data Capture (SDC) is built on top of the FHIR Questionnaire and QuestionnaireResponse resources. Those resources enable the creation of configurable forms that define an optimal data structure for capturing input from users, ideal for data capture.

The idea of SDC offers at least the following benefits:

  1. Advanced dynamic questionnaires including calculated scores, enabling of questions and groups based on complex logic, drop-downs driven by answers to other questions
  2. Support for populating questionnaires from existing clinical data based on the current patient, encounter, etc., including the ability to render the form as HTML or to redirect to a website to complete unanswered items
  3. Support for extracting info from a completed QuestionnaireResponse to generate other FHIR resources such as Observations, MedicationStatements, etc.
  4. Support for completing 'adaptive' questionnaires

Commure is focused on the SDC use cases presented by (2) and (3).

Why use a FHIR Questionnaire and QuestionnaireResponse?

A Questionnaire serves as a kind of schema for producing a QuestionnaireResponse, which holds the results of an answer to a Questionnaire. A Questionnaire can define any number of questions (called items), each of which can collect data of various types and be arranged in groups that make hierarchical sense.

It makes sense to use a Questionnaire when your use case is to store data collected from a user, as they answer some series of (either related or unrelated) questions.

Read More:

What does SDC enable that a Questionnaire and QuestionnaireResponse cannot do alone?

Questionnaires are very flexible FHIR Resources: they can hold as much or as little data as your data entry use case dictates. And this data can be ordered and grouped in a way that makes sense for a user in the relevant context.

Having captured data in this format, it is likely that you will want to translate the arbitrary QuestionnaireResponse items into more meaningful, standalone FHIR resources. That translation process is what Structured Data Capture can facilitate.

When should I use Structured Data Capture?

Structured Data Capture can introduce a lot of overhead and complexity. So the first question worth answering is: do I really need Structured Data Capture?

If your application is not producing data that needs to be interoperable with external systems, you can probably skip Structured Data Capture.

For example:

  • If your users intend to physically print out their QuestionnaireResponses and hand them off to someone to perform clinical work — and the data in those QuestionnaireResponses will never be used by any digital user again — your data doesn't need to be interoperable.
  • If your application is very self-contained — if the Questionnaires ask specific questions to which the answers have no place in the FHIR data model, and no code beyond your application code will have a need to interact with the data being entered — then you probably lose little by leaving your data non-interoperable.

On the other hand, if you are hoping to build an application that is the source of data that is used by other applications in the health systems to which you are deployed, you'll likely want to use Structured Data Capture.

For example: if you have a Questionnaire that asks for a patient's first name and last name, that is likely a valuable piece of information to store in a FHIR Patient - in You can use SDC to perform the transformation of a QuestionnaireResponse.item into that

Opting out of doing SDC on this patient name means that your app will leave the data in only your specific QuestionnaireResponse.item. It is unlikely that other applications will take the time to figure out exactly where this piece of data lives and how to use it. They are more likely to (appropriately) assume that the most up-date information lives in the Patient resource, at

Whether you should adopt SDC in your specific use case can vary based on the scope and long-term intent of your project, so consider it carefully.

Read More:

What parts of SDC does Commure offer?

Commure offers API endpoints that implement the FHIR extended operations $extract and $populate.

$extract exists to take a QuestionnaireResponse as input, and produce a set of other FHIR Resources as output.

Commure's implementation uses definition-based extraction, which means that the mapping of certain Questionnaire items to FHIR Resource fields is encoded in fields (oriented around the definition field) on the Questionnaire itself.

$populate exists to take a Questionnaire and set of other FHIR Resources as input, and output a QuestionnaireResponse that is pre-populated with information from the aforementioned FHIR Resources.

Commure's implementation uses expression-based population, which means that the mapping of those input FHIR Resources to pre-populating specific items in the QuestionnaireResponse is encoded in the corresponding Questionnaire. You can understand what fields get pre-populated with what values by reviewing fields like the questionnaire-initialExpression extension.

Read More:

What architecture/workflow is appropriate for SDC?

A typical flow for using $populate and $extract would look something like the following:

  1. User clicks UI element that is expected to open a form for data entry input
  2. UI fetches a set of FHIR Resources relevant to the data the user is about to enter
  3. UI calls $populate to pre-fill the form with information we already know
  4. User performs data entry on the QuestionnaireResponse
  5. UI POST's the completed QuestionnaireResponse for persistence
  6. UI calls $extract with the completed QuestionnaireResponse
  7. UI submits the extracted resources for persistence

The lion's share of complexity and possibility for issues — given the experimental nature of Commure's SDC tooling — occurs at step 6 and 7. It would be wise to consider decoupling the concerns of capturing QuestionnaireResponse data vs. transforming that captured data into interoperable resources. For example, you could persist the QuestionnaireResponse, and then run an asynchronous job that independently processes completed QuestionnaireResponses through the $extract endpoint.

This asynchronous approach is not always an option. For example, if your application collects information about a patient's name, and then immediately expects the header of the page to update with the newly-input patient's name, it is unlikely that you will want your page header to be querying for the latest QuestionnaireResponse from your app (as opposed to querying directly for the FHIR Patient)

Read More:

References to FHIR Documentation