NAV
cURL python javascript

Dot Health API

Welcome to the Dot Health API! Here, we'll detail the endpoints you can use to access health data stored on our platform.

The Dot Health API is designed to facilitate the exchange of healthcare information between systems, providing a standardized way to represent and retrieve clinical and administrative data.

Our API is organized around REST principles, has resource-oriented URLs and JSON-encoded responses. It employs standard HTTP response codes, authentication methods, and HTTP verbs.

You can utilize the Dot Health API in staging mode, ensuring no impact on your live data or interaction with our organizational networks. The mode (live or test) is determined by the API key used for authentication and the base URL specified in your request.

Production Base URLs

API Requests: https://webapi.dothealth.ca/api/integrations/business/fhir/R5

Authentication Requests: https://webapi.dothealth.ca/auth/api/integrations

Staging Base URLs

API Requests: https://staging.dothealth.ca/api/integrations/business/fhir/R5

Authentication Requests:https://staging.dothealth.ca/auth/api/integrations

Terminology

Health Resource - Any single health record (e.g. allergy, clinical note, diagnostic report). Most health resources would be found in FHIRs level 4 Clinical, Diagnostic, Medications modules.

LOINC - Logical Observation Identifiers Names and Codes; a standardization of terminology for laboratory and clinical observations. More info can be found here.

SNOMED-CT - Systematized Nomenclature of Medicine; a systematically organized computer processable collection of medical terms providing codes, terms, synonyms and definitions used in clinical documentation and reporting. More info can be found here.

Visualization - A trend (ex. over time) generated based off of a collection of health resources.

Authorization

All requests to the Dot API require an access token obtained through one of three currently supported OAuth 2.0 grant types.

1. Client Credentials

Used for machine-to-machine authorization, where the client (your application) directly requests an access token using its own credentials. All information requests, and clients, are created on behalf of your application.

AUTH_URL="https://webapi.dothealth.ca/auth/integrations/token"
GRANT_TYPE="client_credentials"
CLIENT_ID="YOUR_CLIENT_ID"
CLIENT_SECRET="YOUR_CLIENT_SECRET"

response=(curl -X POST $AUTH_URL \
  -H "Content-Type: application/fhir+json" \
  -d '{
        "grant_type": "client_credentials",
        "client_id": "'"$CLIENT_ID"'",
        "client_secret": "'"$CLIENT_SECRET"'"
      }')

echo "Response: $response"
const axios = require('axios');
data = {
  grant_type: "client_credentials",
  client_id: "your_client_id",
  client_secret: "your_client_secret"
}

axios
  .post(
    'https://webapi.dothealth.ca/auth/api/integrations/token',
    {
      body: data
    }
  ).then((result) => console.log(result));
import requests

url = 'https://webapi.dothealth.ca/auth/api/integrations/token'
data = {
  "grant_type": "client_credentials",
  "client_id": "{{client_id}}",
  "client_secret": "{{client_secret}}"
}

response = requests.post(url, json=data)
print(response.json())

Example response:

{
  "access_token": "ACCESS_TOKEN",
  "token_type": "bearer",
  "expires_in": 3600
}

2. Authorization Code

Enables user authentication and access delegation in web and mobile applications. It provides a structured way for applications to obtain access tokens, allowing them to access protected resources on behalf of users.

3. Refresh Token

Used to maintain long-term access to resources on behalf of users, following the authorization code grant, without requiring repeated user interaction. This grant type provides a way to exchange a refresh token for a new access token, extending the validity of the application's access.

Headers

All API requests outlined in this document require the following headers:

Authorization: Bearer {access_token}

Content-Type: application/json

Accept: application/json

Errors

The Authorization API follows standard OAuth 2.0 error responses. Errors will be returned with appropriate HTTP status codes and error descriptions. Refer to the OAuth 2.0 specification for details on error responses.

We use standard HTTP response codes to communicate the outcome of API requests:

Our errors are in accordance with the OperationOutcome resource. Attributes include:

Pagination

Pagination is typically available when retrieving lists of resources that may exceed a predefined limit, for example, you can search patients, organizations, and communication requests.

Search request format

When performing a search request that supports pagination, you can specify parameters to control pagination:

Search response format

The server's response includes a Bundle resource containing the requested resources. Attributes of the searchset type Bundle resource include:

Common Parameters

The parameters below are supported in GET requests for all resources:

Formatting

Reference type URL params should be formatted as <resource type>/id when querying for a particular related resource.

Request Responders

Communication Pattern

To receive and respond to communication requests, our system implements a version of Option C outlined in the Ad-Hoc Workflow Communication Patterns section on the HL7 FHIR website.

