PRO-CTCAE captures four attributes per symptom item and the resulting data has to land in FHIR Observations that the sponsor's analysis pipeline can query at each cycle boundary. The wire format is straightforward on paper. The interesting work is where the QuestionnaireResponse gets converted, how the cycle context gets attached, and how a partial completion is represented cleanly. This walkthrough covers a working pattern that sits inside a FHIR-native runtime.
Step 1: Model the Item as a Group
Each PRO-CTCAE item covers up to four attributes: frequency, severity, interference, and presence. In an SDC Questionnaire, that is one group with up to four child items. Skip logic drops the severity, frequency, and interference questions when presence is answered "Never." The linkId scheme should encode the item code plus the attribute, so a downstream extractor can walk the response tree deterministically.
Step 2: Attach Encounter and Cycle Context
The QuestionnaireResponse has to reference the Encounter that represents the cycle boundary. Cycle 1 day 1 and cycle 1 day 8 are separate Encounters even if the underlying study visit is close in time. Without that linkage, the extracted Observations lose the temporal structure that any decent oncology analysis depends on. A subject reference to the Patient and an encounter reference to the cycle-boundary Encounter cover it.
Step 3: Run the Extraction to Observation
The SDC ExtractDefinition mechanism takes the QuestionnaireResponse and emits one Observation per attribute per item. The LOINC code identifies the PRO-CTCAE item (the NCI has published LOINC bindings for the released item set). The valueCodeableConcept carries the answer coding. Delivery channels are usually opinionated: Force Therapeutics and PatientIQ bake in ortho-specific templates, while general-purpose SDC engines like Formbox let a study compose PRO-CTCAE from a shared Questionnaire catalog and reuse the extraction across SMS, email, and portal without rewriting the extractor per channel.
Step 4: Handle Partial Completions Deterministically
A patient who answers presence and severity but skips interference is not an error. The Observation for the missing attribute either does not get created, or it gets created with dataAbsentReason=asked-declined. Pick one policy and enforce it in the extractor. Analytics teams downstream can handle either, but they cannot handle a mix. This is where most first-pass pipelines quietly break.
Step 5: Bundle the Observations for the Cycle
The output for one PRO-CTCAE administration is a batch Bundle of Observations, all pointing at the same Encounter. Post it as a transaction so the whole cycle-boundary payload either lands or does not. Individual Observation POSTs create windows where analytics sees half a symptom item, which is worse than seeing none.
Teams that want to sanity-check the extraction contract before wiring the runtime can drop the Questionnaire into form-builder.aidbox.app, answer the items in the browser, and inspect the raw QuestionnaireResponse before writing the extraction logic against it.
For adjacent walkthroughs, FHIR Questionnaire vs custom web forms for wellness clinic intake covers the SDC vs custom trade-off at the schema level, and 7 FHIR form builders that handle physical therapy outcome surveys covers the repeated-measure delivery patterns that carry over to oncology.
The rest of the FHIR forms and SDC reference covers the surrounding SDC extraction and Observation-modeling territory.
PRO-CTCAE data quality lives or dies at the extraction step. Once the schema is settled and the cycle context is bound, the rest of the analysis pipeline stays boring, which is the state you want.








