Virtual Care

v9

DexCare offer an on-demand virtual (ODV) platform for booking and conducting telemedicine visits via video.

The DexCare APIs allow these visits to be booked programmatically so health systems may develop their own booking flows.

This page walks you through the API calls required to book a virtual visit and direct the patient end user into the DexCare virtual visit waiting room.

See the previous version of the API here

The calls below assume that the user interface (UI) will provide information to the user about whether the virtual clinic is open. If the clinic is open, the UI will display the current duration of time the user must wait in order to be seen. This duration is known as the Wait Time.

The user will then need to sign-in before progressing to the waiting room.  

This flow requires the following additional pieces of patient information (to being signed in):  

  • the patient’s current location (selected from a pulldown of “practice regions”)
  • the patient’s major complaint / reason-for-visit.  

The following order of operations will be used to create the virtual visit

  1. Retrieving Practice Region Availability
  2. Retrieving Region Wait Times
  3. Retrieving Patient Identifying Information
  4. Creating Visits

Alternatively, client applications may skip the step of retrieving patient information and book an appointment by submitting patient information along with the visit request as part of our Guest Booking Flow.

Once a visit has been created it is possible to Retrieve a Visit Summary

New API Features

For the v9 release, DexCare has added a number of important new features for filtering wait times and creating visits.

Visit Types

In v9 of the DexCare API, the concept of “visit type” was introduced to allow alternate patients to be provided with care via different modalities, such as by phone or virtually via video teleconference.

The v9 API allows clients to specify this visitType as part of the request to create a visit.

Assignment Qualifiers

Another concept introduced as part of the v9 API was the notion of an “assignment qualifier” to allow different types of patients to be directed to providers that suitable for providing those patients care.

This allows, for instance, the system to make a distinction between adult and pediatric patients, in which case only certain providers would be suited for the latter.

The available assignment qualifiers may be retrieved via the Assignment Qualifiers service located at the following endpoint:

https://ecvapi.[servername]/api/9/assignmentqualifiers

View the Open API specification

Language Requirements

The API now allows a flag to be set when the patient is requesting a provider that supports a given language.

This is an open metadata field, though DexCare recommends specifying languages using an ISO 639-3 code.

Urgency

The urgency flag is used to indicate the level of urgency of the patient’s visit.

This is a numeric value to allow for future functionality that will include ranking, but effectively now it is either on (non zero value) or off (0).

The default is 0.

Assessment Tool

The assessment tool field allows clients to indicate what sort of pre-assessment tool was used to evaluate the patient prior to putting them into the queue, such as ADA

Retrieving Practice Region Availability

Virtual Visits are delivered based on a Practice Region.

Practice Regions in the DexCare API correspond to a state provider licensure.

Practice Regions are used to collect the physical location of the patient to assign them to a properly licensed provider.

You will use Practice Regions to query if service is available (i.e. is the clinic open), hours of operation, and wait times.

Initiate a call to get the list of selectable Practice Regions based on the identifier of the Practice. 

Endpoint

https://ecvapi.[servername]/api/8/DexCare/practices/{practiceId}

Example Call

curl -H "Host: you.host" -H "accept: */*" -H "content-type: application/json"  \
-H "domain: your.domain" -H "correlation-id: [your-correlation-id]" \
-H "x-api-key: [yourapikey]" -H "accept-language: en-US,en;q=0.9" \
"https://your.domain.co/api/8/practices/[your-practice-id]?product=[yourproduct]"

Parameters

practiceId

identifier for a Practice belonging to a client. This value is set up and provided by DexCare and may be hardcoded in your application.

REQUIRED

type: path
default: N/A
example: 0cee700e-f4c1-4459-b390-263e4ded436c
(Acme)
values: string

product

namespace particular to a given client

OPTIONAL

type: query
default: N/A
example: healthconnect
values: string

Responses

200

A practice entity instance is returned.