Option C: POST of request to placer/queue server system, receiver uses polling or subscription

Image of Ad-Hoc Workflow Option C.

Figure 1. Communication Pattern C. Source: Health Level Seven International, 2023, https://build.fhir.org/workflow-ad-hoc.html#optionb

Worfklow:

  1.  Dot Health creates a 'request' resource (i.e. CommunicationRequest) and places an "actionable" tag on the resource that indicates the request is intended to be acted upon. The request explicitly identifies the intended fulfiller.

  2.  The filler system uses polling (or a subscription) at the placer or queue server system to see if there are any "new" requests that: are tagged as "actionable", and are a type of request "of interest" to the filler.

  3.  The filler creates an 'event' resource (e.g. MedicationDispense, DiagosticReport, Encounter, etc.) via a POST request to Dot Health. Resources created by the filler must include a reference to the ‘CommunicationRequest’ resource that the action was performed in fulfillment of, inside the `basedOn` field if available.

     This step differs from step 5 in Figure 1. in that currently we can not poll another system for ‘event’ resources, they must be created on our system via POST requests. When responding to a communication request, the event resources may be encapsulated within a FHIR Bundle of type transaction.

     The resource field within each bundle entry should contain the complete FHIR resource, such as Observation, or DiagnosticReport, with all necessary attributes and values filled in according to the FHIR specification. This transactional approach allows multiple resources to be submitted as a cohesive unit, ensuring that all related clinical data pertaining to the patient and the original communication request are processed together.

     A CommunicationRequest will be marked as ‘complete’ if a Communication resource is included in the Bundle where Bundle.replaces contains a reference to the CommunicationRequest.

Example: Respond to CommunicationRequest with Bundle

URL="$BASE_URL/Bundle"
const axios = require('axios');
const URL=`${BASE_URL}/Bundle`
import requests

URL=f'{BASE_URL}/Bundle'
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:1",
      "resource": {
        "resourceType": "Communication",
        "status": "completed",
        "intent": "filler-order",
        "replaces": [{
       reference: "https://staging.dothealth.ca/api/integrations/business/fhir/R5/CommunicationRequest/123"
       type: "CommunicationRequest"
   }],
        "payload": [
          {
            "contentString": "Here are the lab results."
          }
        ]
      }
    },
    {
      "fullUrl": "urn:uuid:2",
      "resource": {
        "resourceType": "Observation",
        "status": "final",
        "basedOn": [{
       reference: "https://staging.dothealth.ca/api/integrations/business/fhir/R5/CommunicationRequest/123"
       type: "CommunicationRequest"
   }],
        "category": [
          {
            "coding": [
              {
                "system": "http://terminology.hl7.org/CodeSystem/observation-category",
                "code": "vital-signs",
                "display": "Vital Signs"
              }
            ]
          }
        ],
        "code": {
          "coding": [
            {
              "system": "http://loinc.org",
              "code": "85354-9",
              "display": "Blood pressure panel with all children optional"
            }
          ]
        },
        "subject": { "reference": "Patient/123" },
        "effectiveDateTime": "2024-06-18T00:00:00Z",
        "valueQuantity": {
          "value": 120,
          "unit": "mmHg",
          "code": "mm[Hg]"
        }
      }
    }
  ]
}
response=(curl -X POST $URL \
  -H "Content-Type: application/fhir+json" \
  -H "Authentication: Bearer $token"
  -d '"'$BUNDLE'"')

echo "Response: $response"
axios
  .post(
    URL,
    {
      body: bundle
    }
  ).then((result) => console.log(result));
response = requests.post(url, json=data)
print(response.json())

Example response:

{
  "resourceType": "Bundle",
  "type": "transaction-response",
  "entry": [
    {
      "response": {
        "status": "201 Created",
        "location": "Communication/123"
      }
    },
    {
      "response": {
        "status": "201 Created",
        "location": "Observation/456"
      }
    }
  ]
}

CommunicationRequests

An object which stores a request for health records.


GET /CommunicationRequest

Retrieve a list of communication request resources.

Query Parameters

In addition to common and pagination parameters:

Parameter Name Type Description
_sort status | priority | lastUpdated Sort the results by specified fields
_include Organization:recipient | Organization:requestor | Patient:subject Include related resources. Format is <resource type>:<field name>
_status draft | active | on-hold | revoked | completed | entered-in-error | unknown Search for communication requests by status
_priority routine | urgent | asap | stat Search for communication requests by priority
_patient Reference(Patient) Search for communication requests by subject reference
_requester Reference(Practitioner) Search for communication requests by requester reference
const axios = require('axios');
const URL = `${BASE_URL}/CommunicationRequest?status=active&priority=urgent&_count=10`

