Provider Specific Time Slots

This page walks through the process of booking a patient with primary care providers and specialists through calls to our provider API endpoints.

The following order of operations will be used to book a time slot with a provider

  1. List the Available Providers
  2. Retrieve Information for a Specific Provider
  3. Retrieve a Patient Identifying Information
  4. Book the Time Slot for a Provider

Listing Providers

It is generally assumed that the caller has a list of providers.

This list could come from rendering a list of providers on the health systems Find A Doctor section, a primary care office web page that had the list of providers, or a call to DexCare platform to get a list of all providers which support digital scheduling through the DexCare platform.

If you are implementing the third option, the call you would use would be:

 v1/providers?product=yourUseCaseDescriptorHere

The returned payload is a list of the providers.

To accommodate health systems that have more than one EMR the data will be returned in a JSON payload that looks like:

	 {
	     "system":"org.customer.emr.instance",
	     "npi":"999999999"
	 }

If there are 500 providers participating in digital scheduling then there will be 500 of these JSON structures returned.

From these lists, it is the National Provider Identifier (NPI) that will be used in the next step.

Retrieving Provider Information

Once you have an NPI you are ready to make the call to get the provider information. This call is:

 /v1/providers/999999999?product=yourUseCaseDescriptorHere

or

 /v1/providers/org.customer.emr.instance|999999999?product=yourUseCaseDescriptorHere

These two calls return the same payload.

However, by including the EMR information you are instructing the system to call the EMR for additional information.

The first call returns the data that the DexCare platform stores which is used to support digital scheduling. This encompasses just the information needed to continue the booking process.

If you want a superset of this information for displaying things like an image, which might be stored (referenced) in Epic, then you should make the second call.

The following is the payload returned. Data that comes from the EMR is indicated.

	 {
	    "providerId":"999999999",
	    "providerExternalIds":
	        [
	          {
	             "system":"org.customer.emr.instance",
	             "value":"11111111"                                    
	          }
	        ],
	    "providerNationalId":"999999999",
	    "specialty":["Family Medicine"],                                      << Overridden by EMR
	    "subSpecialties":[],
	    "name":"John Doe",                                                    << Overridden by EMR
	    "credentials":"M.D.",                                                 << Overridden by EMR
	    "phone":"",
	    "email":"",
	    "address": {
	        "phone":"(888)-555-1212",
	        "newPatientPhone":"(888)-555-1212",
	        "facility":"Acme Family Medicine",
	        "line1":"18133 Anywhere Blvd",
	        "line2":"",
	        "city":"A-City",
	        "state":"WA",
	        "postalCode":"55555",
	        "countryCode":"USA"
	    },
	    "departments":
	        [
	          {
	             "departmentId":"88888888",
	             "epicInstanceName":"org.customer.emr.instance",
	             "departmentUrlName":"NameToIncludeAsParameterWhenTakingAString",
	             "name":"Acme Family Medicine",
	             "center":"Acme Family Medicine",
	             "directions":""
	          }
	        ],
	    "minAge":0,
	    "maxAge":130,
	    "imageURL":"https://providerassetdirectory-JohnDoe.jpg",              << From EMR
	    "providerGender":"Male",
	    "brand":"YourBrand",
	    "isActive":true,
	    "acceptingNewPatients":true,                                          
	    "scheduleStatus": {
	           "allowsOpenSchedule":true,                      
	           "allowsDirectSchedule":true
	    },
	    "visitTypes":
	        [
	           {
	              "visitTypeId":"77777",
	              "name":"New Symptoms Clinic Visit",
	              "preferenceLogic":null,
	              "reasonLabel":"What health changes, if any, have occurred since the previous visit?",
	              "description":"New Symptoms Visit",
	              "shortName":"NewSymptoms",
	              "group":"illness",
	              "sortOrder":"1"
	           },
	           {
	              "visitTypeId":"55555",
	              "name":"New Patient Clinic Visit",
	              "preferenceLogic":null,
	              "reasonLabel":"New patient tool tip",
	              "description":"New Patient Visit",
	              "shortName":"NewPatient",
	              "group":"illness",
	              "sortOrder":"0"}
	           {
	              ...
	           }
	        ]
	   }

There are several important aspects to note about this data structure:

providerId
National Provider Id, which was used for this call and will be used in the remaining booking calls.
departments
contains the departmentId that will be used in the remaining booking calls (departments.departmentId)
visitTypes
contains a list of visit types that can be displayed to the user and will be used in the remaining booking calls.

There will be 1 or more visit types for each provider. In the example above there are two shown, one being for a returning patient visit (Direct booking) and one for new patient (Open booking). The returning visit type is first item in the list with the visitTypeId of “77777.” The patient with a visitTypeId of “55555” in this example is a new patient and is identifiable as such because new patients are always have the value “NewPatient” assigned to their shortName property.