{
	"id": "6996d161-cd16-4556-9577-f942c3f80c80",
	"displayName": "Virtual Visits",
	"careMode": "virtual",
	"payment": {
		"insurance": true,
		"selfPay": true,
		"serviceKey": true
	},
	"epicBookingEnabled": true,
	"practiceRegions": [{
		"id": "333bc7df-b368-4cee-9992-9abeef54dbed",
		"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
		"displayName": "California",
		"regionCode": "CA",
		"active": true,
		"availability": [{
			"start": "2021-11-14T08:00:00.000Z",
			"end": "2021-11-15T07:59:00.000Z"
		}, {
			"start": "2021-11-15T08:00:00.000Z",
			"end": "2021-11-16T07:59:00.000Z"
		}, {
			"start": "2021-11-16T08:00:00.000Z",
			"end": "2021-11-17T07:59:00.000Z"
		}, {
			"start": "2021-11-17T08:00:00.000Z",
			"end": "2021-11-18T07:59:00.000Z"
		}, {
			"start": "2021-11-18T08:00:00.000Z",
			"end": "2021-11-19T07:59:00.000Z"
		}, {
			"start": "2021-11-19T08:00:00.000Z",
			"end": "2021-11-20T07:59:00.000Z"
		}, {
			"start": "2021-11-20T08:00:00.000Z",
			"end": "2021-11-21T07:59:00.000Z"
		}],
		"busy": false,
		"busyMessage": "Providers are currently at capacity and closed",
		"paymentAccountId": "8d4c9407-e1f3-4d4e-b2a1-ed964522151c",
		"visitPrice": 4900,
		"orderWeight": 0,
		"departments": [{
			"id": "4d2a72d5-41d5-462d-985b-9e2ce41c1570",
			"epicDepartmentId": "405772000",
			"ehrSystemName": "org.providence.dig.epic.provorca",
			"defaultDepartmentName": "Interstate"
		}],
		"market": "default"
	}, {
		"id": "8a43204f-f0ef-4dcb-ac9d-4e68ddb2ca87",
		"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
		"displayName": "Montana",
		"regionCode": "MT",
		"active": true,
		"availability": [{
			"start": "2021-11-14T08:00:00.000Z",
			"end": "2021-11-15T07:59:00.000Z"
		}, {
			"start": "2021-11-15T08:00:00.000Z",
			"end": "2021-11-16T07:59:00.000Z"
		}, {
			"start": "2021-11-16T08:00:00.000Z",
			"end": "2021-11-17T07:59:00.000Z"
		}, {
			"start": "2021-11-17T08:00:00.000Z",
			"end": "2021-11-18T07:59:00.000Z"
		}, {
			"start": "2021-11-18T08:00:00.000Z",
			"end": "2021-11-19T07:59:00.000Z"
		}, {
			"start": "2021-11-19T08:00:00.000Z",
			"end": "2021-11-20T07:59:00.000Z"
		}, {
			"start": "2021-11-20T08:00:00.000Z",
			"end": "2021-11-21T07:59:00.000Z"
		}],
		"busy": false,
		"busyMessage": "Providers are currently at capacity and closed",
		"paymentAccountId": "8d4c9407-e1f3-4d4e-b2a1-ed964522151c",
		"visitPrice": 4900,
		"orderWeight": 0,
		"departments": [{
			"id": "4d2a72d5-41d5-462d-985b-9e2ce41c1570",
			"epicDepartmentId": "405772000",
			"ehrSystemName": "org.providence.dig.epic.provorca",
			"defaultDepartmentName": "Interstate"
		}],
		"market": "default"
	}]
}

praticeRegions
List of Practice Regions belonging to the Practice that can be shown to the user in a UI element such as select box. 
Within the Practice Regions are a list of availability instances that define the start and end times for potential appointments.
You will need to add “Other” to the list returned.  If the user selects “Other” you will want to provide a message that they are out of service area.  