axios
  .get(URL
  headers: {
    Content-Type: 'application/fhir+json',
    Authorization: token
  }
  ).then((result) => console.log(result));
import requests

url = f'{BASE_URL}/CommunicationRequest?status=active&priority=urgent&_count=10'
headers = {
  "Content-Type": "application/fhir+json",
  "Authorization": token
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
URL="$BASE_URL/CommunicationRequest?status=active&priority=urgent&_count=10"

response=(curl -X POST $URL \
  -H "Content-Type: application/fhir+json" \
  -H "Authorization: 'Bearer $TOKEN'"
)
echo "$response"

Example response:

{
  "resourceType": "Bundle",
  "id": "bundle-02",
  "type": "searchset",
  "total": 1,
  "link[0]": {
    "relation": "self",
    "url": "https://webapi.dothealth.ca/api/integrations/business/fhir/R5/CommunicationRequest?status=active&priority=urgent&_count=10"
  },
  "entry[0]": {
    "fullUrl": "https://webapi.dothealth.ca/api/integrations/business/fhir/R5/CommunicationRequest/12345",
    "resource": {
      "resourceType": "CommunicationRequest",
      "id": "12345",
      "status": "active",
      "intent": "directive",
      "priority": "urgent",
      "category[0]": {
        "coding[0]": {
          "system": "http://terminology.hl7.org/CodeSystem/communication-category",
          "code": "instruction",
          "display": "Instruction"
        }
      },
      "about[0]": {
        "type": "DiagnosticReport",
        "display": "DiagnosticReport"
      },
      "subject": {
        "reference": "Patient/67890"
      },
      "authoredOn": "2023-01-01",
      "requester": {
        "reference": "Organization/67890"
      },
      "payload[0]": {
        "contentString": "Requesting medical records for the patient."
      },
      "payload[1]": {
        "contentReference": {
          "type": "Consent",
          "reference": "https://staging.dothealth.ca/api/integrations/business/fhir/R5/Consent"
        }
      }
    }
  }
}

Subscriptions

An object used to establish proactive event notifications from a FHIR server to another system.


GET /Subscription

Retrieve a list of subscription resources.

Query Parameters

In addition to common parameters:

Parameter Name Type Description
_topic URI Search by the canonical topic url that triggers notifications
_status requested | active | error | off | entered-in-error Search by the current subscription status
const axios = require('axios');
const URL = `${BASE_URL}/Subscription?topic=communication-request&status=active`

axios
  .get(URL
  headers: {
    Content-Type: 'application/fhir+json',
    Authorization: `Bearer: ${token}`
  }
  ).then((result) => console.log(result));
url = f'{BASE_URL}/Subscription?topic=communication-request&status=active'
headers = {
  "Content-Type": "application/fhir+json",
  "Authorization": token
}
response = requests.get(url, json=data, headers=headers)
print(response.json())
URL="$BASE_URL/Subscription?topic=communication-request&status=active"

response=(curl -X GET $URL \
  -H "Content-Type: application/fhir+json" \
  -H "Authorization: 'Bearer $TOKEN'"
)
echo "$response"

Example response:

{
  "resourceType": "Bundle",
  "type": "searchset",
  "entry": [
    {
      "fullUrl": "https://webapi.dothealth.ca/api/integrations/business/fhir/R5/Subscription/123",
      "resource": {
        "resourceType": "Subscription", 
            "name": "Example Subscription",
            "topic": "communication-request",
        "status": "active",
            "end": "2024-08-07T11:15:18Z",
            "reason": "Monitor communication requests updates for this institution",
            "filterBy": [],
            "channelType": {
                "code": "rest-hook"
            },
            "endpoint": "https://hospital.com/subscription/CommunicationRequest/1",
            "parameter" : [{
                "name": "Authorization",
                "value": "Bearer secret-token-abc-123"
            }],
            "contentType": "application/json",
            "content": "id-only"
      }
    }
  ]
}


POST /Subscription

Create a subscription resource.

const axios = require('axios');
const URL=`${BASE_URL}/Subscription`

const subscription = {
  "resourceType": "Subscription", 
  "name": "Example Subscription",
  "topic": "communication-request",
  "end": "2024-08-07T11:15:18Z",
  "reason": "Monitor communication requests updates for this institution",
  "filterBy": [],
  "channelType": {
      "code": "rest-hook"
  },
  "endpoint": "https://your_domain.com/subscription/CommunicationRequest/1",
  "parameter" : [{
      "name": "Authorization",
      "value": "Bearer secret-token-abc-123"
  }],
  "contentType": "application/fhir+json",
  "content": "id-only"
}

axios
  .post(
    URL,
    {
      body: subscription,
      headers: {
        Content-Type: 'application/fhir+json',
        Authorization: `Bearer: ${token}`
      }
    }
  ).then((result) => console.log(result));
import requests

URL=f'{BASE_URL}/Subscription'
headers = {
  "Content-Type": "application/fhir+json",
  "Authorization": token
}

subscription = {
  "resourceType": "Subscription", 
  "name": "Example Subscription",
  "topic": "communication-request",
  "end": "2024-08-07T11:15:18Z",
  "reason": "Monitor communication requests updates for this institution",
  "filterBy": [],
  "channelType": {
      "code": "rest-hook"
  },
  "endpoint": "https://your_domain.com/subscription/Subscription/1",
  "parameter" : [{
      "name": "Authorization",
      "value": "Bearer secret-token-abc-123"
  }],
  "contentType": "application/fhir+json",
  "content": "id-only"
}

response = requests.post(url, json=data, headers=headers)

print(response.json())
URL="$BASE_URL/Subscription"

SUBSCRIPTION='{
  "resourceType": "Subscription", 
  "name": "Example Subscription",
  "topic": "communication-request",
  "end": "2024-08-07T11:15:18Z",
  "reason": "Monitor communication requests updates for this institution",
  "filterBy": [],
  "channelType": {
      "code": "rest-hook"
  },
  "endpoint": "https://your_domain.com/subscription/Subscription/1",
  "parameter" : [{
      "name": "Authorization",
      "value": "Bearer secret-token-abc-123"
  }],
  "contentType": "application/fhir+json",
  "content": "id-only"
}'