The visitType structure has information that allows for displaying the information to the user, grouping and “tool tips” for the user.

In this data structure, note the following flags

	    "isActive":true,
	    "acceptingNewPatients":true,                                          
	    "scheduleStatus": {
	           "allowsOpenSchedule":true,                      
	           "allowsDirectSchedule":true
	    },

These flags are important if you are building a widget that will display booking options on your health care website.

isActive
if true then the provider is active and if false they are turned off for digital booking through the DexCare platform.
acceptingNewPatients
when true this means that the provider is accepting new patients
scheduleStatus.allowsOpenSchedule
when true this means that the EMR is configured to allow new patient booking.
acceptingNewPatients and scheduleStatus.allowsOpenSchedule
only when this is true should the provider be considered to allow digital new patient booking
scheduleStatus.allowsDirectSchedule
when true this means that the EMR is configured to allow returning patient booking.

Example — Provider Accepts All Visit Types

In the example above, when all the flags are true, this indicates that the provider would work (and accepts) all visit types for which they are configured.

Example — Provider Without a Digital Scheduling Option

Another case is below:


	    "isActive":true,
	    "acceptingNewPatients":false,                                          
	    "scheduleStatus": {
	           "allowsOpenSchedule":true,                      
	           "allowsDirectSchedule":false
	    },
	    

In this case, the EMR is not configured to allow returning patient to book their appointments directly.

When showing visit types or requesting timeslots, you should not show requests for any returning patient (Direct) visit types.

For new patient visit types (Open), even though the EMR is configured for the provider to accept digital booking (scheduleStatus.allowsOpenSchedule keyword), the provider doesn’t accept new patients (acceptingNewPatients keyword).

So this provider effectively has no digital scheduling solution.

Provider Timeslots

Using information from the provider information above you will be able to construct a timeslot call.

There are two forms of timeslot call, one is for an individual provider and the other is a bulk call (which has a few more options).

The timeslot calls will provide all the information necessary to:

  1. use the booking API to create an appointment
  2. navigate the user into the DexCare booking flow

Max Lookahead Days

The EMR has a configured value of how far into the future it will return slots. It is an error to ask for slots beyond this date. To understand this date you can use the following API.

	 /v2/lookups/maxLookaheadDays?visitTypeName=AdultPhysical
	                                   &epicInstanceName=org.customer.emr.instance
	                                   &product=yourUseCaseDescriptorHere

Please note that the line separations are to make reading the call easy and would not function if sent this way.

This will return a payload like

 {
      "maxLookaheadDays": 0
 }

This indicates today + maxLookaheadDays as the last date that time slots can be requested.

Single Provider Call

The most simple of the calls is the single provider call.

	 /v3/providers/999999999/timeslots?visitTypeId=55555&departmentId=88888888     
	                                   &startDate=2021-03-05T12:00:00-08:00        
	                                   &endDate=2021-04-04T12:00:00-07:00          
	                                   &product=yourUseCaseDescriptorHere

Note that the time portion of the startDate and endDate are ignored.

(ISO 8601 date format used by the API requires a time to have a timezone)

Below is a sample output payload:

	 {
	    "providerNationalId":"1417026030",
	    "providerId":"WM1232",
	    "timezone":"America/Los_Angeles",
	    "startDate":"2021-03-05T12:00:00-08:00",
	    "endDate":"2021-04-04T12:00:00-07:00",
	    "scheduleDays":
	       [
	          {
	             "date":"2021-03-05T12:00:00-08:00",
	             "providerNationalId":"1417026030",
	             "providerId":"WM1232",
	             "timeSlots":[]
	          },
	          {
	             "date":"2021-03-06T12:00:00-08:00",
	             "providerNationalId":"1417026030",
	             "providerId":"WM1232",
	             "timeSlots":
	                [
	                   {
	                      "providerNationalId":"1417026030",
	                      "providerId":"WM1232",
	                      "id":"base64 slot ID",
	                      "slotDateTime":"2021-03-06T09:30:00-08:00",
	                      "departmentId":"3100035001",
	                      "departmentIdentifier":"org.providence.dig.epic.provwamt|3100035001",
	                      "slotType":"Returning",
	                      "duration":30,
	                      "visitTypeId":"122859"
	                   },
	                   {
	                      ...
	                   }
	                ]
	           }
	           ...
	      ]
	 }

There are several things to note in the returned payload.