Retrieving Region Wait Times

After the user selects a supported Practice Region you will need to call the following endpoint to determine the wait time for that region using its regionCode.

Users of previous versions of the API please note that you will use the regionCode property instead of the id the practiceRegion in subsequent calls

The wait times that are returned distinguished from each other based on properties such as assignment qualifiers and visit types which may also be used as filters.

Endpoint

https://ecvapi.[servername]/api/9/regions/waittimes

View the Open API specification

See the Open API Specification for the visit service for the full documentation on this endpoint.

Example Call

curl -H "Host: [your.host]" -H "accept: */*" -H "content-type: application/json" \
-H "domain: [your.domain]" -H "correlation-id: [your-correlation-id]" -H "accept-language: en-US,en;q=0.9" \
 "https://your.host.com/api/9/regions/waittimes?regionCodes[]=WA&practiceId=[yourpracticeid]&product=[yourproduct]"

Parameters

regionCodes

REQUIRED

The identifier for the region for which availability is being queried, typically the two letter state code

type: query
default: N/A
example: WA
values: string array

practiceId

identifier for a Practice belonging to a client. This value is set up and provided by DexCare and may be hardcoded in your application.

REQUIRED

type: query
default: N/A
example: 0cee700e-f4c1-4459-b390-263e4ded436c
(Acme)
values: string

assignmentQualifiers

additional assignment qualifiers to filter provider queue (i.e. pediatric or adult)

OPTIONAL

type: query
default: N/A
example: pediatric
values: string array

visitTypeNames

distinguishes between modalities of visit such as virtual visits (done via video) vs those done by phone

OPTIONAL

type: query
default: N/A
example: virtual
values: string array

product

namespace particular to a given client

OPTIONAL

type: query
default: N/A
example: healthconnect
values: string

Responses

200

Returns an “available” state (true or false), and if not available, it will also return the reason why.

If the Region is available (available == true) then the booking button can be set to an active state with the display of a wait time.

If the Region is not available, it is recommended that the user not be allowed to proceed and be displayed the correct messaging.

[{
	"available": true,
	"estimateGeneratedAt": "2021-11-18T19:17:52.435Z",
	"estimatedWaitTimeSeconds": 560,
	"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
	"regionCode": "WA",
	"visitTypeName": "phone",
	"assignmentQualifiers": ["adult"]
}, {
	"available": false,
	"estimateGeneratedAt": "2021-11-18T19:17:52.441Z",
	"reason": "NO_ONCALL_PROVIDERS",
	"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
	"regionCode": "WA",
	"visitTypeName": "phone",
	"assignmentQualifiers": ["testNewAssignmentQualifier_849b9d3f-3b6e-486f-bfa7-bf226ff8ec30"]
}]
available
indicates whether or not the practice is available as a boolean value
reason
enumeration that describes why the practice is not available
values include: OFF_HOURS NO_ONCALL_PROVIDERS REGION_BUSY UNKNOWN

Retrieving Patient Identifying Information

A Patient guid or other patient identifying information is necessary to create a visit.

Our page on Patient related APIs details how this information may retrieved or added to the system.

If you system is generating data in Epic directly and not through DexCare, you will not use our patient guid.

Instead you will supply the following three fields:

  • ehrIdentifier
  • ehrIdentifierType
  • homeEhr

Creating Visits

The final step in this workflow will create a visit within DexCare’s system as well as an appointment in Epic.

Endpoint

POST /api/9/visits

Parameters

Body Schema

Example Virtual Visit Request Payload

