> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.emtelligent.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.emtelligent.com/_mcp/server.

# Filling a Questionnaire

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

```json
{
  "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 type            | Answer                                                                                                                              |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `string`, `text`     | A short answer in the document's own words, qualifiers and units included ("Less than 10 mL")                                       |
| `decimal`, `integer` | A number. A `questionnaire-unit` extension tells the service which unit you want, and `minValue` / `maxValue` are applied as limits |
| `quantity`           | A `valueQuantity`: the number plus your `questionnaire-unit` (with its UCUM system and code when you give them)                     |
| `date`, `dateTime`   | `YYYY-MM-DD` when the document gives a full date                                                                                    |
| `boolean`            | `true` or `false`                                                                                                                   |
| `group`              | Structure 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 `answerOption`s**: 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):

```json
{
  "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" } ]
}
```

> **Note**
>
> 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:

| List                                                                | Answer when no option fits                                                                              |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `open-choice`, or R5 `answerConstraint: optionsOrString`            | The document's own words, as a `valueString`                                                            |
| R5 `answerConstraint: optionsOrType`                                | A 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:

```json
{ "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:

| Item                                          | Why                                                                       |
| --------------------------------------------- | ------------------------------------------------------------------------- |
| `reference`, `attachment`                     | A document cannot supply them                                             |
| Hidden items (`questionnaire-hidden`)         | Not for display or entry                                                  |
| Read-only items with a `calculatedExpression` | Computed: 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

```json
{
  "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](#completeness).
* **Extensions on each answer**:

| Extension URL                                                        | Value                                                                                                                                                                 |
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `https://emtelligent.com/fhir/StructureDefinition/answer-confidence` | `valueDecimal`, 0 to 1                                                                                                                                                |
| `https://emtelligent.com/fhir/StructureDefinition/answer-evidence`   | `valueString`, the verbatim quote from the document                                                                                                                   |
| `https://emtelligent.com/fhir/StructureDefinition/answer-derivation` | `valueCode`: `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](/formfill/guides/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](/formfill/reference/result-format#stats).

## 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](/formfill/reference/limits) for the size limits checked when you submit.