Skip to navigation

Filling a Questionnaire

Send a FHIR R4 Questionnaire, get back a QuestionnaireResponse

A questionnaire job fills a form you define from one clinical document. You send any FHIR R4 Questionnaire and receive a FHIR R4 QuestionnaireResponse that answers it.

Submitting

{
"type": "questionnaire",
"document": { "text": "SURGICAL PATHOLOGY REPORT\nSpecimen: shave biopsy, right forearm.\n…" },
"questionnaire": {
"resourceType": "Questionnaire",
"url": "https://example.org/Questionnaire/skin-biopsy",
"status": "active",
"title": "Skin biopsy",
"item": [
{ "linkId": "dx", "text": "Diagnosis", "type": "string" },
{ "linkId": "lat", "text": "Laterality", "type": "choice",
"answerOption": [
{ "valueCoding": { "system": "http://snomed.info/sct", "code": "7771000", "display": "Left" } },
{ "valueCoding": { "system": "http://snomed.info/sct", "code": "24028007", "display": "Right" } }
] },
{ "linkId": "pni", "text": "Perineural invasion", "type": "choice",
"answerOption": [
{ "valueCoding": { "code": "pni.absent", "display": "Not identified" } },
{ "valueCoding": { "code": "pni.present", "display": "Present" } }
],
"item": [
{ "linkId": "pni.nerve", "text": "Largest nerve involved (mm)", "type": "decimal",
"enableWhen": [ { "question": "pni", "operator": "=",
"answerCoding": { "code": "pni.present" } } ] }
] }
]
}
}

The item text is what the document is searched for, so write it as a clinician would read it. A group’s text gives context to the items inside it: “Size” in a “Margins” group is understood as the margin size.

What is supported

Answer types

Item typeAnswer
string, textA short answer in the document’s own words, qualifiers and units included (“Less than 10 mL”)
decimal, integerA number. A questionnaire-unit extension tells the service which unit you want, and minValue / maxValue are applied as limits
quantityA valueQuantity: the number plus your questionnaire-unit (with its UCUM system and code when you give them)
date, dateTimeYYYY-MM-DD when the document gives a full date
booleantrue or false
groupStructure and context: a group’s text gives meaning to the items inside it

Choice lists

Coded items (choice, open-choice, and the R5 spelling coding) are answered only from your list: the answer is constrained to your options, and a code you did not define never appears in the response. When the document addresses an item but what it says is not on your list, the item is normally left unanswered rather than given the nearest option.

The list can be given in any of these ways:

  • Inline answerOptions: codings, or valueString, valueInteger, valueDate or valueTime options. The answer echoes the option exactly, with its own type. R5 option lists on string, integer, date and time items work the same way.
  • A ValueSet contained in the Questionnaire, referenced as "#id". Its codes can be enumerated (compose, with exclude honoured) or already expanded (expansion.contains, nested groupings allowed):
{
"resourceType": "Questionnaire",
"contained": [
{ "resourceType": "ValueSet", "id": "smoking",
"compose": { "include": [ { "system": "http://loinc.org", "concept": [
{ "code": "LA18976-3", "display": "Current every day smoker" },
{ "code": "LA15920-4", "display": "Former smoker" },
{ "code": "LA18978-9", "display": "Never smoker" } ] } ] } } ],
"item": [
{ "linkId": "smk", "text": "Tobacco smoking status", "type": "choice",
"answerValueSet": "#smoking" } ]
}