{
   "patient":{
      "gender":"mail",
      "phone":"204-555-3233",
      "firstName":"Joe",
      "address":{
         "line2":"Box #1",
         "state":"WA",
         "line1":"312 S Washington St",
         "city":"Seattle",
         "postalCode":"98104"
      },
      "patientGuid":"12341234-129f-4d0e-afaa-b3009dbe80c7",
      "dateOfBirth":"1970-01-01T00:00:00.000Z",
      "email":"patent.email@dexcarehealth.com",
      "lastName":"Public"
   },
   "visitDetails":{
      "practiceId":"6996d161-cd16-4556-9577-f942c3f80c80",
      "stateLicensure":"WA",
      "visitTypeName":"virtual",
      "visitReason":"zzzIntegrationTests visit reason",
      "brand":"providence",
      "acceptedTerms":true,
      "declaration":"self"
   },
   "billingInfo":{
      "couponCode":"kyle1",
      "paymentMethod":"couponcode"
   }
}

Example Phone Visit Request Payload

The following payload sent to the v9 version of the end point would result in a phone visit being created,

This example also illustrates using an ehrIdentifier, ehrIdentifierType, and homeEhr instead of a patient guid.

{
  "billingInfo": {
    "paymentMethod": "insurance",
    "declaration": "self",
    "insuranceType": "manual",
    "insuranceProviderId": "kpvirtual",
    "insuranceMemberId": "internal"
  },
  "patient": {
    "firstName": "Sinjoro",
    "lastName": "Ajnulo",
    "gender": "male",
    "dateOfBirth": "1970-01-13",
    "phone": "202-555-1212",
    "email": "sinjoro.anjulo@example.com",
    "address": {
      "line1": "123 Main Street",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    },
    "ehrIdentifier": "M123456",
    "ehrIdentifierType": "MRN",
    "homeEhr": "MAM",
    "homeMarket": "MAS"
  },
  "visitDetails": {
    "acceptedTerms": true,
    "assignmentQualifiers": [
      "adult"
    ],
    "declaration": "self",
    "stateLicensure": "WA",
    "visitReason": "Example request for a phone visit",
    "visitTypeName": "phone"
  }
}

Example Patient Proxy Payload

This example shows how a pediatric visit would be created where the user creating the visit (the actor) is not the same as the patient.

{
  "actor": {
    "firstName": "Actor",
    "lastName": "Proxy",
    "gender": "female",
    "dateOfBirth": "1970-01-13",
    "phone": "202-555-1212",
    "email": "actor.proxy@example.com",
    "address": {
      "line1": "123 Main Street",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    },
    "ehrIdentifier": "M123456",
    "ehrIdentifierType": "MRN",
    "homeEhr": "MAM"
  },
  "billingInfo": {
    "paymentMethod": "insurance",
    "declaration": "other",
    "insuranceType": "manual",
    "insuranceProviderId": "kpvirtual",
    "insuranceMemberId": "internal",
    "firstName": "Insurance",
    "lastName": "Member",
    "gender": "female",
    "dateOfBirth": "1971-03-15"
  },
  "patient": {
    "firstName": "Sinjoro",
    "lastName": "Ajnulo",
    "gender": "male",
    "dateOfBirth": "2010-02-14",
    "phone": "202-555-1212",
    "email": "sinjoro.anjulo@example.com",
    "address": {
      "line1": "123 Main Street",
      "city": "Seattle",
      "state": "WA",
      "postalCode": "98101"
    },
    "ehrIdentifier": "M123456",
    "ehrIdentifierType": "MRN",
    "homeEhr": "MAM",
    "homeMarket": "MAS"
  },
  "visitDetails": {
    "acceptedTerms": true,
    "assignmentQualifiers": [
      "pediatric"
    ],
    "declaration": "other",
    "stateLicensure": "WA",
    "visitReason": "Example visit of a proxy submitting visit for a child",
    "interpreterLanguage" : "es-MX",
    "urgency" : 1
    
  }
}

Important Payload Properties

For full details, see the OpenAPI Specification for the v9 visits API.

