PROMs instruments are rarely single-answer. PROMIS-29 covers seven domains with four items each. PHQ-9 has nine items plus a computed total. KOOS-JR has seven items and a normalized score. A SDC ExtractDefinition that treats the whole QuestionnaireResponse as a single Observation loses that structure. This guide walks through authoring an ExtractDefinition that emits one Observation per item, a rolled-up score Observation, and preserves the encounter and subject references cleanly.
Step 1: Model the Instrument as a FHIR Questionnaire With Stable linkIds
The extraction contract depends on stable linkIds. Author the Questionnaire so each item in the instrument has a linkId that matches a canonical identifier from the instrument's specification. PHQ-9 items commonly use linkIds phq9-01 through phq9-09 with phq9-total for the score. Bind each Questionnaire.item.code to the LOINC assigned to that item. The extraction step needs this binding to set Observation.code correctly.
Step 2: Attach an sdc-questionnaire-itemExtractionContext
The SDC IG defines the item-level extension sdc-questionnaire-itemExtractionContext that tells the extractor "each answer to this item becomes an Observation of this shape." Attach the extension to each Questionnaire.item that should produce an Observation. The context references a template Observation resource with Observation.code, Observation.category, and any status defaults filled in. The extractor merges the template with the answer at run time.
The pattern rewards discipline. Instruments that document their extraction context alongside their linkIds are portable across SDC runtimes; instruments that rely on runtime heuristics fork per implementation.
Step 3: Author the ExtractDefinition Resource
The ExtractDefinition (implemented as a StructureMap or a bespoke JSON extract resource depending on the runtime) is the object that ties the Questionnaire and the target Observation shape together. A minimal ExtractDefinition for a multi-answer PROMs instrument specifies:
- The source Questionnaire canonical URL and version.
- The target ResourceType (Observation) and profile (LOINC-coded PROMs Observation profile).
- The mapping from each Questionnaire.item to the corresponding Observation.value field, respecting the answer type (valueInteger for PHQ-9 items, valueQuantity for score items).
- The propagation of QuestionnaireResponse.encounter into Observation.encounter and QuestionnaireResponse.subject into Observation.subject.
SDC ExtractDefinition is the standard mechanism; whether the team builds the runtime itself or leans on an engine like Formbox, the extraction contract is the same, which means the ExtractDefinition authored here is a reusable artifact. Authors that want to iterate on the ExtractDefinition against a real Questionnaire before wiring it into a server can use form-builder.aidbox.app as a browser sandbox. For the FHIR conformance and validation hub on this site, the surrounding tooling context is a useful complement.
Step 4: Author the Computed Total Observation
Multi-answer instruments almost always have a computed score. The extraction has two viable patterns for it. Pattern one uses a Questionnaire.item.calculatedExpression to compute the score inside the QuestionnaireResponse itself, and the ExtractDefinition emits the total as one more Observation identical to the item-level ones. Pattern two computes the score at extraction time as a derived Observation.
Pattern one keeps the score visible in the QuestionnaireResponse for user-facing display and is preferable in most cases. Pattern two hides the score from the response but centralises the computation, which suits research settings that recompute scores against updated scoring rules.
Step 5: Validate the Extraction Against a Canonical QuestionnaireResponse
Run a canonical QuestionnaireResponse (one that any real patient submission would resemble) through the extraction and confirm three properties:
- The number of Observations produced matches the expected number for the instrument (nine plus a total for PHQ-9, twenty-nine plus seven domain scores for PROMIS-29, etc.).
- Each Observation.code matches the LOINC binding on the source Questionnaire.item.
- Observation.encounter and Observation.subject resolve to the same references the QuestionnaireResponse had.
Any deviation is a signal that either the Questionnaire binding or the ExtractDefinition is not quite right. Fix it at authoring time rather than in a downstream ETL.
Step 6: Version the ExtractDefinition Alongside the Questionnaire
The ExtractDefinition is a canonical artifact and evolves with the instrument. Version it with the same canonical URL scheme and version identifier as the source Questionnaire. When the instrument is updated (a new PROMs version, a corrected LOINC binding), publish new versions of both together so the extraction contract stays coherent.
The teams that author this way ship extraction pipelines that are boring to operate. The best FHIR profile development tools for Da Vinci IG authoring and best tools for validating Da Vinci PAS submissions pre-production cover adjacent authoring and validation ground. Multi-answer PROMs extraction is fiddly work that repays being done once, correctly.