An external value set (for example https://fhir.loinc.org/ValueSet/LL2201-3), one defined by a rule (a filter), or a contained one with more than 200 codes is not expanded: the item is answered as free text. Give such options inline or as a contained, enumerated ValueSet.

Some lists also accept answers that are not on them:

ListAnswer when no option fits
open-choice, or R5 answerConstraint: optionsOrStringThe document’s own words, as a valueString
R5 answerConstraint: optionsOrTypeA value of the item’s type; for a coded item, a Coding with a display and no code
A list whose only options are placeholders (for example only “N/A”)The value as the document states it (a named assistant, say); “None” still maps to the list’s own “N/A”

Form logic

  • enableWhen with every operator (exists, =, !=, >, <, >=, <=), against coded, string, number and boolean answers, and enableBehavior. Items your logic disables are left unanswered.
  • Implied controls. When an item is gated on a yes/no control (“Eye opening not testable” = false) and the document answers the item, the control is recorded too: an eye response was observed, so eye opening was testable. Without it, FHIR’s rules would hide the answered item.
  • repeats: one answer per value; a repeating group gives one item per occurrence (one per procedure, say). A value stated once (a single CPT code, for example) is not repeated into later occurrences.

Scores

A score defined with an SDC calculatedExpression that sums the weights of the options chosen is calculated from those options, not estimated. Weights come from itemWeight or ordinalValue on your options; both common ways of writing the expression are recognised:

{ "linkId": "gcs.total", "text": "GCS total", "type": "integer", "readOnly": true,
"extension": [ { "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression",
"valueExpression": { "language": "text/fhirpath",
"expression": "%resource.repeat(item).where(linkId in ('gcs.eye' | 'gcs.verbal' | 'gcs.motor')).answer.weight().sum()" } } ] }

The total is filled only when every component is answered with a weighted option: a component answered “Not testable” (no weight) leaves it empty. Other kinds of expression are not evaluated.

Instructions on the form

display items and help text are read as instructions for filling the form (“If a component cannot be tested, record ‘Not testable’”). Display items with their own enableWhen, such as an interpretation shown for some scores, are results rather than instructions and are not used.

Items left to your system

These are never filled from the document:

ItemWhy
reference, attachmentA document cannot supply them
Hidden items (questionnaire-hidden)Not for display or entry
Read-only items with a calculatedExpressionComputed: by this service for weighted scores, otherwise by your renderer

Items pre-filled with initial or an SDC initialExpression (an assessment time of now(), say) are answered if the document states them, and never count as missing.

Completeness

status is completed when every required item that your form logic enables is answered, and in-progress otherwise; stats.required_missing lists those items. An in-progress response is a normal, successful result: the document simply does not state everything your form requires.

The result

{
"id": "job_8f2c1d0e9b7a6c5d4e3f2a1b",
"type": "questionnaire",
"questionnaire_response": {
"resourceType": "QuestionnaireResponse",
"status": "completed",
"questionnaire": "https://example.org/Questionnaire/skin-biopsy",
"item": [
{ "linkId": "dx", "text": "Diagnosis",
"answer": [ { "valueString": "Nodular basal cell carcinoma",
"extension": [
{ "url": "https://emtelligent.com/fhir/StructureDefinition/answer-confidence",
"valueDecimal": 1.0 },
{ "url": "https://emtelligent.com/fhir/StructureDefinition/answer-evidence",
"valueString": "Diagnosis: Nodular basal cell carcinoma" } ] } ] },
{ "linkId": "lat", "text": "Laterality",
"answer": [ { "valueCoding": { "system": "http://snomed.info/sct",
"code": "24028007", "display": "Right" },
"extension": [ … ] } ] },
{ "linkId": "pni", "text": "Perineural invasion",
"answer": [ { "valueCoding": { "code": "pni.absent", "display": "Not identified" },
"extension": [ … ] } ] }
]
},
"stats": { "answerable": 4, "answered": 3, "answer_values": 3,
"unmatched_option": 0, "suppressed": 0, "evidence_located": 3,
"required_missing": [] },
"pipeline_version": "2026.10.12-1"
}

Points to note:

  • Unanswered items are omitted. pni.nerve is absent because the document says perineural invasion was not identified, so your enableWhen disables it. An item the document says nothing about is omitted in the same way.
  • questionnaire is set to your Questionnaire’s url, when it has one.
  • status is completed here because the form requires nothing the document leaves out; see Completeness.
  • Extensions on each answer:
Extension URLValue
https://emtelligent.com/fhir/StructureDefinition/answer-confidencevalueDecimal, 0 to 1
https://emtelligent.com/fhir/StructureDefinition/answer-evidencevalueString, the verbatim quote from the document
https://emtelligent.com/fhir/StructureDefinition/answer-derivationvalueCode: calculated (a score from other answers) or implied (a yes/no control implied by an answered item it gates). These answers have no quote of their own

The QuestionnaireResponse carries the evidence quote but not its position. To highlight evidence in the document, find the quote in the text you sent; see Results and evidence.

Stats

stats counts what happened in the fill: answers given, dropped and located, and the required items left unanswered (required_missing). Every field is described in Result format.

Large forms

A document and its Questionnaire are read together. If the two together are too large, the job fails with input_too_large. Split the document, or the Questionnaire, and submit the parts as separate jobs. See Limits for the size limits checked when you submit.