patient
in cases where the patient is requesting a visit for themselves, this information will match the patient information retrieved from GET /v1/patient. When the user requesting visit is acting on behalf of the patient, this information will match the patient information defined in a call to /v1/patient/other
actor
information provided when booking on behalf of another person information, such as a guardian to a patient for child visits. Required when visitDetails.declaration is other and should not be in the request payload when visitDetails.declaration is self
billingInfo
required properties vary based on the paymentMethod selected. N.B. not all payment methods are supported for each service and some payment methods require setup from your DexCare contact

billingInfo for a credit card through Stripe:

...
"billingInfo": { 
    "paymentMethod": "creditcard", 
    "stripeToken": "TokenFromStripe" 
  }
...

billingInfo for a coupon code or service key:

...
"billingInfo": { 
    "paymentMethod": "couponcode", 
    "couponCode": "aSecretServiceKey", 
  }
...

billingInfo when a patient is using their own insurance:

...
"billingInfo": { 
    "paymentMethod": "insurance", 
    "declaration": "self", 
    "firstName": "patient first name", 
    "lastName": "patient last name", 
    "gender": "enum: 'male' | 'female' | 'other' ", 
    "dateOfBirth": "YYYY-MM-DD", 
    "insuranceType": "manual", 
    "insuranceProviderId": "patient insurance provider id", 
    "insuranceMemberId": "patient insurance membership id", 
  }
...

billingInfo when a patient is using someone else’s insurance:

...
"billingInfo": { 
    "paymentMethod": "insurance", 
    "declaration": "other", 
    "firstName": "first name of the primary insurance holder", 
    "lastName": " last name of the primary insurance holder", 
    "gender": "enum: 'male' | 'female' | 'other' ", 
    "dateOfBirth": "YYYY-MM-DD", 
    "insuranceType": "manual", 
    "insuranceProviderId": "insurance holder insurance provider id", 
    "insuranceMemberId": "insurance holder membership id", 
  }
...
visitDetails.assessmentToolUsed
if patient has done preassessment, which tool was used
visitDetails.assignmentQualifiers
This field will be used to specify any assignment qualifiers (e.g. pediatric or adult)
visitDetails.departmentId
identifier for the department in which visit will be conducted. Use the id of a department returned when you selected a practice region
visitDetails.declaration
indicates if the visit is for the current user (self) or someone else (other)
visitDetails.ehrSystemName
allows support for health systems with more than one EHR/EMR instance. Use the ehrSystemName of a department returned when you selected a practice region
visitDetails.interpreterLanguage
optional language requested if interpreter services are available — use ISO 639-3 Individual Language codes
visitDetails.practiceRegionId
Practice Region in which the patient is currently located — alows for virtual MA to triage patients that might be outside of treatment area
visitDetails.urgency
urgency rating; 0 for default urgency
visitDetails.visitReason
patient’s major complaint / symptom. This is used by the virtual MA for triaging patients. 
visitDetails.visitTypeName
This field will be used to specify the modality of the visit (e.g. virtual or phone)

Responses

200

The returned payload is a Visit containing the visitId necessary to navigate to the “waiting room”

i.e. a Waiting Room URL: DexCare/visit/{visitID}?brand={brandID} AUTH TOKEN REQUIRED

{
	"visitId": "241f29d1-3402-4a00-b74b-064d28d22596",
	"patientGuid": "233441f4-129f-4d0e-afaa-b3009dbe80c7",
	"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
	"visitRedirectUrl": "https://th.frosh.dex.care/visit/241f29d1-3402-4a00-b74b-064d28d22596?brand=providence",
	"tokBoxVisit": {
		"waitingRoomSession": {
			"sessionId": "2_MX40NjQ5NzM1Mn5-MTYzNzI2MzA3MzU2Mn5pcktjWSsreTF5bFBIQ25lOHUvb1B2L1B-fg"
		},
		"videoConferenceSession": {
			"sessionId": "1_MX40NjQ5NzM1Mn5-MTYzNzI2MzA3MzgzMn5VbDFaRjc2R2J0UGRaWENUQzZRTTdyN2R-fg"
		}
	}
}
visitId
needed by the browser to navigate into the waiting room

