FHIRbase API

Conformance

fhir_conformance('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns an JSON

Create storage

fhir_create_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns an JSON

Example

Create patient table

SELECT fhir_create_storage('{"resourceType": "Patient"}'::json);

Response:

{  "message": "Table patient was created",  "status": "ok" }

Create all storages

fhir_create_all_storages()

Arguments

Function has no arguments

Returns

Returns an string

Drop storage

fhir_drop_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns an JSON

Drop all storages

fhir_drop_all_storages('{}'::json)

Arguments

Function has no arguments

Returns

Returns an JSON

Describe storage

fhir_describe_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns an JSON

Truncate storage

fhir_truncate_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns an JSON

Create resource

fhir_create_resource('{}'::json)

Arguments

Takes an argument JSON with properties:

  • allowId boolean
  • resource JSON with properties:
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Create patient

SELECT fhir_create_resource('  {    "resource": {      "name": [        {          "given": [            "Smith"          ]        }      ],      "resourceType": "Patient"    }  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-05T16:57:26.202Z",    "versionId": "0a75f4b1-1e15-4628-b1ad-ae8a8730af00"  },  "id": "c6258cdc-1c80-4dda-80d4-6027c2a23ffd",  "name": [    {      "given": [        "Smith"      ]    }  ],  "resourceType": "Patient" }

Create patient with specific id

SELECT fhir_create_resource('  {    "resource": {      "id": "smith",      "resourceType": "Patient"    },    "allowId": true  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-06T13:38:11.910Z",    "versionId": "c112dd87-1f5b-4c2a-a3c0-783e371cc721"  },  "id": "smith2",  "resourceType": "Patient" }

Read resource

fhir_read_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Show patient by id

SELECT fhir_read_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "resourceType": "Patient",  "meta": {    "lastUpdated": "2016-05-06T13:18:20.996Z",    "versionId": "c8da6a21-018f-4646-afbf-dc2e36baaef1",    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "smith" }

Vread resource

fhir_vread_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • versionId string (mandatory)

Returns

Returns Resource JSON

Update resource

fhir_update_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Update patient by id

SELECT fhir_update_resource('  {    "resource": {      "name": [        {          "family": [            "Smith"          ],          "given": [            "John"          ]        }      ],      "id": "smith",      "resourceType": "Patient"    }  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "PUT",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-06T13:46:09.571Z",    "versionId": "946b91ac-b285-4751-9f6f-c6462d0e7465"  },  "name": [    {      "family": [        "Smith"      ],      "given": [        "John"      ]    }  ],  "id": "smith",  "resourceType": "Patient" }

Patch resource

fhir_patch_resource('{}'::json)

Arguments

Takes an argument JSON with properties:

  • patch array (mandatory) contains objects with properties:
  • op string (mandatory)
  • path string (mandatory)
  • value string (mandatory)
  • resource JSON (mandatory) with properties:
  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Patch patient by id

SELECT fhir_patch_resource('  {    "patch": [      {        "value": "Jane",        "path": "\/name\/0\/given\/0",        "op": "replace"      }    ],    "resource": {      "id": "johndoe",      "resourceType": "Patient"    }  } ');

Response:

{  "resourceType": "Patient",  "name": [    {      "family": [        "Doe"      ],      "given": [        "Jane"      ],      "text": "John Doe"    }  ],  "meta": {    "lastUpdated": "2016-05-11T16:12:50.377Z",    "versionId": "3541fd2e-4ca9-4790-9382-41f98c8b9ad7",    "extension": [      {        "valueString": "PUT",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "johndoe" }

Delete resource

fhir_delete_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Mark patient as deleted (i.e. keep history)

SELECT fhir_delete_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "resourceType": "Patient",  "meta": {    "lastUpdated": "2016-05-06T14:10:50.841Z",    "versionId": "a307ff6c-d35d-4cc4-9784-a91865dfa933",    "extension": [      {        "valueString": "DELETE",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "smith" }

Terminate resource

fhir_terminate_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Example

Completely delete patient and its history

SELECT fhir_terminate_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

[  "{\"id\": \"smith\", \"meta\": {\"extension\": [{\"url\": \"fhir-request-method\", \"valueString\": \"POST\"}, {\"url\": \"fhir-request-uri\", \"valueUri\": \"Patient\"}], \"versionId\": \"3074d414-2318-42e4-aebe-f521d0ef1aff\", \"lastUpdated\": \"2016-05-06T14:10:43.186Z\"}, \"resourceType\": \"Patient\"}",  "{\"id\": \"smith\", \"meta\": {\"extension\": [{\"url\": \"fhir-request-method\", \"valueString\": \"DELETE\"}, {\"url\": \"fhir-request-uri\", \"valueUri\": \"Patient\"}], \"versionId\": \"a307ff6c-d35d-4cc4-9784-a91865dfa933\", \"lastUpdated\": \"2016-05-06T14:10:50.841Z\"}, \"resourceType\": \"Patient\"}" ]

Resource history

fhir_resource_history('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Example

Show patient's history

SELECT fhir_resource_history('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "entry": [    {      "resource": {        "resourceType": "Patient",        "meta": {          "lastUpdated": "2016-05-06T13:18:20.996Z",          "versionId": "c8da6a21-018f-4646-afbf-dc2e36baaef1",          "extension": [            {              "valueString": "POST",              "url": "fhir-request-method"            },            {              "valueUri": "Patient",              "url": "fhir-request-uri"            }          ]        },        "id": "smith"      },      "request": {        "url": "Patient",        "method": "POST"      }    }  ],  "type": "history",  "meta": {    "lastUpdated": "2016-05-06T13:46:48.278Z"  },  "total": 1,  "resourceType": "Bundle" }

Resource type history

fhir_resource_type_history('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Search

fhir_search('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Example

Patient search

SELECT fhir_search('{"resourceType": "Patient", "queryString": "name=smith"}');

Response:

{  "entry": [    {      "resource": {        "deceasedBoolean": "N",        "resourceType": "Patient",        "identifier": [          {            "system": "urn:oid:2.16.840.1.113883.4.3.42",            "value": "010107112",            "type": {              "text": "External ID"            }          },          {            "system": "urn:oid:2.16.840.1.113883.4.3.45",            "value": "160923",            "type": {              "text": "Internal ID"            }          },          {            "system": "urn:oid:2.16.840.1.113883.4.3.46",            "value": "160923",            "type": {              "text": "Alternate ID"            }          },          {            "value": "5435435435",            "type": {              "text": "Account number"            }          },          {            "system": "http:\/\/hl7.org\/fhir\/sid\/us-ssn",            "value": "123-22-1111",            "type": {              "text": "Social Security Number"            }          }        ],        "birthDate": "1996-02-16T04:17+03",        "telecom": [          {            "system": "phone",            "value": "090.293.5104 x4116",            "use": "home"          }        ],        "contact": [          {            "address": {              "use": "Mailing Address"            },            "gender": "unknown",            "name": {              "middle": [                "Ms."              ],              "family": [                "Balistreri"              ],              "given": [                "Bartholome"              ],              "text": "JEAN SANDY JACK",              "use": "official"            }          }        ],        "address": [          {            "postalCode": "08928",            "country": "USA",            "state": "MI",            "line": [              "45713 Glennie Loaf",              "Schumm Village"            ],            "city": "Rodriguezville"          }        ],        "gender": "female",        "name": [          {            "middle": [              "Mrs."            ],            "family": [              "Smitham"            ],            "given": [              "Rudy"            ],            "text": "JEAN SANDY JACK"          }        ],        "id": "97af0e81-29fc-4a97-935d-a7909da2c17d"      }    }  ],  "link": [    {      "url": "Patient\/search?name=smith&_page=0",      "relation": "self"    }  ],  "total": 1,  "type": "searchset",  "resourceType": "Bundle" }

Get search SQL

fhir_search_sql('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Example

See generated SQL

SELECT fhir_search_sql('  {    "queryString": "name=smith",    "resourceType": "Patient"  } ');

Response:

[  "SELECT * FROM \"patient\" tbl1     WHERE fhir_extract_as_string(             ( \"tbl1\".\"resource\" )::json,             ( '[\"Patient\",\"name\"]' )::json,             'HumanName'           ) ilike $1     LIMIT $2",  "%^^smith%",  10 ]

Expand valueset

fhir_expand_valueset('{}'::json)

Arguments

Takes an argument JSON with properties:

  • id string (mandatory)
  • filter string

Returns

Returns ValueSet JSON

Analyze storage

fhir_analyze_storage('{}'::json)

Analyze on resource tables to update PostgreSQL statistic

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns an JSON

Index parameter

fhir_index_parameter('{}'::json)

Create index for parameter

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Index order

fhir_index_order('{}'::json)

Creates index for parameter sort

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Unindex parameter

fhir_unindex_parameter('{}'::json)

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Unindex order

fhir_unindex_order('{}'::json)

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an JSON

Explain search

fhir_explain_search('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an integer

Transaction

fhir_transaction('{}'::json)

Arguments

Takes Bundle JSON with properties:

  • resourceType string (mandatory)
  • entry array (mandatory) contains objects with properties:
  • resource JSON (mandatory) with properties:
  • resourceType string (mandatory)
  • request JSON (mandatory) with properties:
  • method string (mandatory)url string (mandatory)

Returns

Returns Bundle JSON

Example

Create practitioner and associated patient

Patient search

SELECT fhir_transaction('  {    "resourceType": "Bundle",    "id": "bundle-transaction-id",    "type": "transaction",    "entry": [      {        "resource": {          "resourceType": "Practitioner"        },        "request": {          "method": "PUT",          "url": "/Practitioner/created-practitioner-id"        }      },      {        "resource": {          "resourceType": "Patient",          "careProvider": [            {              "reference": "/Practitioner/created-practitioner-id"            }          ]        },        "request": {          "method": "PUT",          "url": "/Patient/created-patient-id"        }      },      {        "request": {          "method": "GET",          "url": "/Patient?_id=created-patient-id&_include=careprovider"        }      }    ]  } ');

Response:

{  "resourceType": "Bundle",  "type": "transaction-response",  "entry": [    {      "resourceType": "Practitioner",      "id": "created-practitioner-id",      "meta": {        "versionId": "b6de0892-0aa5-48f3-a645-b833fc4bf0c3",        "lastUpdated": "2016-05-12T12:29:22.412Z",        "extension": [          {            "url": "fhir-request-method",            "valueString": "PUT"          },          {            "url": "fhir-request-uri",            "valueUri": "Practitioner"          }        ]      }    },    {      "resourceType": "Patient",      "careProvider": [        {          "reference": "/Practitioner/created-practitioner-id"        }      ],      "id": "created-patient-id",      "meta": {        "versionId": "ffc1c306-c2bd-472e-916f-d75ba2ce133d",        "lastUpdated": "2016-05-12T12:29:22.414Z",        "extension": [          {            "url": "fhir-request-method",            "valueString": "POST"          },          {            "url": "fhir-request-uri",            "valueUri": "Patient"          }        ]      }    },    {      "resourceType": "Bundle",      "type": "searchset",      "total": 1,      "link": [        {          "relation": "self",          "url": "/Patient?_id=created-patient-id&_include=careprovider&_page=0"        }      ],      "entry": [        {          "resource": {            "id": "created-patient-id",            "meta": {              "extension": [                {                  "url": "fhir-request-method",                  "valueString": "POST"                },                {                  "url": "fhir-request-uri",                  "valueUri": "Patient"                }              ],              "versionId": "ffc1c306-c2bd-472e-916f-d75ba2ce133d",              "lastUpdated": "2016-05-12T12:29:22.414Z"            },            "careProvider": [              {                "reference": "/Practitioner/created-practitioner-id"              }            ],            "resourceType": "Patient"          }        },        {          "resource": {            "id": "created-practitioner-id",            "meta": {              "extension": [                {                  "url": "fhir-request-method",                  "valueString": "PUT"                },                {                  "url": "fhir-request-uri",                  "valueUri": "Practitioner"                }              ],              "versionId": "b6de0892-0aa5-48f3-a645-b833fc4bf0c3",              "lastUpdated": "2016-05-12T12:29:22.412Z"            },            "resourceType": "Practitioner"          }        }      ]    }  ] }

Valueset after changed

fhir_valueset_after_changed('{}'::json)

Arguments

Takes ValueSet JSON with properties:

  • id string (mandatory)

Returns

Returns an JSON

Valueset after deleted

fhir_valueset_after_deleted('{}'::json)

Arguments

Takes ValueSet JSON with properties:

  • id string (mandatory)

Returns

Returns an JSON

Disk usage

fhirbase_disk_usage_top('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns an array

Benchmark

fhir_benchmark('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns an array

Fhir version

fhir_version()

Arguments

Function has no arguments

Returns

Returns version string

Example

SELECT fhir_version();

Response:

1.3.0

Fhirbase version

fhirbase_version()

Arguments

Function has no arguments

Returns

Returns version string

Example

SELECT fhirbase_version();

Response:

1.3.0.13

Fhirbase release date

fhirbase_release_date()

Arguments

Function has no arguments

Returns

Returns datetime string

Example

SELECT fhirbase_release_date();

Response:

1970-12-31T23:59:59Z

Overview

DB Console is a convenient way to interact with your application database.

clojure.lang.LazySeq@6cb560ac

UI Guide

On the right side you can see menu with "History", "Snippets" and "Examples" tabs.

clojure.lang.LazySeq@6cb560ac

Type your sql query on text area and press "Ctrl + Enter" or "Execute" button

clojure.lang.LazySeq@1bded

Query resuls will be show below. Also you can swith result view as "Talbe" or "List"

clojure.lang.LazySeq@1b8bf

Custom DB REST end point

Aidbox has a ability to provide REST endpoint to your postgresql procedures. This feature can be usefull when you need some complex logic on backend.

  • Using DB console create procedure named, for example, sample. This procedure takes 1 arguments as json, and return json object. Procedure in exaple just return params argument.
CREATE OR REPLACE FUNCTION sample(params json) RETURNS json AS $$ return params $$ LANGUAGE plv8;
  • Now your sample procedure is available at POST to URL http:// <boxname>/db/<procedurename>, where body of request was passed as argument to youy procedure
  • Using REST console, lets try execute POST query to your procedure passing simple object
clojure.lang.LazySeq@1baaa
  • Now lets try create more complex procedure, for example, get all users with their id and names
CREATE OR REPLACE FUNCTION sample(params json) RETURNS json AS $$  var sql = "select * from app.users"  var res = plv8.execute(sql)  return res.map(function(x){return {id: x.id, name: x.data.name}}) $$ LANGUAGE plv8

Box Management CLI

Aidbox provides a command-line user interface (CLI) as a means of interacting with boxes where user issues commands to Aidbox in the form of successive lines of text (command lines).

Aidbox Account

First, create an account on https://aidbox.io.

Now you need to install aidbox-cli utility globally. Also you may need to install coffee-script.

$ sudo npm install -g coffee-script
$ sudo npm install -g aidbox-cli
$ aidbox v  
OK: v0.5.9

Logging In and Out

Let's log in your aidbox.io account throught the aidbox-cli utility:

$ aidbox login  
Login: <enter your login>  
Password: <enter your password>  
OK: Auth success

Then try to log out:

$ aidbox logout  
OK: Now you are logged out  
OK: All session data has been removed

Getting Started

In order to start working with Aidbox, you have to do 3 things:

  1. Create a box, which will host your application.
  2. Create an implicit client, on behalf of which deploy and authorization will be performed.
  3. Create users of the box.

Box

box is a command for managing boxes. By means of this command it's possible to create new boxes, view a list of all existing boxes, switch between boxes, delete boxes and so on.

To view a list of all possible subcommands, execute:

$ aidbox box help  box                 -- Display current box  
box new <boxname>   -- Create new box with specified  <boxname>  
box list            -- Display all available boxes  
box use <boxname>   -- Switch current box to <boxname> 

Box Commands

box

Outputs your current box:

$ aidbox box  
OK: Your current box is [boxname]

box new

Creates a new box. After creation of a new box, you will be automatically switched to the newly created box context. It means that all futher operations, such as creating users, clients, deploy, etc will be done in this box.

$ aidbox box new <boxname>  
INFO: Create new box [boxname]  
OK: Box [boxname] has been created  
OK: Current box has been switched to [boxname]

box list

Outputs a list of all available boxes.

$ aidbox box list  
-- Outputs a list of all available boxes with their IDs and hosts. For now it's a raw JSON.

box use

Switches a context of command execution to a specified box.

$ aidbox box use <other-box>  
OK: Current box has been switched to box [other-box]

deploy

deploy command deploys your application to a box. By default it deploys content of the dist folder in the root of your application. You can specify the folder to be depoyed in a box, as well. For example, it can be public, build, etc.

$ aidbox deploy build  
INFO: Compress you app...  
INFO: Publish app...  
OK: You application has been successfully uploaded in box [boxname]  
OK: Temp files have been removed

Example Workflow

Here is a typical development workflow. Let us suppose there are two boxes dev-myapp and prod-myapp. Currently you are working in dev-myapp box. When you want to deploy your application on prod-myapp, all you need is to switch context to prod-myapp, execute deploy operation in prod-myapp, come back to dev-myapp and continue development.

Thus, a workflow for two boxes dev-myapp and prod-myapp may look like:

$ aidbox login
$ aidbox box new dev-myapp
$ aidbox box new prod-myapp
$ aidbox box use dev-myapp ; Some actions for the development of an application ; Writing code, building application, testing ; Now you need to deploy your application to dev-myapp box ; and make sure eerything is working
$ aidbox box
$ adibox deploy ; If everything works as intended, you can deploy application to prod-myapp box $ aidbox box use prod-myapp $ adibox deploy ; Return back into dev-myapp box
$ aidbox box use dev-myapp ; And continue development

Users and Groups CLI

User Commands

user is a command for working with users in current box. To view a list of all available subcommands, execute:

$ aidbox user help  
user list                -- Display a list of users in current box  
user help -- Show help information  
user new                 -- Create a user via wizard  user new email:password  -- Create a user inline

user list

Outputs a list of all users in current box.

$ aidbox user list  INFO: Display a list of users in box [boxname]  ; For now it displays raw JSON

user new

Creates a new user using a wizard, in current box.

$ aidbox user new  
INFO: Create new user in box [boxname]  
Email: <test@gmail.com>  
Password: <password>  
OK: User [test@gmail.com] has been successfully created in box [boxname]

Another command to create a user inline without a wizard, has the following syntax:

aidbox user new email:password

$ aidbox user new test_2@gmail.com:password  
INFO: Create new user in box [boxname]  
OK: User [test_2@gmail.com] has been successfully created in box [boxname]

Users and Groups REST API

Same tasks can be performed programmatically via REST API.

POST /users

Creates new user.

Example Request:

POST https://[box-name].aidbox.io/users?access_token=[access-token] Accept: application/json Content-Type: application/json {"email": "user@example.com", "password": "godloveskittens", "data": "{}"}

Example Response:

{  "data": null,  "password": "$s0$f0801$PAPMyIhrU98utG2MFZN66w==$L6xOyD4seflK3hzQtQLAQJ6U1PP01x/ciDvSQnxfVIg=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 201 Created // Server: nginx // Date: Thu, 05 May 2016 10:38:44 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.307818s

In case of invalid data you'll receive 422 Unprocessable Entity status:

{  "entity": {    "data": "{}",    "password": "godloveskittens",    "email": "user@example.com"  },  "errors": {    "email": [      "email is already taken"    ]  } } // HTTP/1.1 422 Unprocessable Entity // Server: nginx // Date: Thu, 05 May 2016 10:49:06 GMT // Content-Type: application/json // Content-Length: 126 // Connection: keep-alive // Request duration: 0.514180s

GET /users

Returns list of existing box users.

Example Request:

GET https://[box-name].aidbox.io/users?access_token=[access-token]

Example Response:

[  {    "group-ids": [],    "groups": null,    "data": "{ }",    "email": "user@example.com",    "status": null,    "id": 2  } ] // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 10:51:55 GMT // Content-Type: application/json // Content-Length: 180 // Connection: keep-alive // Request duration: 0.403116s

GET /users/[id]

Retrieves data for specific user.

Example Request:

GET https://[box-name].aidbox.io/users/2?access_token=[access-token]

Example Response:

{  "groups": [],  "data": null,  "password": "$s0$f0801$PAPMyIhrU98utG2MFZN66w==$L6xOyD4seflK3hzQtQLAQJ6U1PP01x/ciDvSQnxfVIg=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 12:53:39 GMT // Content-Type: application/json // Content-Length: 164 // Connection: keep-alive // Request duration: 0.192518s

PUT /users/[id]

Updates existing user.

Example Request:

PUT https://[box-name].aidbox.io/users/2?access_token=[access-token] Accept: application/json Content-Type: application/json {"data": null, "password": "new-password", "email": "user@example.com"}

Example Response:

{  "data": null,  "password": "$s0$f0801$z7Q1dw22tyH5lkHTVSf0hQ==$NpBEXBOCbHty4cURu0FIm7rcSUCTXE3tHaPnE4fT5Ms=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 13:06:19 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.357732s

DELETE /users/[id]

Deletes specific user. Returns data of deleted user.

Example Request:

DELETE https://[box-name].aidbox.io/users/2?access_token=[access-token]

Example Response:

{  "data": null,  "password": "$s0$f0801$z7Q1dw22tyH5lkHTVSf0hQ==$NpBEXBOCbHty4cURu0FIm7rcSUCTXE3tHaPnE4fT5Ms=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 13:07:35 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.387985s

FHIR Server REST API

General REST Information

Server Root URL

In FHIR Specification all REST actions are relative to Server Root URL, which itself described in [FHIR-2.1.0.1] and refered as [base] in other parts of Specification. When using Aidbox, Server Root URL is composed in following way:

http(s)://<box-name>.aidbox.io/fhir

For box named example Server Root URL will be http(s)://example.aidbox.io/fhir.

HTTP and HTTPS

Both HTTP and HTTPS are supported, but we strongly recommend our users to use HTTPS for reasons of data safety.

Authorization and Authentication

Aidbox uses OAuth for authenticating clients, so in most cases you should provide access_token param in query string or request headers. Proceed to OAuth Section for more comprehensive coverage of this topic.

For Authorization purposes Aidbox uses policies which are explained in detail in Security Section. For testing purposes, it's often useful to have just one policy which allows anonymous access to all FHIR URLs.

Request and Response Formats

[FHIR-2.1.0.6] declares both XML and JSON as valid formats for request and response bodies. Hovewer, Aidbox supports only JSON for now.

Resources CRUD

GET /fhir/[type]/[id]

[FHIR-2.1.0.8]: Reads current version of specific resource.

GET /fhir/[type]/[id]/_history/[vid]

[FHIR-2.1.0.9]: Reads historical version of specific resource.

GET /fhir/[type]/[id]/_history/[vid]

[FHIR-2.1.0.9]: Reads historical version of specific resource.

PUT /fhir/[type]/[id]

[FHIR-2.1.0.10]: Updates existing resource or creates new one with client-defined ID. When updating existing resource performs optimistic locking via checking of meta.versionId.

DELETE /fhir/[type]/[id]

[FHIR-2.1.0.12]: Deletes resource.

POST /fhir/[type]

[FHIR-2.1.0.13]: Creates new resource. Supports conditional create via If-None-Exist header.

Search

GET /fhir/[type]?[parameters]

[FHIR-2.1.0.14]: Searches a set of resources based on some filter criteria.

History

GET /fhir/[type]/[id]/_history

[FHIR-2.1.0.17]: Returns history of specific resource.

GET /fhir/[type]/_history

[FHIR-2.1.0.17]: Returns history of all resources of specific type.

Other

GET /fhir/metadata

[FHIR-2.1.0.15]: Returns Conformance Resource describing available interactions of this FHIR Server.

POST /fhir

[FHIR-2.1.0.16]: Performs atomic set of operations (transaction) on arbitrary FHIR Resources.

GET /fhir/ValueSet/[id]/$expand

[FHIR-6.24.18.1]: Expands ValueSet.

Not Supported FHIR Features

Below is list of features not yet supported by Aidbox FHIR Server:

  • XML format support
  • Messaging [FHIR-2.4]
  • GET /fhir/_history history of all resource types
  • GET /fhir/_search search through all available resources
  • Searching by _text and _content attributes
  • Expanding ValueSets containing references to external NamingSystems (LOINC, SNOMED, etc)

Sample App Tutorial

We are offering this tutorial for learning core concepts of application development with Aidbox. We will develop a sample AngularJS web application which consists of a form for on-boarding patients (CRUD) with a search by name function.

See sample single-page application (SPA).

clojure.lang.LazySeq@7f423a4d

After completing this tutorial you should learn:

  • how to create Aidbox Web applications with NodeJS and AngularJS
  • how to use aidbox-cli
  • how to use REST API and query the FHIR server

Get Started

To start your development you have to install NodeJS. All the instructions how to install NODE.JS you can find at nodejs.org/download . The next step of preparing your development environment is installation of aidbox-cli and box setup. All the information you need for working with aidbox-cli you can find on its official page.

$ npm install -g aidbox-cli $ aidbox v

Sample App Structure

Clone our sample single-page application (SPA).

Sample app consists of three main files:

├── dist
│   ├── aidbox.js
│   ├── app.js
│   ├── index.html 
└── package.json
  • package.json - manifest file of your app. It contains the name of your project, its version, dependencies, commands to run etc You can read more about package.json file on this page of npm documentation.
  • index.html - the first HTML file of your application.
  • app.js - main part of your app. It contains all business logic, queries to the FHIR server via REST API, authorisation etc

Let's look at each file more closely:

Package.json

package.json contains only minimally required settings, one dependency http-server and one command start for starting a local Web server on the port 5000.

package.json

{  "name": "Aidbox-sample-spa",  "version": "0.0.0",  "dependencies": { },  "devDependencies": {    "http-server": "latest"  },  "engines": {    "node": ">=0.12.0"  },  "scripts": {    "start": "`npm bin`/http-server dist -p 5000"  } }

index.html

To simplify the app, let’s load all the styles and scripts from the CDN. Please pay attention that angular-aidbox.js - is a service for the AngularJS framework providing REST API and authorization implementation. You can read more details about this project on the aidboxjs official page.

index.html

<!doctype html> <html ng-app="app">  <head>    <meta charset="utf-8">    <title>My sample app</title>    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js" ></script>    <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular-cookies.min.js" ></script>   <script src="//aidbox.io/angular-aidbox.js" ></script>  </head>  <body>    <nav class="navbar navbar-default navbar-static-top" role="navigation">      <div class="container">        <div id="navbar" class="navbar">          <ul class="nav navbar-nav navbar-right">            <li ng-if="user" class="login">              <a href="#">{{user.email}}</a>            </li>            <li ng-if="!user">              <a ng-click="auth.signin()" href="#">Sign in</a>            </li>            <li ng-if="user">              <a ng-click="auth.signout()" href="#">Sign out</a>            </li>          </ul>        </div>      </div>    </nav>    <div class="container">      <h3>Sample app</h3>      <div ng-show="user" class="ng-hide">      </div>    </div>  </body> </html>

app.js

app.js

(function() {    var BOX_URL = 'https://myapp.aidbox.io';    var app = angular.module('app', ['ngCookies', 'ngAidbox']);    app.run(function($rootScope, $aidbox) {        $aidbox.init({            box: BOX_URL,            onSignIn: function(user) {                $rootScope.user = user;            },            onSignOut: function() {                $rootScope.user = null;            }        });    }); })();

Run

npm run start

Deploy

aibox deploy

FHIRbase Console Overview

Each Aidbox box includes separate PostgreSQL database with installed Fhirbase. Fhirbase is an open source PostgreSQL extension for storing FHIR resources in PostgreSQL. You can get direct connection to it from Box Administration Interface.

Fhirbase Console is a way to interact with Fhirbase, which is built Aidbox.

Fhirbase itself is an open source storage based on the FHIR standard.

Interaction with Fhirbase Console is performed via writing and executing PostgreSQL functions. This is due to the fact that Fhirbase is an extension of PostgreSQL.

FHIRbase Console UI Guide

How to work with the FHIRbase Console

First, you need to create a table of patients.

  • ‍Open Fhirbase Console
  • Copy and paste the following query:
SELECT fhir_create_storage('{"resourceType": "Patient"}'::json);
  • ‍Click the 'Execute' button
clojure.lang.LazySeq@4380bb9a
  • ‍Check the result
clojure.lang.LazySeq@4380bb9a

Then you can add a new patient:

1. Copy and paste the following query:

SELECT fhir_create_resource(' {"resource": {"resourceType": "Patient"}} ');

2. Click the 'Execute' button

Let's check that the patient has been added:

  1. Copy and paste the following query:
SELECT * FROM patient LIMIT 5;

2. Click the 'Execute' button

clojure.lang.LazySeq@4380bb9a

3. Check the result

FHIRbase API

Conformance

fhir_conformance('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns a JSON

Create storage

fhir_create_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns a JSON

Example

Create patient table

SELECT fhir_create_storage('{"resourceType": "Patient"}'::json);

Response:

{  "message": "Table patient was created",  "status": "ok" }

Create all storages

fhir_create_all_storages()

Arguments

Function has no arguments

Returns

Returns an string

Drop storage

fhir_drop_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns a JSON

Drop all storages

fhir_drop_all_storages('{}'::json)

Arguments

Function has no arguments

Returns

Returns a JSON

Describe storage

fhir_describe_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns a JSON

Truncate storage

fhir_truncate_storage('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns a JSON

Create resource

fhir_create_resource('{}'::json)

Arguments

Takes an argument JSON with properties:

  • allowId boolean
  • resource JSON with properties:
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Create patient

SELECT fhir_create_resource('  {    "resource": {      "name": [        {          "given": [            "Smith"          ]        }      ],      "resourceType": "Patient"    }  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-05T16:57:26.202Z",    "versionId": "0a75f4b1-1e15-4628-b1ad-ae8a8730af00"  },  "id": "c6258cdc-1c80-4dda-80d4-6027c2a23ffd",  "name": [    {      "given": [        "Smith"      ]    }  ],  "resourceType": "Patient" }

Create patient with specific id

SELECT fhir_create_resource('  {    "resource": {      "id": "smith",      "resourceType": "Patient"    },    "allowId": true  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-06T13:38:11.910Z",    "versionId": "c112dd87-1f5b-4c2a-a3c0-783e371cc721"  },  "id": "smith2",  "resourceType": "Patient" }

Read resource

fhir_read_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Show patient by id

SELECT fhir_read_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "resourceType": "Patient",  "meta": {    "lastUpdated": "2016-05-06T13:18:20.996Z",    "versionId": "c8da6a21-018f-4646-afbf-dc2e36baaef1",    "extension": [      {        "valueString": "POST",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "smith" }

Vread resource

fhir_vread_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • versionId string (mandatory)

Returns

Returns Resource JSON

Update resource

fhir_update_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Update patient by id

SELECT fhir_update_resource('  {    "resource": {      "name": [        {          "family": [            "Smith"          ],          "given": [            "John"          ]        }      ],      "id": "smith",      "resourceType": "Patient"    }  } ');

Response:

{  "meta": {    "extension": [      {        "valueString": "PUT",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ],    "lastUpdated": "2016-05-06T13:46:09.571Z",    "versionId": "946b91ac-b285-4751-9f6f-c6462d0e7465"  },  "name": [    {      "family": [        "Smith"      ],      "given": [        "John"      ]    }  ],  "id": "smith",  "resourceType": "Patient" }

Patch resource

fhir_patch_resource('{}'::json)

Arguments

Takes an argument JSON with properties:

  • patch array (mandatory) contains objects with properties:
  • op string (mandatory)
  • path string (mandatory)
  • value string (mandatory)
  • resource JSON (mandatory) with properties:
  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Patch patient by id

SELECT fhir_patch_resource('  {    "patch": [      {        "value": "Jane",        "path": "\/name\/0\/given\/0",        "op": "replace"      }    ],    "resource": {      "id": "johndoe",      "resourceType": "Patient"    }  } ');

Response:

{  "resourceType": "Patient",  "name": [    {      "family": [        "Doe"      ],      "given": [        "Jane"      ],      "text": "John Doe"    }  ],  "meta": {    "lastUpdated": "2016-05-11T16:12:50.377Z",    "versionId": "3541fd2e-4ca9-4790-9382-41f98c8b9ad7",    "extension": [      {        "valueString": "PUT",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "johndoe" }

Delete resource

fhir_delete_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Resource JSON

Example

Mark patient as deleted (i.e. keep history)

SELECT fhir_delete_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "resourceType": "Patient",  "meta": {    "lastUpdated": "2016-05-06T14:10:50.841Z",    "versionId": "a307ff6c-d35d-4cc4-9784-a91865dfa933",    "extension": [      {        "valueString": "DELETE",        "url": "fhir-request-method"      },      {        "valueUri": "Patient",        "url": "fhir-request-uri"      }    ]  },  "id": "smith" }

Terminate resource

fhir_terminate_resource('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Example

Completely delete patient and its history

SELECT fhir_terminate_resource('{"resourceType": "Patient", "id": "smith"}');

Response:

[  "{\"id\": \"smith\", \"meta\": {\"extension\": [{\"url\": \"fhir-request-method\", \"valueString\": \"POST\"}, {\"url\": \"fhir-request-uri\", \"valueUri\": \"Patient\"}], \"versionId\": \"3074d414-2318-42e4-aebe-f521d0ef1aff\", \"lastUpdated\": \"2016-05-06T14:10:43.186Z\"}, \"resourceType\": \"Patient\"}",  "{\"id\": \"smith\", \"meta\": {\"extension\": [{\"url\": \"fhir-request-method\", \"valueString\": \"DELETE\"}, {\"url\": \"fhir-request-uri\", \"valueUri\": \"Patient\"}], \"versionId\": \"a307ff6c-d35d-4cc4-9784-a91865dfa933\", \"lastUpdated\": \"2016-05-06T14:10:50.841Z\"}, \"resourceType\": \"Patient\"}" ]

Resource history

fhir_resource_history('{}'::json)

Arguments

Takes Resource JSON with properties:

  • id string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Example

Show patient's history

SELECT fhir_resource_history('{"resourceType": "Patient", "id": "smith"}');

Response:

{  "entry": [    {      "resource": {        "resourceType": "Patient",        "meta": {          "lastUpdated": "2016-05-06T13:18:20.996Z",          "versionId": "c8da6a21-018f-4646-afbf-dc2e36baaef1",          "extension": [            {              "valueString": "POST",              "url": "fhir-request-method"            },            {              "valueUri": "Patient",              "url": "fhir-request-uri"            }          ]        },        "id": "smith"      },      "request": {        "url": "Patient",        "method": "POST"      }    }  ],  "type": "history",  "meta": {    "lastUpdated": "2016-05-06T13:46:48.278Z"  },  "total": 1,  "resourceType": "Bundle" }

Resource type history

fhir_resource_type_history('{}'::json)

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Search

fhir_search('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns Bundle JSON

Example

Patient search

SELECT fhir_search('{"resourceType": "Patient", "queryString": "name=smith"}');

Response:

{  "entry": [    {      "resource": {        "deceasedBoolean": "N",        "resourceType": "Patient",        "identifier": [          {            "system": "urn:oid:2.16.840.1.113883.4.3.42",            "value": "010107112",            "type": {              "text": "External ID"            }          },          {            "system": "urn:oid:2.16.840.1.113883.4.3.45",            "value": "160923",            "type": {              "text": "Internal ID"            }          },          {            "system": "urn:oid:2.16.840.1.113883.4.3.46",            "value": "160923",            "type": {              "text": "Alternate ID"            }          },          {            "value": "5435435435",            "type": {              "text": "Account number"            }          },          {            "system": "http:\/\/hl7.org\/fhir\/sid\/us-ssn",            "value": "123-22-1111",            "type": {              "text": "Social Security Number"            }          }        ],        "birthDate": "1996-02-16T04:17+03",        "telecom": [          {            "system": "phone",            "value": "090.293.5104 x4116",            "use": "home"          }        ],        "contact": [          {            "address": {              "use": "Mailing Address"            },            "gender": "unknown",            "name": {              "middle": [                "Ms."              ],              "family": [                "Balistreri"              ],              "given": [                "Bartholome"              ],              "text": "JEAN SANDY JACK",              "use": "official"            }          }        ],        "address": [          {            "postalCode": "08928",            "country": "USA",            "state": "MI",            "line": [              "45713 Glennie Loaf",              "Schumm Village"            ],            "city": "Rodriguezville"          }        ],        "gender": "female",        "name": [          {            "middle": [              "Mrs."            ],            "family": [              "Smitham"            ],            "given": [              "Rudy"            ],            "text": "JEAN SANDY JACK"          }        ],        "id": "97af0e81-29fc-4a97-935d-a7909da2c17d"      }    }  ],  "link": [    {      "url": "Patient\/search?name=smith&_page=0",      "relation": "self"    }  ],  "total": 1,  "type": "searchset",  "resourceType": "Bundle" }

Get search SQL

fhir_search_sql('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Example

See generated SQL

SELECT fhir_search_sql('  {    "queryString": "name=smith",    "resourceType": "Patient"  } ');

Response:

[  "SELECT * FROM \"patient\" tbl1     WHERE fhir_extract_as_string(             ( \"tbl1\".\"resource\" )::json,             ( '[\"Patient\",\"name\"]' )::json,             'HumanName'           ) ilike $1     LIMIT $2",  "%^^smith%",  10 ]

Expand valueset

fhir_expand_valueset('{}'::json)

Arguments

Takes an argument JSON with properties:

  • id string (mandatory)
  • filter string

Returns

Returns ValueSet JSON

Analyze storage

fhir_analyze_storage('{}'::json)

Analyze on resource tables to update PostgreSQL statistic

Arguments

Takes Resource JSON with properties:

  • resourceType string (mandatory)

Returns

Returns a JSON

Index parameter

fhir_index_parameter('{}'::json)

Create index for parameter

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Index order

fhir_index_order('{}'::json)

Creates index for parameter sort

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Unindex parameter

fhir_unindex_parameter('{}'::json)

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Unindex order

fhir_unindex_order('{}'::json)

Arguments

Takes an argument JSON with properties:

  • name string (mandatory)
  • resourceType string (mandatory)

Returns

Returns a JSON

Explain search

fhir_explain_search('{}'::json)

Arguments

Takes an argument JSON with properties:

  • queryString string (mandatory)
  • resourceType string (mandatory)

Returns

Returns an integer

Transaction

fhir_transaction('{}'::json)

Arguments

Takes Bundle JSON with properties:

  • resourceType string (mandatory)
  • entry array (mandatory) contains objects with properties:
  • resource JSON (mandatory) with properties:
  • resourceType string (mandatory)
  • request JSON (mandatory) with properties:
  • method string (mandatory)url string (mandatory)

Returns

Returns Bundle JSON

Example

Create practitioner and associated patient

Patient search

SELECT fhir_transaction('  {    "resourceType": "Bundle",    "id": "bundle-transaction-id",    "type": "transaction",    "entry": [      {        "resource": {          "resourceType": "Practitioner"        },        "request": {          "method": "PUT",          "url": "/Practitioner/created-practitioner-id"        }      },      {        "resource": {          "resourceType": "Patient",          "careProvider": [            {              "reference": "/Practitioner/created-practitioner-id"            }          ]        },        "request": {          "method": "PUT",          "url": "/Patient/created-patient-id"        }      },      {        "request": {          "method": "GET",          "url": "/Patient?_id=created-patient-id&_include=careprovider"        }      }    ]  } ');

Response:

{  "resourceType": "Bundle",  "type": "transaction-response",  "entry": [    {      "resourceType": "Practitioner",      "id": "created-practitioner-id",      "meta": {        "versionId": "b6de0892-0aa5-48f3-a645-b833fc4bf0c3",        "lastUpdated": "2016-05-12T12:29:22.412Z",        "extension": [          {            "url": "fhir-request-method",            "valueString": "PUT"          },          {            "url": "fhir-request-uri",            "valueUri": "Practitioner"          }        ]      }    },    {      "resourceType": "Patient",      "careProvider": [        {          "reference": "/Practitioner/created-practitioner-id"        }      ],      "id": "created-patient-id",      "meta": {        "versionId": "ffc1c306-c2bd-472e-916f-d75ba2ce133d",        "lastUpdated": "2016-05-12T12:29:22.414Z",        "extension": [          {            "url": "fhir-request-method",            "valueString": "POST"          },          {            "url": "fhir-request-uri",            "valueUri": "Patient"          }        ]      }    },    {      "resourceType": "Bundle",      "type": "searchset",      "total": 1,      "link": [        {          "relation": "self",          "url": "/Patient?_id=created-patient-id&_include=careprovider&_page=0"        }      ],      "entry": [        {          "resource": {            "id": "created-patient-id",            "meta": {              "extension": [                {                  "url": "fhir-request-method",                  "valueString": "POST"                },                {                  "url": "fhir-request-uri",                  "valueUri": "Patient"                }              ],              "versionId": "ffc1c306-c2bd-472e-916f-d75ba2ce133d",              "lastUpdated": "2016-05-12T12:29:22.414Z"            },            "careProvider": [              {                "reference": "/Practitioner/created-practitioner-id"              }            ],            "resourceType": "Patient"          }        },        {          "resource": {            "id": "created-practitioner-id",            "meta": {              "extension": [                {                  "url": "fhir-request-method",                  "valueString": "PUT"                },                {                  "url": "fhir-request-uri",                  "valueUri": "Practitioner"                }              ],              "versionId": "b6de0892-0aa5-48f3-a645-b833fc4bf0c3",              "lastUpdated": "2016-05-12T12:29:22.412Z"            },            "resourceType": "Practitioner"          }        }      ]    }  ] }

Valueset after changed

fhir_valueset_after_changed('{}'::json)

Arguments

Takes ValueSet JSON with properties:

  • id string (mandatory)

Returns

Returns a JSONValueset after deleted

fhir_valueset_after_deleted('{}'::json)

Arguments

Takes ValueSet JSON with properties:

  • id string (mandatory)

Returns

Returns a JSON

Disk usage

fhirbase_disk_usage_top('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns an array

Benchmark

fhir_benchmark('{}'::json)

Arguments

Takes an argument JSON

Returns

Returns an array

FHIR version

fhir_version()

Arguments

Function has no arguments

Returns

Returns version string

Example

SELECT fhir_version();

Response:

1.3.0

FHIRbase version

fhirbase_version()

Arguments

Function has no arguments

Returns

Returns version string

Example

SELECT fhirbase_version();

Response:

1.3.0.13

FHIRbase release date

fhirbase_release_date()

Arguments

Function has no arguments

Returns

Returns datetime string

Example

SELECT fhirbase_release_date();

Response:

1970-12-31T23:59:59Z

Overview

FHIR REST API is one of Aidbox core features. While Aidbox Team tries to stay close to FHIR specification, it's not always worthwhile or technically possible to implement some tricky parts of FHIR specification.

In this article we'll briefly cover all available REST interactions with links to corresponding paragraphs from FHIR Specification. Also you'll find list of unsupported or partly supported features at the end of this article.

FHIR Server UI Guide

How to create a patient

First, you need to create a table of patients (see FHIRbase Console UI)

SELECT fhir_create_storage('{"resourceType": "Patient"}'::json);

or all tables

fhir_create_all_storages()

Then you can add a new patient:

1. Open REST Console2. Select the POST method

clojure.lang.LazySeq@4380bb9a

3. Enter fhir/Patient after the slash4. Paste a JSON example of the Patient resource from the FHIR specification, having removed a line with id assigning, into the request body.

{  "managingOrganization": {    "reference": "Organization\/1"  },  "contact": [    {      "period": {        "_start": {          "fhir_comments": [            "   The contact relationship started in 2012   "          ]        },        "start": "2012"      },      "gender": "female",      "telecom": [        {          "value": "+33 (237) 998327",          "system": "phone"        }      ],      "name": {        "given": [          "B\u0413\u00a9n\u0413\u00a9dicte"        ],        "_family": [          {            "extension": [              {                "valueCode": "VV",                "url": "http:\/\/hl7.org\/fhir\/StructureDefinition\/iso21090-EN-qualifier",                "fhir_comments": [                  "   the \"du\" part is a family name prefix (VV in iso 21090)   "                ]              }            ]          },          null        ],        "family": [          "du",          "March\u0413\u00a9"        ]      },      "relationship": [        {          "coding": [            {              "code": "partner",              "system": "http:\/\/hl7.org\/fhir\/patient-contact-relationship"            }          ]        }      ]    }  ],  "address": [    {      "period": {        "start": "1974-12-25"      },      "postalCode": "3999",      "state": "Vic",      "district": "Rainbow",      "city": "PleasantVille",      "line": [        "534 Erewhon St"      ],      "type": "both",      "use": "home"    }  ],  "deceasedBoolean": false,  "_birthDate": {    "extension": [      {        "valueDateTime": "1974-12-25T14:35:45-05:00",        "url": "http:\/\/hl7.org\/fhir\/StructureDefinition\/patient-birthTime"      }    ]  },  "birthDate": "1974-12-25",  "_gender": {    "fhir_comments": [      "   use FHIR code system for male \/ female   "    ]  },  "gender": "male",  "telecom": [    {      "use": "home",      "fhir_comments": [        "   home communication details aren't known   "      ]    },    {      "use": "work",      "value": "(03) 5555 6473",      "system": "phone"    }  ],  "name": [    {      "given": [        "Peter",        "James"      ],      "family": [        "Chalmers"      ],      "use": "official",      "fhir_comments": [        "   Peter James Chalmers, but called \"Jim\"   "      ]    },    {      "given": [        "Jim"      ],      "use": "usual"    }  ],  "active": true,  "identifier": [    {      "assigner": {        "display": "Acme Healthcare"      },      "period": {        "start": "2001-05-06"      },      "value": "12345",      "system": "urn:oid:1.2.36.146.595.217.0.1",      "type": {        "coding": [          {            "code": "MR",            "system": "http:\/\/hl7.org\/fhir\/v2\/0203"          }        ]      },      "use": "usual",      "fhir_comments": [        "   MRN assigned by ACME healthcare on 6-May 2001   "      ]    }  ],  "text": {    "div": "<div>\n      \n      <table>\n        \n        <tbody>\n          \n          <tr>\n            \n            <td>Name<\/td>\n            \n            <td>Peter James \n              <b>Chalmers<\/b> (&quot;Jim&quot;)\n            <\/td>\n          \n          <\/tr>\n          \n          <tr>\n            \n            <td>Address<\/td>\n            \n            <td>534 Erewhon, Pleasantville, Vic, 3999<\/td>\n          \n          <\/tr>\n          \n          <tr>\n            \n            <td>Contacts<\/td>\n            \n            <td>Home: unknown. Work: (03) 5555 6473<\/td>\n          \n          <\/tr>\n          \n          <tr>\n            \n            <td>Id<\/td>\n            \n            <td>MRN: 12345 (Acme Healthcare)<\/td>\n          \n          <\/tr>\n        \n        <\/tbody>\n      \n      <\/table>    \n    \n    <\/div>",    "status": "generated"  },  "resourceType": "Patient" }

5. Click the 'Execute' button

clojure.lang.LazySeq@4380bb9a

6. Check the response body

clojure.lang.LazySeq@4380bb9a

Let's check that the patient has been added.

Bundle (Transaction)

Ensure, that you have already created necessary tables.

1. Open REST Console2. Select the POST method

clojure.lang.LazySeq@4380bb9a

3. Set the URL to /fhir/4. Paste your JSON into the request body

{  "resourceType": "Bundle",  "type": "transaction",  "entry": [    {      "resource": {        "resourceType": "Patient",        "name": [          {            "use": "official",            "given": [              "FirstName123"            ],            "family": [              "LastName123"            ]          },          {            "use": "usual",            "given": [              "FirstName123"            ],            "family": [              "LastName123"            ]          }        ]      },      "request": {        "method": "PUT",        "url": "/Patient/f0587417-6e01-aa5e-06a7-b4a1a502a48d"      }    },    {      "resource": {        "resourceType": "EpisodeOfCare",        "status": "active",        "reference": {          "patient": "/Patient/f0587417-6e01-aa5e-06a7-b4a1a502a48d"        }      },      "request": {        "method": "POST",        "url": "/EpisodeOfCare"      }    }  ] }

5. Click EXECUTE

clojure.lang.LazySeq@aaf59d0c

6. Check the RESPONSE BODY

clojure.lang.LazySeq@aaf610d0

FHIR Server REST API

General REST Information

Server Root URL

In FHIR Specification all REST actions are relative to Server Root URL, which itself described in [FHIR-2.1.0.1] and refered as [base] in other parts of Specification. When using Aidbox, Server Root URL is composed in following way:

http(s)://<box-name>.aidbox.io/fhir

For box named example Server Root URL will be http(s)://example.aidbox.io/fhir.

HTTP and HTTPS

Both HTTP and HTTPS are supported, but we strongly recommend our users to use HTTPS for reasons of data safety.

Authorization and Authentication

Aidbox uses OAuth for authenticating clients, so in most cases you should provide access_token param in query string or request headers. Proceed to OAuth Section for more comprehensive coverage of this topic.

For Authorization purposes Aidbox uses policies which are explained in detail in Security Section. For testing purposes, it's often useful to have just one policy which allows anonymous access to all FHIR URLs.

Request and Response Formats

[FHIR-2.1.0.6] declares both XML and JSON as valid formats for request and response bodies. Hovewer, Aidbox supports only JSON for now.

Resources CRUD

GET /fhir/[type]/[id]

[FHIR-2.1.0.8]: Reads current version of specific resource.

GET /fhir/[type]/[id]/_history/[vid]

[FHIR-2.1.0.9]: Reads historical version of specific resource.

GET /fhir/[type]/[id]/_history/[vid]

[FHIR-2.1.0.9]: Reads historical version of specific resource.

PUT /fhir/[type]/[id]

[FHIR-2.1.0.10]: Updates existing resource or creates new one with client-defined ID. When updating existing resource performs optimistic locking via checking of meta.versionId.

DELETE /fhir/[type]/[id]

[FHIR-2.1.0.12]: Deletes resource.

POST /fhir/[type]

[FHIR-2.1.0.13]: Creates new resource. Supports conditional create via If-None-Exist header.

Search

GET /fhir/[type]?[parameters]

[FHIR-2.1.0.14]: Searches a set of resources based on some filter criteria.

History

GET /fhir/[type]/[id]/_history

[FHIR-2.1.0.17]: Returns history of specific resource.

GET /fhir/[type]/_history

[FHIR-2.1.0.17]: Returns history of all resources of specific type.

Other

GET /fhir/metadata

[FHIR-2.1.0.15]: Returns Conformance Resource describing available interactions of this FHIR Server.

POST /fhir

[FHIR-2.1.0.16]: Performs atomic set of operations (transaction) on arbitrary FHIR Resources.

GET /fhir/ValueSet/[id]/$expand

[FHIR-6.24.18.1]: Expands ValueSet.

Not Supported FHIR Features

Below is list of features not yet supported by Aidbox FHIR Server:

  • XML format support
  • Messaging [FHIR-2.4]
  • GET /fhir/_history history of all resource types
  • GET /fhir/_search search through all available resources
  • Searching by _text and _content attributes
  • Expanding ValueSets containing references to external NamingSystems (LOINC, SNOMED, etc)

Overview

Aidbox supports all basic OAuth 2.0 workflows:

  • Web Application (Autorization Code)
  • Single Page Applications (Implicite)
  • REST clients (Client Credentials)

See RFC6749 for more information about OAuth 2.0 authorization.

Every box implements OAuth 2.0 Provider Service and all REST API calls is secured by OAuth.

On the 'Clients' page you can view a list of available clients, add new or edit existing clients.

Clients UI Guide

Default Client

Each newly created box has a default implicit client named site.

clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

In order to use this client, you will need to add the following policy:

{ "required" : [ "client" ], "properties" : {   "client" : {     "type" : "object",     "properties" : {       "client_id" : {         "constant" : "site"       }     }   } } }

Implicit

Let's add a client with type = Implicit and client_id = implicit_client123.

  1. Open the Clients tab
  2. Click the 'Create new item' button
clojure.lang.LazySeq@6cb5d493
  1. Select the type 'Implicit for browser-based or mobile apps'
  2. Fill in the fields:
  • Name = implicit_client
  • Client Id = implicit_client123
  • Redirect Uri = localhost
  1. Click the Create button
clojure.lang.LazySeq@6cb5d493

In order to test implicit authorization, let's add a new policy policy_for_implicit_client with Id = policy_for_implicit_client123 that will be checking for implicit client with the client_id = implicit_client123.

{ "required" : [ "client" ], "properties" : {   "client" : {     "type" : "object",     "properties" : {       "client_id" : {         "constant" : "implicit_client123"       }     }   } } }
clojure.lang.LazySeq@6cb5d493

In order to test the implicit authorization, let's add a user with Email = and Password = 12345678.

clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

Remove the existing default implicit client named site (to avoid confusion).

Edit dist/aidbox.js code: in the line with client_id: 'site' change 'site' to 'implicit_client123'. TODO: Remove this step after fix.

clojure.lang.LazySeq@6cb5d493

Now let's check the implicit authentication.

  1. Deploy your aidbox
clojure.lang.LazySeq@6cb5d493
  1. Visit your application at the URL generated from the box name - e.g. https://mysuperapp.aidbox.io for the mysuperapp box, you can use the link from your aidbox Dashboard.
clojure.lang.LazySeq@6cb5d493
  1. Click the 'Sign in' link
clojure.lang.LazySeq@6cb5d493
  1. You will see a login form labeled Allow implicitclient to use your account where implicitclient is the name of your client
  2. Log in with the box user credentials (not your aidbox account credentials). In our example: Email = and Password = 12345678.
clojure.lang.LazySeq@6cb5d493
  1. You will see Patients list page of the sample application
clojure.lang.LazySeq@6cb5d493

Authorization Code

In order to test the Authorization Code type of authorization, you will need a tool for testing RESTful requests. For example Postman.

Let's add a new client with the Authorization Code type.

  1. Open the Clients tab.
  2. Click the 'Create new item' button
  3. Select the type 'Authorization Code for apps running on a web server'
  4. Fill in the fields:
  • Name = auth_code
  • Client Id = auth_code123
  • Client Secret = pwd
  • Redirect Uri = localhost, www.getpostman.com
  1. Click the Create button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

Let's add a new policy that would allow an access for our client.

  1. Open the Policies tab
  2. Click the 'Create new item' button
  3. Fill in the fields:
  • Id = policy_for_auth_code_client123
  • Title = policy_for_auth_code_client
  • Policy =
{ "required" : [ "client" ], "properties" : {   "client" : { "type" : "object", "properties" : {   "client_id" : {     "constant" : "auth_code123"   } }   } } }
  1. Click the Create button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

Now let's check the Authorization Code authentication.

  1. Open Postman
  2. Select method GET
  3. Enter request URL: e.g. https://yourboxname.aidbox.io/users
  4. Select Type = OAuth 2.0
  5. Fill in the following fields:
  1. Click the 'Request Token' button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493
  1. You will see a login form labeled Allow authcode to use your account where authcode is the name of your client.
  2. Log in with the box user credentials (not your aidbox account credentials). In our example: Email = and Password = 12345678
clojure.lang.LazySeq@6cb5d493
  1. In the Postman click on the Token Name in order to add the token to the request URL, e.g. https://yourboxname.aidbox.io/users?access_token=1ba63588-45e5-4f0d-9a0c-0ae5ebe131f5
clojure.lang.LazySeq@6cb5d493
  1. In the Postman click the 'Send' button
clojure.lang.LazySeq@6cb5d493
  1. Scroll down and check the request body below
clojure.lang.LazySeq@6cb5d493

You will see something like: 

[  { "id": 1, "status": null, "email": "boxuser1@gmail.com", "data": "null", "groups": null, "group-ids": []  } ]

Client Credentials

Let's add a new client with the Client credentials type.

  1. Open the Clients tab
  2. Click the 'Create new item' button
  3. Select the type 'Client credentials for application access'
  4. Fill in the fields:
  • Name = client_credentials
  • Client Id = client_credentials123
  • Client Secret = secret
  • Redirect Uri = localhost, www.getpostman.com
  1. Click the Create button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

Let's add a new policy that would allow an access for our client.

  1. Open the Policies tab
  2. Click the 'Create new item' button
  3. Fill in the fields:
  • Id = policy_for_client_credentials_client123
  • Title = policy_for_client_credentials_client
  • Policy =  
{ "required" : [ "client" ], "properties" : {   "client" : { "type" : "object", "properties" : {   "client_id" : {     "constant" : "client_credentials_client123"   } }   } } }
  1. Click the Create button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493

Now let's check the Client Credentials authentication.

  • Click the Request Token button.
  • Click on Token Name in order to add the token to the request URL.
  • Click the Send button.
  • Check the request body below.
  1. Open Postman
  2. Select method GET
  3. Enter request URL: e.g. https://yourboxname.aidbox.io/users/1
  4. Select Type = OAuth 2.0
  5. Fill in the following fields:
  1. Click the 'Request Token' button
clojure.lang.LazySeq@6cb5d493
clojure.lang.LazySeq@6cb5d493
  1. In the Postman click on the Token Name in order to add the token to the request URL, e.g. https://yourboxname.aidbox.io/users?access_token=1ba63588-45e5-4f0d-9a0c-0ae5ebe131f5
clojure.lang.LazySeq@6cb5d493
  1. In the Postman click the 'Send' button
clojure.lang.LazySeq@6cb5d493
  1. Scroll down and check the request body below
clojure.lang.LazySeq@6cb5d493

You will see something like:

 {  "id": 1,  "status": null,  "email": "boxuser1@gmail.com",  "password": "$s0$f0801$9T3nDgBQFyF1RU0sXjnyXg==$smBzJ4YzXNu4YkYjhXj0cwxeQM66xRD5F/FtQkytpqE=",  "data": null,  "groups": [] }

Aidbox Overview

We built Aidbox with the FHIR standard. FHIR (Fast Healthcare Interoperability Resources) is an open HL7 standard and specification for storing and exchanging healthcare data by leveraging modern web technologies.

The FHIR standard currently describes about 116 models for storing health data, and these units are called Resources (such as Patient, Encounter, Observation etc.). FHIR uses a REST API to access and manipulate the data (Create, Update, Search, etc).

Aidbox is a FHIR server as a service with useful additions.

With Aidbox, you can focus on your business ideas validation, and leave the backend technical details to us.

Aidbox provides you with everything you need to start building your healthcare application:

  • A scalable and powerful PostgreSQL database (fhirbase) to store and query your data
  • FHIR compliant REST API to access and manipulate this data
  • OAuth 2.0 and flexible security rules to control access to application data
  • API to manage application users, with optional registration module
  • Terminology servers for popular medical coding systems (LOINC, SNOMED, ICD10, RxNorm) and custom dictionaries (ValueSets)
  • Hosting for Single Page Applications written in HTML and JavaScript

With Aidbox, you can easily develop Mobile, Single Page, and classic Web Applications.

Box Management Overview

If you already have an Aidbox account, then you can create your own boxes. Each box is an instance of FHIR server with a separate database and URL.

For example, you can create several boxes for development, one box for staging, and another for production.

Boxes can be created from the Dashboard, using REST API, or aidbox-cli util.

We take care of all the maintaining, scaling and updating of your boxes.

Box management is done on the 'Dashboard' page. 

The 'Dashboard' is a place where you can see all your existing boxes, and create, manage, share and destroy boxes. Each box in the Dashboard has a name, an URL where it will be deployed, a list of users the box is shared with, a destroy option and a payment plan indicator.

The primary box interface is a REST API. Each box is fully compliant to the FHIR specification.

Users and Groups Overview

Each aidbox box has its own users and security rules. You can use the REST API, Box Admin UI or aidbox-cli to manage users in an Aidbox box. You can also enable the registration module to allow users to register in an Aidbox box by themselves.

Users could be assigned to groups and for each group you can create specific security rules.

Users and Groups tools are used to create, edit and delete box users and user groups. These users' credentials are used to log in the application working on the top of the Aidbox box.

Policies Overview

Policy is a JSON schema filtering REST requests. A request succeeds if at least one of the policies is valid for it.

Clients Overview

Aidbox supports all basic OAuth 2.0 workflows:

  • Web Application (Autorization Code)
  • Single Page Applications (Implicit)
  • REST clients (Client Credentials)

See RFC6749 for more information about the OAuth 2.0 authorization.

Every box implements the OAuth 2.0 Provider Service and all REST API calls are secured by OAuth.

On the 'Clients' page you can view a list of available clients, and add or edit existing clients.

FHIR Server Overview

The FHIR REST API is one of the Aidbox core features. While our Aidbox team tries to stay close to the FHIR specification, it's not always worthwhile or technically possible to implement some parts of the FHIR specification.

In this article we'll briefly cover all available REST interactions with links to corresponding paragraphs from FHIR Specification. Also you'll find list of unsupported or partly supported features at the end of this article.

FHIRbase Console Overview

Each Aidbox box includes a separate PostgreSQL database with an installed FHIRbase. FHIRbase is an open source extension of PostgreSQL for storing FHIR resources. 

You can get directly connect to it from the Box Administration Interface in Aidbox.

You can use the FHIRbase Console to interact with FHIRbase, and any interactions with the FHIRbase Console is performed via writing and executing PostgreSQL functions. 

Hosting Overview

You can host One Page applications (written in HTML & JavaScript) directly on your box. These applications can easily be developed on your local machine and deployed in a box in a few seconds with one command (see Quick Start).

Overview

This tutorial shows you how to start development, run your first app on Aidbox, and deploy it into the cloud.

Setup Development Environment

To take full advantage of Aidbox, you will need GIT and NODE.JS.

You will also need aidbox-cli. You can install it using NPM. Just make sure that you have permission for installing modules globally. 

Execute this in your command terminal:

$ npm install -g aidbox-cli
$ aidbox v

If "aidbox v" returns OK, everything is ready for developing your applications with Aidbox!

Using Aidbox on the Website

To start working with Aidbox you have to create a free Aidbox account. After you receive a confirmation email from us, click the link it contains to confirm that you own the email address.

  • Log in to Aidbox
  • Create a new box e.g. mysuperEHR (see Box Management on how to create a new one)
  • Open the box by clicking its name on the Dashboard
  • Create a user in your box e.g. user1@test.com / 7777 (see Users and Groups on how to create a new one)
  • Each newly created box has a default implicit client named "site" (see Clients for more information about clients)
  • Open this client for editing and add the following link to the 'Redirect Uri' field on the form: s3-us-west-1.amazonaws.com
  • Create a new policy with the following schema (see Policies on how to create a new one):
{"required": ["client"],
"properties": {
  "client": {
    "type": "object",
      "properties": {
        "client_id": {
          "constant": "site"
        }
      }
     }
  }
}

AIDBOX CLI

In your command console, switch to the sample-spa folderConnect to Aidbox:

$ aidbox login

Enter email and password of your Aidbox accountView the list of your boxes

$ aidbox box list

Choose a box to work with

$ aidbox box use <boxname>

Run Sample Application

To try Aidbox, run our sample single-page application (SPA).

Execute the following commands to clone it, and install modules and packages it depends on:

$ git clone https://github.com/Aidbox/sample-spa
$ cd sample-spa
$ npm install

In the file dist/app.js, set the variable BOX_URL to the URL of your box.

For instance, if the name of your box is mysuperEHR then set the variable BOX_URL this way:

var BOX_URL = 'https://mysuperEHR.aidbox.io';

You can run your application locally with this command from the project folder (this step is optional):

$ npm run start

Your application will be running at http://localhost:5000.

Click on the login button and enter login and password of one of the box users e.g. user1@test.com / 7777.

After logging in, you will see a simple patient list which allows you to filter, add and edit patients.

Deploy Sample Application

Deploy your application into the box from the sample-spa folder with the following command:

$ aidbox deploy

Visit your running application by the URL generated from the box name - e.g. https://s3-us-west-1.amazonaws.com/aidbox-production4-aidbox-files/mysuperehr/index.html for the box mysuperEHR.

Click on the login button and enter login and password of one of the box users e.g. user1@test.com / 7777.

Overview

If you already have aidbox account, then you can create your own boxes. Box is an instance of FHIR server with separate database and url.

For example: you can create several boxes for development, one box for staging and another for production.

Boxes could be created from dashboard UI, using REST API or aidbox-cli util.

We undertake the maintaining, scaling and updating of your boxes.

Box management is done on the 'Dashboard' page. The 'Dashboard' is a place where you can see all your existing boxes, and create, manage, share and destroy boxes. Each box in the Dashboard has a name, an URL where it will be deployed, a list of users the box is shared with, destroy option and payment plan indicator.

The primary box interface is REST API. Box is expected to be fully compliant to FHIR specification.

Box Management UI Guide

Create a Box

  1. Open Dashboard
  2. Enter a name of your future box
  3. Click on the "Create Box" button
clojure.lang.LazySeq@4380bb94
  1. A new box with the entered name will appear on the dashboard
clojure.lang.LazySeq@4380bb9a

Manage a Box

  1. Open Dashboard
  2. Click on the box name
clojure.lang.LazySeq@37e9f70e

     3. You will be directed to the box dashboard where you will see navigation menu and information about your box like Fhirbase version,           number of users and number of resources in the box:

clojure.lang.LazySeq@37eadfaf

Box Sharing

You can share your box with other aidbox users.

  1. Click the 'Share Box' button
clojure.lang.LazySeq@43812ff8
  1. Find a user in the list to share the box with (you can search by name)
clojure.lang.LazySeq@43812fb7
  1. Close the list
clojure.lang.LazySeq@4382187a
  1. A small circle with initials of the user inside will be displayed under the box's name
clojure.lang.LazySeq@43821895

Box Unsharing

  1. Click the 'Share Box' button
  2. Find a user in the list 'Owners and collaborators' (you can search by name)
  3. Click on the 'Unshare' button
clojure.lang.LazySeq@43812fd4
  1. Close the list

Delete a Box

  1. Open Dashboard
  2. Click the 'Destroy Box' link
clojure.lang.LazySeq@2f61872
  1. Click 'OK' in the confirmation dialog
clojure.lang.LazySeq@2f618ae
  1. The box will be deleted and disappear from the Dashboard

Box Management CLI

Aidbox Account

First, create an account on https://aidbox.io.

Now you need to install aidbox-cli utility globally. Also you may need to install coffee-script.

$ sudo npm install -g coffee-script
$ sudo npm install -g aidbox-cli
$ aidbox v  OK: v0.5.9

Logging In and Out

Let's log in your aidbox.io account throught the aidbox-cli utility:

$ aidbox login  Login: <enter your login>  Password: <enter your password>  OK: Auth success

Then try to log out:

$ aidbox logout  OK: Now you are logged out  OK: All session data has been removed

Getting Started

In order to start working with Aidbox, you have to do 3 things:

  1. Create a box, which will host your application.
  2. Create an implicit client, on behalf of which deploy and authorization will be performed.
  3. Create users of the box.

Box

box is a command for managing boxes. By means of this command it's possible to create new boxes, view a list of all existing boxes, switch between boxes, delete boxes and so on.

To view a list of all possible subcommands, execute:

$ aidbox box help  box                 -- Display current box  box new <boxname>   -- Create new box with specified  <boxname>  box list            -- Display all available boxes  box use <boxname>   -- Switch current box to <boxname>  box destroy         -- Destroy current box [!not ready yet!]

Box Commands

box

Outputs your current box:

$ aidbox box  OK: Your current box is [boxname]

box new

Creates a new box. After creation of a new box, you will be automatically switched to the newly created box context. It means that all futher operations, such as creating users, clients, deploy, etc will be done in this box.

$ aidbox box new <boxname>  INFO: Create new box [boxname]  OK: Box [boxname] has been created  OK: Current box has been switched to [boxname]

box list

Outputs a list of all available boxes.

$ aidbox box list  Outputs a list of all available boxes with their IDs and hosts. For now it's a raw JSON.

box use

Switches a context of command execution to a specified box.

$ aidbox box use <other-box>  OK: Current box has been switched to box [other-box]

box destroy - not ready yet

Deletes current box.

$ aidbox destroy  ; Not ready yet

deploy

deploy command deploys your application to a box. By default it deploys content of the dist folder in the root of your application. You can specify the folder to be depoyed in a box, as well. For example, it can be public, build, etc.

$ aidbox deploy build  INFO: Compress you app...  INFO: Publish app...  OK: You application has been successfully uploaded in box [boxname]  OK: Temp files have been removed

Example Workflow

Here is a typical development workflow. Let us suppose there are two boxes dev-myapp and prod-myapp. Currently you are working in dev-myapp box. When you want to deploy your application on prod-myapp, all you need is to switch context to prod-myapp, execute deploy operation in prod-myapp, come back to dev-myapp and continue development.

Thus, a workflow for two boxes dev-myapp and prod-myapp may look like:

$ aidbox login $ aidbox box new dev-myapp
$ aidbox box new prod-myapp
$ aidbox box use dev-myapp ; Some actions for the development of an application ; Writing code, building application, testing ; Now you need to deploy your application to dev-myapp box ; and nake sure eerything is working
$ aidbox box
$ adibox deploy ; If everything works as intended, you can deploy application to prod-myapp box
$ aidbox box use prod-myapp
$ adibox deploy ; Return back into dev-myapp box
$ aidbox box use dev-myapp ; And continue development

Overview

Each aidbox box has its own users and security rules. You can use REST API, Box Admin UI or aidbox-cli to manage users in an aidbox box. Also you can enable registration module to allow users register in an aidbox box by themselves.

Users could be assigned to groups and for each group you can create specific security rules.

Users and Groups tools are used to create, edit and delete box users and user groups. These users' credentials are used to log in the application working on the top of the aidbox box.

Users and Groups UI Guide

How to add a new group

  • Open the Groups tab
  • Click the 'Create new item' button
clojure.lang.LazySeq@6cb560ac
  • Fill in the fields Name and Description
  • Click the Create button
clojure.lang.LazySeq@6cb5d493

How to add a new user

  • Open the Users tab
  • Click the 'Create new item' button
clojure.lang.LazySeq@6cc21b0d
  • Fill in the fields Email, Password, Data (any valid JSON), select Group-ids (if there are groups)
  • Click the Create button
clojure.lang.LazySeq@6cc28ed4

Search by users and groups

  • To search by users and groups, simply enter the search text in the filter field.
clojure.lang.LazySeq@6ccfbd96
  • Records in the list will be immediately filtered according to your entry.
clojure.lang.LazySeq@6ccfbd9c

How to edit users and groups

  • Select required user or group record in the list
  • Perform necessary editing
  • Click the Save button
clojure.lang.LazySeq@6cb5d4ea
clojure.lang.LazySeq@6cc28f12
clojure.lang.LazySeq@6cb5d4ea
clojure.lang.LazySeq@6cc28f12

How to delete users and groups

  • Select required user or group record in the list
  • Click the Delete button
  • The record will be deleted without confirmation
clojure.lang.LazySeq@6cb5d4ee
clojure.lang.LazySeq@6cc28f15

Users and Groups CLI

User Commands

user is a command for working with users in the current box. To view a list of all available subcommands, execute:

$ aidbox user help  user list                -- Display a list of users in current box  user help                -- Show help information  user new                 -- Create a user via wizard  user new email:password  -- Create a user inline

user list

Outputs a list of all users in current box.

$ aidbox user list  INFO: Display a list of users in box [boxname]  ; For now it displays raw JSON

user new

Creates a new user using a wizard, in current box.

$ aidbox user new  INFO: Create new user in box [boxname]  Email: <test@gmail.com>  Password: <password>  OK: User [test@gmail.com] has been successfully created in box [boxname]

Another command to create a user inline without a wizard, has the following syntax:

aidbox user new email:password

$ aidbox user new test_2@gmail.com:password  INFO: Create new user in box [boxname]  OK: User [test_2@gmail.com] has been successfully created in box [boxname]

Users and Groups REST API

Same tasks can be performed programmatically via REST API.

POST /users

Creates new user.

Example Request:

POST https://[box-name].aidbox.io/users?access_token=[access-token] Accept: application/json Content-Type: application/json {"email": "user@example.com", "password": "godloveskittens", "data": "{}"}

Example Response:

{  "data": null,  "password": "$s0$f0801$PAPMyIhrU98utG2MFZN66w==$L6xOyD4seflK3hzQtQLAQJ6U1PP01x/ciDvSQnxfVIg=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 201 Created // Server: nginx // Date: Thu, 05 May 2016 10:38:44 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.307818s

In case of invalid data you'll receive 422 Unprocessable Entity status:

{  "entity": {    "data": "{}",    "password": "godloveskittens",    "email": "user@example.com"  },  "errors": {    "email": [      "email is already taken"    ]  } } // HTTP/1.1 422 Unprocessable Entity // Server: nginx // Date: Thu, 05 May 2016 10:49:06 GMT // Content-Type: application/json // Content-Length: 126 // Connection: keep-alive // Request duration: 0.514180s

GET /users

Returns list of existing box users.

Example Request:

GET https://[box-name].aidbox.io/users?access_token=[access-token]

Example Response:

[  {    "group-ids": [],    "groups": null,    "data": "{ }",    "email": "user@example.com",    "status": null,    "id": 2  } ] // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 10:51:55 GMT // Content-Type: application/json // Content-Length: 180 // Connection: keep-alive // Request duration: 0.403116s

GET /users/[id]

Retrieves data for specific user.

Example Request:

GET https://[box-name].aidbox.io/users/2?access_token=[access-token]

Example Response:

{  "groups": [],  "data": null,  "password": "$s0$f0801$PAPMyIhrU98utG2MFZN66w==$L6xOyD4seflK3hzQtQLAQJ6U1PP01x/ciDvSQnxfVIg=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 12:53:39 GMT // Content-Type: application/json // Content-Length: 164 // Connection: keep-alive // Request duration: 0.192518s

PUT /users/[id]

Updates existing user.

Example Request:

PUT https://[box-name].aidbox.io/users/2?access_token=[access-token] Accept: application/json Content-Type: application/json {"data": null, "password": "new-password", "email": "user@example.com"}

Example Response:

{  "data": null,  "password": "$s0$f0801$z7Q1dw22tyH5lkHTVSf0hQ==$NpBEXBOCbHty4cURu0FIm7rcSUCTXE3tHaPnE4fT5Ms=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 13:06:19 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.357732s

DELETE /users/[id]

Deletes specific user. Returns data of deleted user.

Example Request:

DELETE https://[box-name].aidbox.io/users/2?access_token=[access-token]

Example Response:

{  "data": null,  "password": "$s0$f0801$z7Q1dw22tyH5lkHTVSf0hQ==$NpBEXBOCbHty4cURu0FIm7rcSUCTXE3tHaPnE4fT5Ms=",  "email": "user@example.com",  "status": null,  "id": 2 } // HTTP/1.1 200 OK // Server: nginx // Date: Thu, 05 May 2016 13:07:35 GMT // Content-Type: application/json // Content-Length: 152 // Connection: keep-alive // Request duration: 0.387985s

Overview

Policy is a JSON schema filtering REST requests. A request succeeds if at least one of the policies is valid for it.

Policies UI Guide

General Information

Let's consider the work of the Basic template. Here is the JSON schema of the template:

{  "type": "object",  "properties": {    "method": {      "constant": "GET"    },    "uri": {      "type": "string",      "pattern": "/fhir.*"    }  } }

In this schema two constraints are introduced:

  1. it is allowed to use only the GET method;
  2. it is allowed to use only request URIs starting with "/fhir".

Below the template selection element there is a tool for debugging. This tool consists of the following elements:

  • HTTP-method selection (GET, POST, PUT, DELETE);
  • command line for entering address, starting with /fhir (implying the base server address going before the slash);
  • the Debug button;
  • the Request Body area.

The Request Body area is used for displaying the request, the schema and the result with errors and warnings if any. 

For debugging the magic key __debug=true is used, so only request validation is performed, and the requests themselves are not executed. 

Let's perform the following tests to check our Basic template:

Positive:

  1. select the GET method
  2. enter the URI /fhir/Patient
  3. click the Debug button
clojure.lang.LazySeq@4380bb9a
clojure.lang.LazySeq@4380bb9a
  1. Part 'result' shows that there are no errors
clojure.lang.LazySeq@4380bb9a

Negative:

  1. select the POST method
  2. enter the URI /users
  3. click the Debug button
clojure.lang.LazySeq@4380bb9a
  1. Part result shows that there are two errors:
  • POST method is used and only GET method is allowed
  • URI should start with /fhir, but it starts with /users
clojure.lang.LazySeq@4380bb9a

How to add a new policy rule

  1. Open the Policies tab
  2. Click the 'Create new item' button
clojure.lang.LazySeq@4380bb9a
  1. Fill in the fields Id, Title, Type, Policy. The 'Policy' field is used to enter a JSON schema. By default the Policy field is preset to the Basic template, you can select another template from available Basic, Advanced and Pro templates
  2. Click the Create button
clojure.lang.LazySeq@4380bb9a

Built-in Help

  1. Click the Help button to get information about possible schema parameters
clojure.lang.LazySeq@4380bb9a
  1. Click the Close button to return to editing policy
clojure.lang.LazySeq@4380bb9a

Search by policy rule

  1. To search by policy rule, simply enter the search text in the filter field.
clojure.lang.LazySeq@4380bb9a
  1. Records in the list will be immediately filtered according to your entry.
clojure.lang.LazySeq@4380bb9a

How to edit a policy rule

  1. Select required policy rule record in the list
  2. Perform necessary editing
  3. Click the Save button
clojure.lang.LazySeq@4380bb9a
clojure.lang.LazySeq@4380bb9a

How to delete a policy rule

  1. Select required policy rule record in the list
  2. Click the Delete button
  3. The record will be deleted without confirmation
clojure.lang.LazySeq@4380bb9a
clojure.lang.LazySeq@4380bb9a

Note: A request succeeds if at least one of the policies is valid for it.

Examples

Allow everything

_Note:_Empty schema allows everything and is not recommended to use.

{}

Read-only access to everything

{  "type" : "object",  "properties" : {   "title" : "Read-only access to everything",    "method" : {      "enum" : [ "GET" ]    }  } }

Access for a client with client_id = site

{ "required" : [ "client" ], "properties" : {   "client" : {     "type" : "object",     "properties" : {       "client_id" : {         "constant" : "site"       }     }   } } }

Allow access for the 'Users' group

{  "required" : [ "user" ],  "properties" : {    "uri" : {      "type" : "string",      "anyOf" : [ {        "pattern" : "/users"      }, {        "pattern" : "/fhir/.+"      } ]    },    "user" : {      "type" : "object",      "required" : [ "groups" ],      "properties" : {        "groups" : {          "not" : {            "items" : {              "properties" : {                "name" : {                  "not" : {                    "enum" : [ "Users" ]                  }                }              }            }          },          "type" : "array",          "items" : {            "type" : "object",            "required" : [ "name" ]          },          "minItems" : 1        }      }    },    "method" : {      "enum" : [ "GET" ]    }  } }

Allow access for all clients

{  "required" : [ "client" ],  "properties" : {    "client" : {      "type" : "object"    }  } }

Checks that user has specific email and at least one group

{  "type" : "object",  "required" : [ "user" ],  "properties" : {    "user" : {      "required" : [ "email", "groups" ],      "properties" : {        "email" : {          "enum" : [ "boxuser1@gmail.com" ]        },        "groups" : {          "type" : "array",          "minItems" : 1        }      }    }  } }

Checks that user has at least one group

{  "required" : [ "user" ],  "properties" : {    "user" : {      "type" : "object",      "required" : [ "groups" ],      "properties" : {        "groups" : {          "type" : "array",          "minItems" : 1        }      }    }  } }

Set access rights for administrators

{  "required" : [ "user" ],  "properties" : {    "uri" : {      "type" : "string",      "title" : "Any string",      "pattern" : ".+"    },    "user" : {      "type" : "object",      "required" : [ "groups" ],      "properties" : {        "groups" : {          "not" : {            "items" : {              "required" : [ "name" ],              "properties" : {                "name" : {                  "not" : {                    "enum" : [ "Administrators" ]                  }                }              }            }          },          "description" : "Should be in Administrators group"        }      }    },    "method" : {      "enum" : [ "GET", "POST", "PUT", "DELETE", "OPTION", "PATCH", "HEAD" ]    }  } }