response=(curl -X POST $URL \
  -H "Content-Type: application/fhir+json" \
  -H "Authorization: 'Bearer $TOKEN'" \
  -d '"'$SUBSCRIPTION'"')
)
echo "$response"

Example response:

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "information",
    "code": "informational",
    "details": { "text" : "All OK" }
  }]
}


DELETE /Subscription

Delete a subscription resource.

const axios = require('axios');
const URL = `${BASE_URL}/Subscription/1234`

axios
  .delete(URL
  headers: {
    Content-Type: 'application/fhir+json',
    Authorization: `Bearer: ${token}`
  }
  ).then((result) => console.log(result));
import requests

url = f'{BASE_URL}/Subscription/1234'
headers = {
  "Content-Type": "application/fhir+json",
  "Authorization": token
}
response = requests.delete(url, json=data, headers=headers)
print(response.json())
URL="$BASE_URL/Subscription/1234"

response=(curl -X DELETE $URL \
  -H "Content-Type: application/fhir+json" \
  -H "Authorization: 'Bearer $TOKEN'"
)
echo "$response"

Example response:

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "information",
    "code": "informational",
    "details": { "text" : "All OK" }
  }]
}

Health Resources

The table below contains the FHIR resources which may be included in transaction Bundles by request responders, see Example: Respond to CommunicationRequest with Bundle example, and received by request creators. The table's endpoint column displays the POST request endpoint, if created individually. For more information, see a detailed description of our health data models here.

Resource Type Endpoint
AdverseEvent /AdverseEvent
AllergyIntolerance /AllergyIntolerance
Appointment /Appointment
CarePlan /CarePlan
Communication /Communication
CommunicationRequest /CommunicationRequest
Condition /Condition
Consent /Consent
DeviceDispense /DeviceDispence
DeviceUsage /DeviceUsage
DiagnosticReport /DiagnosticReport
DocumentReference /DocumentReference
Encounter /Encounter
EpisodeOfCare /EpisodeOfCare
FamilyMemberHistory /FamilyMemberHistory
Goal /Goal
Group /Group
ImagingStudy /ImagingStudy
Immunization /Immunization
Invoice /Invoice
Medication /Medication
MedicationAdministration /MedicationAdministration
MedicationDispense /MedicationDispense
MedicationRequest /MedicationRequest
MedicationStatement /MedicationStatement
Observation /Observation
Organization /Organization
Patient /Patient
Practitioner /Practitioner
Procedure /Procedure
QuestionnaireResponse /QuestionnaireResponse
RiskAssessment /RiskAssessment
ServiceRequest /ServiceRequest

Support

If you have any questions, need further assistance, or find that something is missing from this documentation, please don't hesitate to contact us at care@dothealth.ca. We are here to help you make the most out of our API.