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:
- 2xx Range: Indicates a successful operation.
- 4xx Range: Indicates client errors, such as invalid requests or missing parameters.
- 5xx Range: Indicates server errors, where the request could not be fulfilled due to issues on our end.
Our errors are in accordance with the OperationOutcome resource. Attributes include:
- resourceType: Indicates the type of resource being returned, which is always "OperationOutcome" for error responses.
- issue: An array containing details about the encountered issue(s). Each item in the array includes:
- severity: Indicates the severity of the issue ("error" for client errors, "fatal" for server errors).
- code: A short string indicating the specific error code. This code is designed to aid in programmatically handling errors and is usually specific to the operation that encountered the issue.
- diagnostics: A human-readable message providing additional details about the error.
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:
- _count: Specifies the maximum number of resources to return per page. This parameter helps control the size of each page of results.
- _page: Indicates the specific page of results to retrieve.
- Other Parameters: Depending on the resource type, additional parameters like _sort, _filter, or specific search criteria (name, status, etc.) may be available to refine results.
Search response format
The server's response includes a Bundle resource containing the requested resources. Attributes of the searchset type Bundle resource include:
- resourceType: Always "Bundle" for search responses.
- type: Indicates the type of bundle ("searchset").
- total: The total number of matching resources across all pages.
- link: An array of elements in the response to navigate between pages.
- entry: An array containing a list of resources. Each item in the array contains:
- fullUrl: Complete URLs which may be used to retrieve the resource.
- resource:: A resource in the bundle matching the request resource type. If using the ‘_include’ search parameter, full resources related to the primary resources are also returned.
Common Parameters
The parameters below are supported in GET requests for all resources:
- _id: Search parameter used to allow searching based on the logical identifier of resources (Resource.id). The parameter requires a resource type specified in the search context - it can only be used in searches that contain a [type] component in the search request.
- _lastUpdated: Filters resources based on when they were last updated. This parameter supports date and time ranges.
- _language:The standard search parameter _language is used to match resources based on the language of the resource used. Note that match testing is performed against the element Resource.language and does not match against the actual language used in elements.
- _source: The standard search parameter _source is used to match resources based on source information in the Resource.meta.source element.
- _tag: standard search parameter _tag is used to match resources based on tag information in the Resource.meta.tag element.
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
Figure 1. Communication Pattern C. Source: Health Level Seven International, 2023, https://build.fhir.org/workflow-ad-hoc.html#optionb
Worfklow:
- 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.
- 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.
-
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.