400

Bad request; See response for info

404

Practice not found

500

Internal error

Guest Booking Flow

The guest booking flow consolidates the process of booking patients described above by allowing client applications to submit patient information as part of the the booking request instead of looking it up separately.

For this API, looking up Practice Regions is also not a required step.

Endpoint

POST /v1/booking/queued-guest-visit

Example Call

The full OAS details the parameters in full.

Below is a sample request used to submit to the guest booking endpoint.

{
    "patient": {
        "firstName": "first",
        "lastName": "last",
        "email": "first.last@foo.bar.baz",
        "phone": "206-789-0123",
        "gender": "male",
        "dateOfBirth": "1958-06-07",
        "address": {
            "line1": "2324 Eastlake Ave",
            "city": "Seattle",
            "state": "WA",
            "postalCode": "98102"
        }
    },
    "billingInfo": {
        "paymentMethod": "insurance",
        "declaration": "self",
        "insuranceType": "manual",
        "insuranceProviderId": "string",
        "insuranceMemberId": "string"
    },
    "visitDetails": {
        "visitTypeName": "virtual",
        "acceptedTerms": true,
        "declaration": "self",
        "stateLicensure": "WA",
        "visitReason": "reasons",
        "brand": "providence"
    }
}

Responses

200

The returned payload contains the Url required to redirect users to the waiting room.

{
  "visitId": "<uuid>",
  "visitRedirectUrl": "<string>"
}

Retrieving Visit Summaries

Once a visit has been created, it is possible to retrieve its data using the summary endpoint.

The results from this call will allow you to display the current status and type of the visit.

Endpoint

/api/9/visits/{visitId}/summary

Example Call

curl -H "Host: [your.host]" -H "domain: [your.domain]" -H "content-type: application/json" \
-H "accept: */*" -H "accept-language: en-US,en;q=0.9" -H "correlation-id: [your-correlation-id]" \
-H "x-api-key: [your-api-key]"" -H "authorization: Bearer [your-auth-token]" \
"https://your.host.com/api/9/visits/[your.visit.id]/summary"

Parameters

visitId

identifier for a visit

REQUIRED

type: path
default: N/A
example: 241f29d1-3402-4a00-b74b-064d28d22596
values: string

Responses

200

{
	"visitId": "241f29d1-3402-4a00-b74b-064d28d22596",
	"userId": "446566b8-d043-411d-90ae-a3a6b39a8ab9",
	"patientGuid": "233441f4-129f-4d0e-afaa-b3009dbe80c7",
	"status": "requested",
	"type": "virtual",
	"modality": "virtual",
	"assignmentQualifiers": [],
	"isHighPriority": false,
	"stateLicensure": "WA",
	"practiceId": "6996d161-cd16-4556-9577-f942c3f80c80",
	"providerId": null,
	"homeMarket": "default",
	"assessmentToolUsed": null,
	"integrations": {
		"tytoCare": {
			"enabled": true,
			"account": {
				"accountId": "233441f4-129f-4d0e-afaa-b3009dbe80c7",
				"isActive": true,
				"devicePairingStatus": "NOT_PAIRED",
				"isDeviceOnline": false
			}
		}
	},
	"tokBoxVisit": {
		"apiKey": "46497352",
		"waitingRoomSession": {
			"sessionId": "2_MX40NjQ5NzM1Mn5-MTYzNzI2MzA3MzU2Mn5pcktjWSsreTF5bFBIQ25lOHUvb1B2L1B-fg"
		},
		"videoConferenceSession": {
			"sessionId": "1_MX40NjQ5NzM1Mn5-MTYzNzI2MzA3MzgzMn5VbDFaRjc2R2J0UGRaWENUQzZRTTdyN2R-fg"
		}
	}
}