How to build and test a Questionnaire in Aidbox Forms Builder
Two ways: create from scratch or convert PDF
16 cells · updated Feb 4, 2025
Introduction
Aidbox Forms allows you to create forms based on the FHIR SDC spec, store them as FHIR Questionnaire resources, and extract data into FHIR QuestionnaireResponse and other FHIR resources in Aidbox for further use.
We’ll demonstrate this using the NCD/CVD Risk Assessment Form as an example.
Create two test patients
Before building the form, create test patients in Aidbox to test and debug the Questionnaire.
POST /
content-type: application/yaml
resourceType: Bundle
type: transaction
entry:
- resource:
resourceType: Patient
gender: male
name:
- given:
- John
family: Doe
birthDate: '1996-05-12'
id: john
request:
method: PUT
url: /Patient/john
- resource:
resourceType: Patient
gender: female
name:
- given:
- Jane
family: Doe
id: jane
birthDate: '1993-09-11'
request:
method: PUT
url: /Patient/janetype: transaction-response
resourceType: Bundle
entry:
- resource:
id: john
name:
- given: [John]
family: Doe
gender: male
birthDate: '1996-05-12'
resourceType: Patient
meta: {lastUpdated: '2025-02-03T01:13:55.776235Z', createdAt: '2025-02-03T01:13:55.776235Z', versionId: '6'}
response: {etag: '6', location: /Patient/john/_history/6, status: '200', lastModified: '2025-02-03T01:13:55.776235Z'}
- resource:
id: jane
name:
- given: [Jane]
family: Doe
gender: female
birthDate: '1993-09-11'
resourceType: Patient
meta: {lastUpdated: '2025-02-03T01:13:57.244057Z', createdAt: '2025-02-03T01:13:57.244057Z', versionId: '7'}
response: {etag: '7', location: /Patient/jane/_history/7, status: '200', lastModified: '2025-02-03T01:13:57.244057Z'}
id: '21'
There are two ways to create a FHIR Questionnaire in Aidbox Forms:
- Create from scratch - Use the UI Form Builder to design a new form. (option A)
- Convert a PDF (paper form) to a Questionnaire – Upload a PDF form and automatically generate a digital version. (option B)
Option A: Create form from scratch with calculated expression, enable when condition and data extraction to Observations
Let's create part of the NCD/CVD Risk Assessment Form
1.. Open Aidbox Forms
2.. Click "Create Template"
3.. Choose "Create in UI Builder"
4.. Click on form title to open Questionnaire settings
5.. Change title to "NCD/CVD Risk Assesment Form"
6.. Create sections:
Create Patient Section
- Add "Group"
- Add "Name" a. Add Text item b. Change text to "Name"
- Add "Gender" a. Add Choice item b. Add two options: male, female
Create BMI section
- Add Group and change name to "Obesity"
- Add "Height"
- Add new Quantity item
- Change text to "Height"
- Change link id to "height"
- Change unit to "cm"
- Add "Weight"
- Add new Quantity item
- Change text to "Weight"
- Change link id to "Weight"
- Change unit to "kg"
- Add BMI
- Add new Decimal item
- Change text to "BMI"
- Set item code to:
system: http://snomed.info/sct code: 60621009 display: Body Mass Index- Change calculated expression to:
(%resource.repeat(item).where(linkId='weight').answer.value.value /
%resource.repeat(item).where(linkId='height').answer.value.value.power(2)) * 10000 ```
- Enable data extraction
- Click on "Extraction" checkbox
- Choose "Extract to Observation"
Create Smoking status section
- Add new Choice item
- Change text to "Smoking Status"
- Change item code to:
system: http://snomed.info/sct code: 365981007 display: Tobacco smoking behavior - finding - Import choice options
- Click "Use ValueSet" under the "Options"
- Click "Use external terminology server"
- Set your terminology server to
https://tx.fhirlab.net/fhir - Search needed valueset "Smoking status"
- Enable data extraction
- Click on "Extraction" checkbox
- Choose "Extract to Observation"
Create Alcohol Intake section
- Add new Choice item
- Change text to "Alcohol intake"
- Add two options:
- Never consumed | never-consumed
- Yes | yes
Create Excessive Alcohol Intake section
- Create new group with name "Excessive Alcohol Intake"
- Add enable when rule. In "Rules" section:
- Click "Enable when" checkbox
- Choose "Conditions"
- Add new rule to show this group when:
answer to "Alcohol Intake" question is "Yes"
Create Excessive Alcohol questions:
For males:
- Add new Choice question
- Change text to "In the past 6 months had 5 drinks in a row"
- Change item code to:
system: http://snomed.info/sct code: 719848005 display: Disorder caused by alcohol - Import Answers from
https://tx.fhirlab.net/fhir(search value set Yes_No) - Add enable when rule:
answer to "Patient gender" is "Male"
- Turn on extraction to Observation
For females:
- Duplicate last question
- Change text to "In the past 6 months had 4 drinks in a row"
- Change enable when rule:
answer to "Patient Gender" is "Female"
Option B: Convert PDF to Questionnaire
Follow these steps to convert a PDF form into a FHIR Questionnaire in Aidbox Forms:
1.. Download the PDF file NCD/CVD Risk Assessment Form
2.. Copy your ChatGPT API key (required for conversion):
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
3.. Open Aidbox Forms
4.. Click "Create Template".
5.. Select "Import Questionnaire".
6.. Upload your PDF file and paste your ChatGPT API key.
7.. Click "Import"—your form will be converted and appear in the Aidbox Forms Builder.
8.. Edit the CVD/NCD Form as needed (see the steps of option A).
You can use any PDF form to go through this process. (e.g., NCD/CVD Risk Assessment Form, Maternal Client Record, or Child Immunization Record).
Test the form and Verify Data Storage
Let's test the form to ensure that rules work correctly and data is saved in Aidbox storage.
1. Get the Questionnaire ID
Run the following SQL query in Aidbox to retrieve the ID of the Questionnaire you just created:
select id, resource#>>'{title}' from Questionnaire
order by cts desc limit 102. Generate the Form Link
Use the $populatelink operation to generate a link to open the form:
POST /fhir/Questionnaire/30048d73-a63b-434c-aadd-6265209d366d/$populatelink
content-type: application/yaml
resourceType: Parameters
parameter:
- name: subject
valueReference:
reference: Patient/john
- name: local
valueBoolean: trueresourceType: Parameters
parameter:
- {name: link, valueUri: 'http://localhost:8080/ui/sdc#/questionnaire-response/111ff2cb-bd1f-4f6c-b8f4-5784929500c9?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJTRENSU0FTaGFyZWRMaW5rSXNzdWVyIiwiZXhwIjoxNzM5MTQ1NjAwLCJvcGVyYXRpb25zIjpbImZoaXItcHJvY2Vzcy1yZXNwb25zZSIsInByb2Nlc3MtcmVzcG9uc2UiXSwicSI6eyJpZCI6IjMwMDQ4ZDczLWE2M2ItNDM0Yy1hYWRkLTYyNjUyMDlkMzY2ZCIsInVybCI6Imh0dHA6Ly9mb3Jtcy5haWRib3guaW8vcXVlc3Rpb25uYWlyZS9jdmQtbmNkLXJpc2stYXNzZXNzbWVudC1mb3JtIiwiY2Fub25pY2FsIjoiaHR0cDovL2Zvcm1zLmFpZGJveC5pby9xdWVzdGlvbm5haXJlL2N2ZC1uY2Qtcmlzay1hc3Nlc3NtZW50LWZvcm0ifSwicXIiOnsiaWQiOiIxMTFmZjJjYi1iZDFmLTRmNmMtYjhmNC01Nzg0OTI5NTAwYzkifX0.dYRtNpvfwBrD89AroKWri9_lwXNM3CJkQRCgogE5zTKtbx-7hgSqvSaZn-gaF_ffAdSZN-3mkc1dmXG0iPK2xlXBuH6LX0wEdE0IPZY9TXWnxR3QgDJIk-QuVkkPyeQV5IUhTWsdtvxnXmtqHOgH4pEO5vRP6e_LIK2sGDrR3UvCA3OxNcUP0X3MSdNi8YjXU_UseXz6AgpB1iCooesAgRETUXr1eKbC3MvxqbBfLa5VqtPinMj3F8kvEuKhkz2nnbC0BzxBieqIHrlrBNJDRfN468hz8ETAUjXXdST3kd7sA1Gkuus7G5vLQxD2yhiDMLpn9e2Czq9c8zBUQ5XQIQ'}
3. Fill out the Form and get the QuestionnaireResponse
1.. Open the Form using the generated link.
2.. Fill out the answers and click "Submit".
3.. Verify that responses were recorded by retrieving the QuestionnaireResponse from Aidbox:
select * from QuestionnaireResponse order by ts desc limit 1| id | ts | cts | txid | status | resource | resource_type |
|---|---|---|---|---|---|---|
| 111ff2cb-bd1f-4f6c-b8f4-5784929500c9 | 2025-02-03T01:48:20Z | 2025-02-03T01:47:53Z | 32 | updated | {"questionnaire":"http://forms.aidbox.io/questionnaire/cvd-ncd-risk-assessment-form","meta":{"createdAt":"2025-02-03T01:47:53.995170Z","versionId":"31","lastUpdated":"2025-02-03T01:48:16.043477Z"},"item":[{"item":[{"text":"Alcohol Intake","answer":[{"value":{"Coding":{"code":"yes","display":"Yes"}}}],"linkId":"3.2"},{"text":"In the past month had 5 drinks in a row","answer":[{"value":{"Coding":{"code":"373066001","system":"http://snomed.info/sct","display":"Yes"}}}],"linkId":"3.3"}],"text":"Smoking and Alcohol Intake","linkId":"3"},{"item":[{"text":"Height","answer":[{"value":{"Quantity":{"unit":"cm","value":180}}}],"linkId":"height"},{"text":"Weight","answer":[{"value":{"Quantity":{"unit":"kg","value":89}}}],"linkId":"weight"},{"text":"BMI","answer":[{"value":{"decimal":{"ib":-1,"rep":"27.469135802469136","tag":"f"}}}],"linkId":"G3CAnFK1"}],"text":"Obesity Assessment","linkId":"4"}],"resourceType":"QuestionnaireResponse","author":{"identifier":{"type":{"coding":[{"code":"UID","system":"urn:system:aidbox","display":"User ID"}]},"value":"38439b9c-54c8-43ea-b4a9-b690abf6801b","system":"http://localhost:8080"}},"status":"completed","id":"111ff2cb-bd1f-4f6c-b8f4-5784929500c9","authored":"2025-02-03T01:48:19.051Z","subject":{"id":"john","resourceType":"Patient"}} | QuestionnaireResponse |
4. Get Observations
Let's see what Observations were created from this QuestionnaireResponse:
GET /fhir/Observation{
"resourceType": "Bundle",
"type": "searchset",
"meta": {
"versionId": "0"
},
"total": 2,
"link": [
{
"relation": "first",
"url": "http://localhost:8080/fhir/Observation?page=1"
},
{
"relation": "self",
"url": "http://localhost:8080/fhir/Observation?page=1"
}
],
"entry": [
{
"resource": {
"meta": {
"lastUpdated": "2025-02-03T01:48:20.770479Z",
"versionId": "33",
"extension": [
{
"url": "ex:createdAt",
"valueInstant": "2025-02-03T01:48:20.770479Z"
}
]
},
"derivedFrom": [
{
"reference": "QuestionnaireResponse/111ff2cb-bd1f-4f6c-b8f4-5784929500c9"
}
],
"resourceType": "Observation",
"effectiveDateTime": "2025-02-03T01:48:19.051Z",
"status": "final",
"id": "1313bd70-9d01-4bdd-8706-02159e6fa6f5",
"code": {
"coding": [
{
"code": "135820002",
"system": "http://snomed.info/sct",
"display": "Not sure of general health"
}
]
},
"valueCodeableConcept": {
"coding": [
{
"code": "373066001",
"system": "http://snomed.info/sct",
"display": "Yes"
}
]
},
"subject": {
"reference": "Patient/john"
}
},
"search": {
"mode": "match"
},
"fullUrl": "http://localhost:8080/Observation/1313bd70-9d01-4bdd-8706-02159e6fa6f5",
"link": [
{
"relation": "self",
"url": "http://localhost:8080/Observation/1313bd70-9d01-4bdd-8706-02159e6fa6f5"
}
]
},
{
"resource": {
"meta": {
"lastUpdated": "2025-02-03T01:48:20.770479Z",
"versionId": "34",
"extension": [
{
"url": "ex:createdAt",
"valueInstant": "2025-02-03T01:48:20.770479Z"
}
]
},
"derivedFrom": [
{
"reference": "QuestionnaireResponse/111ff2cb-bd1f-4f6c-b8f4-5784929500c9"
}
],
"valueQuantity": {
"value": 27.469135802469136
},
"resourceType": "Observation",
"effectiveDateTime": "2025-02-03T01:48:19.051Z",
"status": "final",
"id": "bd21d14d-b8aa-44c5-8ad5-04ff5a3e5c98",
"code": {
"coding": [
{
"code": "181195007",
"system": "http://snomed.info/sct",
"display": "Entire nose"
}
]
},
"subject": {
"reference": "Patient/john"
}
},
"search": {
"mode": "match"
},
"fullUrl": "http://localhost:8080/Observation/bd21d14d-b8aa-44c5-8ad5-04ff5a3e5c98",
"link": [
{
"relation": "self",
"url": "http://localhost:8080/Observation/bd21d14d-b8aa-44c5-8ad5-04ff5a3e5c98"
}
]
}
]
}Final
Using Aidbox Forms, we successfully created the NCD/CVD Risk Assessment Form with calculated expressions and Observation-based extraction.
We verified that:
- The form works as expected.
- Data is stored in Aidbox as a QuestionnaireResponse resource.
- Extracted data is saved in Observation resources.
The form is now ready for use and integration into clinical workflows. Here is the final NCD/CVD Risk Assessment Form — you can upload it to test.