startDate
startDate is not guaranteed to be the same as the dates requested. If your health system has a buffer set for digital scheduling the DexCare platform will mirror this (a configured setting in the DexCare platform). If you health system as a buffer of 3 days and a request is made for a startDate of today, the returned startDate will be today plus the 3 day buffer.
endDate
endDate will be the requested endDate unless it exceeds the EMR configured lookahead days for requesting slots. This EMR configured value is not the span between startDate and endDate but is the number of days from today that slots are available. So, even asking for a time range of three days that span this future date will fail.

Note that date fields are ISO 8601 compliant date-time fields so that they include a time zone.

scheduleDays
every day in the span returned will have an entry in the scheduleDays array. In the example above the first requested date for time slots, 03/05/2021, does not have any available slots.
The next entry, 03/06/2021, has two entries (data for just the first). The slot description has all the information to properly display the slot to the user and for booking the slot.

Batch Provider Call / Next N Slots

This call serves two purposes. The first is if you have more than 1 provider for which you wish to get timeslots. The other is when you want a set number of slots and not the slots between a date range. It accepts a date range too.

There are use cases where retrieving a set number of slots is desirable, even if just for one provider. For example if you have a user interface with a scheduling widget that shows only 8 slots at a time, then getting a large payload of 100s of slots may not be desirable when what you want is just the next eight available.

	 /v2/timeslots?providerId=8888888&providerId=99999999
	           &visitTypeId=1000003
	           &startDate=2021-02-22
	           &endDate=2021-04-14
	           &maxSlots=5
	           &product=yourUseCaseDescriptorHere

Note that the list of providers is sent in a repeating list of providerId parameters.

This call works for only a single visit type.

Even though the call contains a start and end date these will be ignored because the maxSlots parameter is also being sent. It would function without the dates being sent too.

The returned payload is different than the previous payload to limit the size of the returned payload.

	 {
	   "providers": 
	   {
	       "8888888": 
	       {
	         "slots": 
	           [
	              {
	                 "date": "2021-03-09",
	                 "time": "08:00:00",
	                 "duration": 30,
	                 "visitTypeId": "1000003",
	                 "timezone": "America/Los_Angeles",
	                 "departmentId": "3100035001",
	                 "slotType": "NewPatient"
	             },
	             {
	                 ...
	             },
	             {
	                 ...
	             },
	             {
	                 ...
	             }
	          ]
		    },
	      "99999999": 
	      {
	         "slots": [ ]
	      }
	   }
	 }

The returned payload reveals that provider 8888888 has only 4 slots of visit type 1000003 between today and the max lookahead range (remember that the start and end date are ignored). The other requested provider has no available slots of this visit type.

Getting Patient Identifying Information

At this point you will have most of the data you need to make an appointment for a patient.

The last thing that needs to be done is to identify the patient through their unique identifier.

See our Patient APIs for details how the patient identifier may retrieved.

Booking With the Provider

`/api/7/visits/providerbooking`              

This is a POST so the arguments are in the body. The required body structure is:

	{
  	    "actor": {                                    <-- required
          "email": "string",
          "firstName": "string",
          "lastName": "string",
          "gender": "male",
          "dateOfBirth": "string",
          "relationshipToPatient": "string",
          "phone": "string"
	    },
       "billingInfo": {
          "paymentMethod": "creditcard",
          "declaration": "self",
          "firstName": "string",
          "lastName": "string",
          "gender": "male",
          "dateOfBirth": "string",
          "couponCode": "string",
          "insuranceType": "string",
          "insuranceProviderId": "string",
          "insuranceMemberId": "string",
          "stripeToken": "string"
	   },
	   "patient": {
          "patientGuid": "string",                  <-- required, see above
          "address": {													       
              "line1": "string",
              "line2": "string",
              "city": "string",
              "state": "string",
              "postalCode": "string"
	       }
	   },
	   "visitDetails": {                             <-- all fields required
          "declaration": "self",                    <-- "self" | "other"
          "departmentId": "string",                 <-- acquired from previously described call
          "ehrSystemName": "string",                <-- acquired from previously described call
          "nationalProviderId": "string",           <-- acquired from previously described call
          "slotId": "string",                       <-- acquired from previously described call
          "visitReason": "string",                  <-- reason entered by patient
          "visitTypeId": "string"                   <-- acquired from previously described call
	   }
	}

When the visitDetails.declaration is “other” the “actor” structure must also be present. If visitDetails.declaration is “self” the “actor” structure is optional and any values sent will be ignored.

When the visitDetails.declaration is “other” the product operates as if a guardian is making an appointment for someone else. The guardian information is passed in using the actor structure. In this case the actor information is required.

The billingInfo data is always optional. If provided it will be put in the appointment notes field at the time of making the appointment. The Provider Booking flow at this time does not support collecting credit card information or charging a patient.