Form API
Converts Questionnaire to Aidbox SDC Form (Document + Form + Launch + (Finalize))
params:
Param | Description | Type | required? |
---|---|---|---|
url | Link to Questinnaire on public FHIR server | zen/string | no |
resource | Questionnaire resource body | zenbox/resource | no |
options | Additional options | map | no |
optinos.gen-extractions | Generate basic extractions for fields | boolean | no |
optinos.keygen-strategy | Strategy for document keys generation | "text"/"numbers"/"link-id"/"code-or-link-id" | no |
optinos.base-name | Name prefix for all generated zen-symbols and namespace | string | no |
options.key-prefix | Prefix for document keys | zen/string | no |
Request:
POST /rpc
method: aidbox.sdc/convert-questionnaire
params:
options:
gen-extractions: true
resource:
resourceType: Questionnaire
id: 90854-1
url: http://loinc.org/q/90854-1
name: Duke_Anxiety_Depression_Scale
title: Duke Anxiety Depression Scale
status: draft
code:
- system: http://loinc.org
code: 90854-1
display: Duke Anxiety Depression Scale
item:
- linkId: '107153'
text: Final score
type: decimal
Result:
result:
ns: duke-anxiety-depression-scale
filename: duke-anxiety-depression-scale.edn
code: |
{ns duke-anxiety-depression-scale,
import #{aidbox.sdc zenbox fhir hl7-fhir-r4-core.Coding},
DukeAnxietyDepressionScaleDocument
{:zen/tags #{zen/schema aidbox.sdc/doc aidbox.sdc/rules},
:source {:code "90854-1", :system "http://loinc.org"}
:zen/desc "Duke Anxiety Depression Scale",
:type zen/map,
:confirms #{aidbox.sdc/Document},
:keys {:final-score {:linkId "/107153",
:text "Final score",
:type zen/number,
:sdc-type aidbox.sdc/decimal}}},
DukeAnxietyDepressionScaleLayout
{:zen/tags #{aidbox.sdc/Layout aidbox.sdc/rules},
:document DukeAnxietyDepressionScaleDocument,
:engine aidbox.sdc/Hiccup,
:layout {:type aidbox.sdc/col, :children [{:bind [:final-score]}]}},
DukeAnxietyDepressionScaleLaunch
{:zen/tags #{aidbox.sdc/Launch},
:document DukeAnxietyDepressionScaleDocument,
:params {:encounter-id {:type zen/string}},
:populate-engine aidbox.sdc/LispPopulate,
:populate {:author (get-in [:ctx :user]),
:encounter
{:id (get-in [:params :encounter-id]),
:resourceType "Encounter"},
:patient (sql {:select [:#> :resource [:subject]],
:from :Encounter,
:where [:= :id (get-in [:params :encounter-id])]})}},
DukeAnxietyDepressionScaleFinalizeConstraints
{:type zen/map, :zen/tags #{zen/schema}},
DukeAnxietyDepressionScaleFinalize
{:zen/tags #{aidbox.sdc/Finalize zen/schema},
:document DukeAnxietyDepressionScaleDocument,
:profile DukeAnxietyDepressionScaleFinalizeConstraints,
:export-engine aidbox.sdc/LispExport,
:create
[{:template aidbox.sdc/gen-observation-template
:params {:path [:final-score]}}]}
DukeAnxietyDepressionScaleForm
{:zen/tags #{aidbox.sdc/Form},
:title "Duke Anxiety Depression Scale",
:document DukeAnxietyDepressionScaleDocument,
:layout DukeAnxietyDepressionScaleLayout,
:launch DukeAnxietyDepressionScaleLaunch,
:finalize DukeAnxietyDepressionScaleFinalize}}
Converts Aidbox Form to FHIR Questionnaire, optionaly can save it to Questinnaire resource in Aidbox.
As Aidbox Forms is able to express more stuff than Questionnaire can handle - only subset of Forms functionality supported for convertion.
Basically only
Document
and FinalizeConstraints
DSLs are supportedWhat is supported:
Document
structure with questions- nested questions
- repeated questions
- Questions ordering based on natural question order in
Document DSL
- required fields based on
Document DSL
andFinalizeConstraints DSL
- Questionnaire root properties via
Forms DSL
properties
params:
Param | Description | Type | required? |
---|---|---|---|
form | Form symbolic name | string | yes |
format | Format of QR. Aidbox or FHIR | string | yes |
save-to-resource | Save Questionnaire to resource | boolean | no |
opts | | Map | no |
opts.describe-rules* | If true - will add field calculation rule description to QR | boolean | no |
to use include-scores and describe-rules options you need to importaidbox.sdc.extra
namespace in configuration project
Request:
POST /rpc
method: aidbox.sdc/convert-form
params:
form: 'box.sdc.sdc-example/PHQ2PHQ9Form
format: "aidbox"
save-to-resource: true
Result:
result:
resourceType: Questionnaire
title: PHQ2/PHQ9 Depresssion
name: box.sdc.sdc-example/PHQ2PHQ9Form
status: draft
lastReviewDate: '2022-10-10'
contact:
- name: cont1
telecom:
- system: tel
value: 300-00-00
effectivePeriod:
start: '2022-10-10T10:10:10Z'
end: '2022-10-10T10:10:10Z'
description: Base schema for questionnaire(document) definition. Also a resource in DB - SDCDocument
approvalDate: '2022-10-10'
item:
- linkId: misc-yes-no-button
text: 'PHQ-9 Questionnaire: For positive depression screen or follow up'
type: boolean
- linkId: 44258-2
text: Feeling bad about yourself-or that you are a failure or have let yourself or your family down
type: choice
code:
- code: 44258-2
system: http://loinc.org
answerOption:
- value:
Coding:
code: LA6568-5
system: http://loinc.org
display: Not at all
- value:
Coding:
code: LA6569-3
system: http://loinc.org
display: Several days
- value:
Coding:
code: LA6570-1
system: http://loinc.org
display: More than half the days
- value:
Coding:
code: LA6571-9
system: http://loinc.org
display: Nearly every day
- linkId: loinc-LL382-3
text: PHQ-9 Interp-score
type: decimal
code:
- code: LL382-3
system: http://loinc.org
Error:
error:
message: Can't save form to resource: you need specify :fhir/id property on the form
Convert all SDCForms with :fhir/id property to FHIR questionnaire and store them in DB.
params:
Param | Description | Type | required? |
---|---|---|---|
describe-rules* | If true - will add field calculation rule description to Q | boolean | no |
Returns list of pairs [form-name, convertions-result] where convertion result is one of:
- Ok
- {messge: "error message"}
Request:
POST /rpc
method: aidbox.sdc/convert-forms
params:
describe-rules: true
Result:
result:
- - box.sdc.sdc-example/PHQ2PHQ9Form
- ok
- - box.sdc.sdc-example/PHQ2PHQ9Form
- message: '...Something wrong with conversion...'
Generate ZEN namespace with empty Form definition and all relevant layers. You can use this as starting point when you need create custom form from scratch.
Note: rpc doesn't make any changes in filesystem - it just returns template. You then should save it to file manually
params:
Param | Description | Type | required? |
---|---|---|---|
ns | Namespace of form | String | no |
title | Form Title | String | no |
POST /rpc?
method: aidbox.sdc/generate-form-template
params:
ns: 'my.company.forms.my-vitals'
title: 'My first form'
Result:
result:
form-content: |
{ns my.company.forms.my-vitals,
import #{aidbox.sdc zenbox aidbox.sdc.fhir},
MyVitalsDocument
{:zen/tags #{zen/schema aidbox.sdc/doc aidbox.sdc/rules},
:zen/desc "My first form",
:type zen/map,
:confirms #{aidbox.sdc/Document},
:keys {}},
MyVitalsLayout
{:zen/tags #{aidbox.sdc/Layout aidbox.sdc/rules},
:document MyVitalsDocument,
:engine aidbox.sdc/Hiccup,
:layout {:type aidbox.sdc/col, :children []}},
MyVitalsLaunch
{:zen/tags #{aidbox.sdc/Launch},
:document MyVitalsDocument,
:params {:encounter-id {:type zen/string}},
:populate-engine aidbox.sdc/LispPopulate,
:populate
{:author (get-in [:ctx :user]),
:encounter
{:id (get-in [:params :encounter-id]), :resourceType "Encounter"},
:patient (sql {:select [:#> :resource [:subject]],
:from :Encounter,
:where [:= :id (get-in [:params :encounter-id])]})}},
MyVitalsFinalizeConstraints
{:type zen/map, :zen/tags #{zen/schema}},
MyVitalsFinalize
{:zen/tags #{aidbox.sdc/Finalize zen/schema},
:document MyVitalsDocument,
:profile MyVitalsFinalizeConstraints,
:export-engine aidbox.sdc/LispExport,
:create []},
MyVitalsForm
{:zen/tags #{aidbox.sdc/Form},
:title "My first form",
:document MyVitalsDocument,
:layout MyVitalsLayout,
:launch MyVitalsLaunch,
:finalize MyVitalsFinalize}}
Generate Form Layout Definition, based on Document schema.
Note: rpc doesn't make any changes in filesystem - it just returns template. You then should save it to file manually
params:
Param | Description | Type | required? |
---|---|---|---|
document | SDCDocument schema name | symbol | yes |
show-keys | fields to show in layout | vector of strings | no |
if
show-keys
is not given - generate layout for all fields in the document.NOTE: layout fields order will be the same as natural keys order in SDCDocument
POST /rpc?
method: aidbox.sdc/generate-form-layout
params:
document: my.company.forms.my-vitals/MyVitals
show-keys:
- weight
- height
Result:
result: |
{:zen/tags #{aidbox.sdc/Layout aidbox.sdc/rules},
:document my.company.forms.my-vitals/MyVitals,
:engine aidbox.sdc/Hiccup,
:layout
{:type aidbox.sdc/col,
:children
[{:bind [:height]}
{:bind [:weight]}]}}
Error
error:
message: Invalid params
method: aidbox.sdc/generate-form-layout
errors:
- message: No symbol 'my.forms/MyForm found
type: symbol
Generate Form FinalizeConstrains Definition, based on Document schema
Note: rpc doesn't make any changes in filesystem - it just returns template. You then should save it to file manually
params:
Param | Description | Type | required? |
---|---|---|---|
document | SDCDocument schema name | symbol | yes |
required-keys | Required fields | vector of strings | no |
if
required-keys
is not given - all fields are required by default.POST /rpc?
method: aidbox.sdc/generate-form-constraints
params:
document: my.company.forms.my-vitals/MyVitals
required-keys:
- weight
- height
Result:
result: |
{:zen/tags #{zen/schema},
:type zen/map,
:require #{:height :weight}}
Error
error:
message: Invalid params
method: aidbox.sdc/generate-form-layout
errors:
- message: No symbol 'my.forms/MyForm found
type: symbol
Generate Form Finalize Definition with extractions, based on Document schema.
Note: rpc doesn't make any changes in filesystem - it just returns template. You then should save it to file manually
params:
Param | Description | Type | required? |
---|---|---|---|
document | SDCDocument schema name | symbol | yes |
extract-keys | Keys for extraction | vector of strings | no |
profile | name of Finalize Constraint profile. | string/symbol | no |
if
extract-keys
is not given - generate layout for all fields in the document.POST /rpc?
method: aidbox.sdc/generate-form-finalize
params:
document: my.company.forms.my-vitals/MyVitals
profile:
extract-keys:
- weight
- height
Result:
result: |
{:zen/tags #{aidbox.sdc/Finalize zen/schema},
:document box.sdc.sdc-example/VitalsDocument,
:export-engine aidbox.sdc/LispExport,
:create
[{:template aidbox.sdc/gen-observation-template,
:params {:path [:weight]}}
{:template aidbox.sdc/gen-observation-template,
:params {:path [:height]}}]}
Error
error:
message: Invalid params
method: aidbox.sdc/generate-form-layout
errors:
- message: No symbol 'my.forms/MyForm found
type: symbol
Get form related properties.
Properties is a typical map where each key is a property name and value is any JSON value
Properties are stored in two sources:
- in ZEN (properties of Form symbol) - static properties
- in DB (SDCFormMetadata resource) - dynamic properties
You can query
static
, dynamic
or all
form properties.You can manage dynamic properties byadd-form-properties
anddelete-form-properties
RPCs
params:
Param | Description | Type | required? |
---|---|---|---|
form | Form symbolic name | String | yes |
properties | properties type | static/dynamic/all | no |
Request:
POST /rpc?
method: aidbox.sdc/get-form-properties
params:
form: my.company.forms.vitals/Vitals
properties: dynamic
Response:
result:
form: my.company.forms.vitals/Vitals
properties:
in-development: true
Add set of dynamic properties to a form.
Properties is a typical map where each key is a property name and value is any JSON value Dynamic Properties - properties that are stored in DB, inSDCFormMetadata
resource
Given properties will be merged with existed - you can replace old values by this operation.
Returns updated
SDCFormMetadata
resource.params:
Param | Description | Type | required? |
---|---|---|---|
form | Form symbolic name | String | yes |
properties | properties map | map | yes |
Request:
POST /rpc?
method: aidbox.sdc/add-form-properties
params:
form: my.company.forms.vitals/Vitals
properties:
team: surgeons
in-development: true
Result:
Success
result:
id: my.company.forms.vitals/Vitals
resourceType: SDCFormMetadata
properties:
team: surgeons
in-development: true
Delete set of form dynamic properties.
Dynamic Properties - properties that are stored in DB, inSDCFormMetadata
resource
Returns updated
SDCFormMetadata
resource. Returns error when SDCFormMetadata
resource or some of property name is not foundparams:
Param | Description | Type | required? |
---|---|---|---|
form | Form symbolic name | String | yes |
properties | properties names to delete | vector of strings | yes |
Request:
POST /rpc?
method: aidbox.sdc/delete-form-properties
params:
form: my.company.forms.vitals/Vitals
properties:
- team
- in-development
Response:
Success
result:
id: my.company.forms.vitals/Vitals
resourceType: SDCFormMetadata
properties: {}
Error
error:
message: SDCFormMetadata with id = '<resource-id>' is not found
message: There are no such properties [<prop-names>] in FormMetadata with id = '<resource-id>'
Get forms definitions
Response can be narrowed with document Symbol name substring
params:
Param | Description | Type | required? |
---|---|---|---|
q | substring of Form symbolic name | String | no |
include.properties | include-filter for properties match | map | no |
exclude.properties | exclude-filter for properties match | map | no |
- include/exclude properties should be in that shape as you except them in Form definition.
- if property value is a set - then filter specifies elements subset with AND logic
- if property value is a coll - then filter specifies collection matching with strict order and elements counts
- if property value is a map - then filter specifies subset of map structure with searched leaves values
- if property value is a keyword/string/symbol - then filter specifies equal match by stringified property value.
Request:
POST /rpc?
method: aidbox.sdc/get-forms
params:
q: 'Vitals'
include:
properties:
teams: [physician]
in-dev: true
Result
result:
entries:
- form: box.sdc.sdc-example/VitalsForm
title: Vitals Signs
- form: box.sdc.sdc-example/VitalsFormWithoutExtractions
title: Vitals Signs
Get form for given document definition
params:
Param | Description | Type | required? |
---|---|---|---|
form | Form Symbol name | String | yes |
POST /rpc?
method: aidbox.sdc/get-form
params:
form : aidbox.sdc.VitalsForm
Launch form with given launch, prepoluate data, and return enriched with metadata layout.
Param | Description | Type | required? |
---|---|---|---|
form | Form Symbol name | String | yes |
dry-run | Run without saving document in db | boolean | no |
unit-system | Preffered unit system (default: imperial) | String | no |
rules-in-lisp | Return rules as Lisp or AST | boolean | no |
params | Params to launch-context | map | no |
POST /rpc?
method: aidbox.sdc/launch
params:
form: box.sdc.sdc-example/VitalsForm
dry-run: true
params:
encounter-id: enc-1
Result:
Success
result:
form: 'box.sdc.sdc-example/VitalsForm' ;; Form name
title: "MyForm" ;; Form title
version: 1 ;; Internal form version.
document: {} ;; SDCDocument resource
document-def: {} ;; Document zen definition (can be used for UI validations)
layout: {} ;; Enriched layout with document metadata and rules. Used for rendering
layout-def: {} ;; Layout zen definition. (can be used for retrieving additional info from layout engine)
rules: {} ;; merged (and optionally transformed) :sdc/rules from document and layout definitions
rules-order: {} ;; Rules keys in topological sort.
finalize-profile: {} ;; Zen Schema for Finalize Constraints
Error:
error:
message: "Wrong population logic for resource defined"
errors: [{message: "..."}] ;; schema validation errors (zen-style errors)
warnings: ;; failed population logic expressions
- message: "..."
launch-ctx {...} ;; context data of the launch process
localion:
expr: <lisp/expr> ;; failed lisp/expr
Get form for saved document.
Param | Description | Type | required? |
---|---|---|---|
id | Document id | String | yes |
rules-in-lisp | Return rules as Lisp or AST | boolean | no |
POST /rpc?
method: aidbox.sdc/read-document
params:
id: doc-1
Result:
Success
result:
form: 'box.sdc.sdc-example/VitalsForm' ;; Form name
title: "MyForm" ;; Form title
version: 1 ;; Internal form version.
document: {} ;; SDCDocument resource
document-def: {} ;; Document zen definition (can be used for UI validations)
layout: {} ;; Enriched layout with document metadata and rules. Used for rendering
layout-def: {} ;; Layout zen definition. (can be used for retrieving additional info from layout engine)
rules: {} ;; merged (and optionally transformed) :sdc/rules from document and layout definitions
rules-order: {} ;; Rules keys in topological sort.
finalize-profile: {} ;; Zen Schema for Finalize Constraints
Error:
error:
:message "Can't find document"
Save document draft without Finalize Profile validations. Can be used with documents in
draft
, in-progress
, in-amendment
statusesParam | Description | Type | required? |
---|---|---|---|
document | document resource | SDCDocument | yes |
If document in
draft
status - set in-progress
status to it.Request:
POST /rpc?
method: aidbox.sdc/save,
params:
document:
id: doc-1,
patient: {id: pt-1, resourceType: Patient},
encounter: {id: enc-1, resourceType: Encounter},
type: box.sdc.sdc-example/VitalsDocument,
resourceType: SDCDocument,
loinc-59408-5: {value: 97},
author: {id: doc-1, resourceType: User},
loinc-8310-5: {value: 36.6, unit: C},
loinc-8867-4: {value: 72}
Result:
Error
error:
message: Can't be saved in final status: <(completed/canceled/amended)>