MyPatientPortal OAuth API

MyPatientPortal OAuth API

Disclaimer: this is a draft . It is not the final version. Changes can come later.

About this API

The MyPatientPortal OAuth API utilizes the OAuth 2.0 standard, enables a secure, token-based access to patient health data for third-party applications. It allows developers to request specific permissions from users, ensuring seamless integration with external apps while protecting sensitive information, without requiring login credentials.

This documentation assumes a basic familiarity with the OAuth 2.0 framework and protocol. If you are new to OAuth, you may want to have a look at the basic concepts of OAuth or the actual OAuth 2.0 specification (RFC6749).

About OIDC

We also support OIDC (OpenID Connect) authentication protocol that extends our OAuth 2.0 authorization protocol. When you provide addtional openid scope to your OAuth 2 requests, you will indicate a will to authenticate using OIDC flow.

The configuration for OIDC is available on .well-known/openid-configuration endpoint. Most of OIDC libraries can use it to automatically perform authentication and OAuth 2 authorization for you. With that, you won’t need to manually code anything relating retrieving and refreshing access tokens. It is our recommended way to use this API.

Using OIDC, we also expose userinfo_endpoint that contains detailed information about authenticated user.

Credentials

Client credentials, which include an ID and secret, uniquely identify your application and are used to authenticate it with your patient portal (Authorization Server). They ensure secure API access. Before being able to use the API, reach out to our administrator to generate credentials with the callback URI of your application.

Please remember to keep your client credentials confidential.

Grant types

Our integration allows you to request access tokens with two grant types:

  1. authorization_code - used when you want to access resources on behalf of the specific user. To get access token, you need to provide authorization code, see this section for more details: https://samedigmbh.atlassian.net/wiki/spaces/DW/pages/672235527/MyPatientPortal+OAuth+API#Obtaining-access-token-with-authorization_code-grant-type . With this grant type, you will also have access to resources available with client_credentials grant type.

  2. client_credentials - used when you want to access resources without a user present. It’s useful for guest bookings or details for a potential appointment like appointment types, locations etc. Please refer to the table in https://samedigmbh.atlassian.net/wiki/spaces/DW/pages/672235527/MyPatientPortal+OAuth+API#Scopes section to see more details.
    Refer to https://samedigmbh.atlassian.net/wiki/spaces/DW/pages/672235527/MyPatientPortal+OAuth+API#Obtaining-access-token-with-client_credentials-grant-type section to see an example of getting an access token using client_credentials grant type.

Roles

OAuth 2.0 specifies 4 distinct roles. In the context of your patient portal, these are mapped as following:

  • The Resource Owner is your patient portal user on whose behalf appointments are booked.

  • Your external application or service acts as the Client and can access Resource Owner's data, but only with their prior permission.

  • The OAuth API serves as an interface to the Resource Servers which control access to protected resources by means of tokens.

  • Furthermore, the API interfaces to the Authorization Server which after successful authorization issues the appropriate access tokens of Resource Owner.

The interaction sequence between these roles is the following:

  1. The Client requests the authorization of Resource Owner. The latter may grant the authorization by logging in to his/her account.

  2. The Client receives the user’s authorization from Authorization Server.

  3. The Client presents its client ID, client secret and the granted authorization to Resource Server (via the API).

  4. Upon validation, Resource Server returns to the client an access token.

  5. The Client requests access to the protected resources and signs these requests with the access token.

  6. Resource Server, upon successful validation of the access token, returns the requested resource.

Scopes

OAuth scopes limit what actions a Client can perform, such as reading or modifying certain resources on behalf of the Resource Owner. In your patient portal, three scopes are defined in terms of OAuth:

  • basic: Our base scope, required to perform any action. It is

  • profile_read: Allows to retrieve Resource Owner’s profile

  • appointment_read: Grants access to read appointments and to video consultation

  • appointment_write: Allows to book, cancel and reschedule appointments

The following table demonstrates what scope each OAuth endpoint requires

Endpoint

HTTP Method

Scope

Grant Types

Endpoint

HTTP Method

Scope

Grant Types

/oauth/userinfo

GET

profile_read

authorization_code

/api/patient/v1/appointments

GET

appointment_read

authorization_code

/api/patient/v1/appointments/overview

GET

appointment_read

authorization_code

/api/patient/v1/appointments/{id}

GET

appointment_read

authorization_code

/api/patient/v1/appointments/{id}/cancel

POST

appointment_write

authorization_code

/api/patient/v1/booking

POST

appointment_write
OR
basic (guest booking)

authorization_code, client_credentials (guest booking)

/api/patient/v1/reschedule

POST

appointment_write

authorization_code

/api/patient/v1/appointment_categories

GET

basic

authorization_code, client_credentials

/api/patient/v1/appointment_types

GET

basic

authorization_code, client_credentials

/api/patient/v1/appointment_types/{id}

GET

basic

authorization_code, client_credentials

/api/patient/v1/appointment_types/{appointment_type_id}/availabilities

GET

basic

authorization_code, client_credentials

/api/patient/v1/appointments/{appointment_id}/availabilities

GET

appointment_read

authorization_code

/api/patient/v1/appointments/{id}/asap_availability

GET

appointment_read

authorization_code

/api/patient/v1/appointments/{id}/asap_list_subscription

PUT, DELETE

appointment_write

authorization_code

/api/patient/v1/institutions

GET

basic

authorization_code, client_credentials

/api/patient/v1/institutions/{id}

GET

basic

authorization_code, client_credentials

/api/patient/v1/locations

GET

basic

authorization_code, client_credentials

/api/patient/v1/insurances

GET

basic

authorization_code, client_credentials

/api/patient/v1/video_consultations_patient_accesses

POST

appointment_read

authorization_code

Obtaining access tokens

To perform actions in our API, you will need to obtain a correct access token. These tokens are only valid for a limited time, given in return alongside the code (e.g. 7200 seconds).

Some of the resources are user specific and require getting authorized by the user. That includes booking appointments on behalf of the user, rescheduling appointments, cancelling appointments and more.

Many resources are not user specific and can be accessed withour user authorization.

To choose which resources you want to access, you need to request access token with a specific grant type.

Obtaining access token with authorization_code grant type

This grant type is used for accessing resources that may be specific to the user. It requires getting the user authorized and user allowing your OAuth2 application to access their data.

Note: You can access resources that are not user specific, using an access token with authorization_code grant type.

Step 1. Obtain a authorization code

The endpoint /oauth/authorize of your patient portal is used to obtain authorization from the Resource Owner. This authorization is represented in the form of an authorization code which can be subsequently used to request an Access Token. Depending on the use cases, you need to specify the corresponding scopes in request.

A sample of authorization request:

GET /oauth/authorize?client_id=CLIENT_ID&redirect_uri=https://client.example.com/cb&response_type=code&scope=basic+profile_read+appointment_read+appointment_write HTTP/1.1 Host: your-patient-portal.com

The Resource Owners will be then asked to authenticate themselves to the Authorization Server, verify the requested scopes and grant the permissions.

Upon a successful authorization, the Authorization server directs the Resource Owner back to the callback URI together with a authorization code.

HTTP/1.1 302 Found Location: https://client.example.com/cb?code=AUTHORIZATION_CODE

If authorization is turned down, the response will contain error messages.

HTTP/1.1 302 Found Location: https://client.example.com/cb?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.

For more error responses, please check the official specification our API follows.

Step 2. Requesting access token

After obtaining an authorization code, the Client makes an access token request to the Authorization Server. This request should include the authorization code, client ID, client secret, redirect URI and specific grant type authorization_code.

curl -X POST "https://your-patient-portal.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=https://client.example.com/cb" \ -H "Accept: application/json" \ -H "Content-Type: application/json"

Upon validation, the server responds with an access token, which the application can then use to access protected resources on behalf of the Resource Owner.

An example of access token in a successful response:

{"access_token": "ACCESS_TOKEN","token_type":"Bearer","expires_in":7200,"refresh_token":"REFRESH_TOKEN","scope":"profile_read appointment_read appintment_write","created_at":1728472949}

For any malformed or otherwise incorrect request, the included error descriptions are following the OAuth 2.0 Specification.

Refreshing access token

A refresh token request allows Client to obtain a new access token after the original has expired without requiring the Resource Owner to reauthorize. When the access token is nearing expiration, Client sends a request to the Authorization Server, including the refresh token, client ID, and client secret. Grant type must be refresh_token

curl -X POST "https://your-patient-portal.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN \ -H "Accept: application/json" \ -H "Content-Type: application/json"

If valid, the server responds with a new access token, with the same format as described in section Requesting access token, enabling continued access to protected resources.

Obtaining access token with client_credentials grant type

When you want to access resources that are not user specific, you can use your client credentials to get an access token.

Ask for a new access token by providing your client credentials and basic scope.

curl -X POST "https://your-patient-portal.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=client_credentials&scope=basic" \ -H "Accept: application/json" \ -H "Content-Type: application/json"

An example of access token in a successful response:

{"access_token": "ACCESS_TOKEN","token_type":"Bearer","expires_in":7200,"scope":"basic","created_at":1744628265}

For any malformed or otherwise incorrect request, the included error descriptions are following the OAuth 2.0 Specification.

Using the API

After obtaining a correct access token, you can access the resources in our API. Here are some examples of how to use the API.

Retrieving Resource Owner’s profile

Once your application obtains the proper access token for authorized user, it can request profile information of the Resource Owner with the following cURL command,

curl -X GET "https://your-patient-portal.com/oauth/userinfo" -H "Authorization: Bearer ACCESS_TOKEN"

A sample of response data:

{"sub":"06d0ebd45909630c59adbb48cf11516026a60bdb2529230515ec1ffb5bcd3dba","given_name":"John","family_name":"Doe","name":"Doe, John","email":"jdoe@example.com","address":{"street_address":"Raeger straße 44","locality":"Berlin","postal_code":"10117","country":"DE"}}

A walkthrough of appointment booking

This is meant to be used as a quick-start guide only, to help you quickly create first appointment using the API. As Client accesses the resources on behalf of Resource Owner, all requests must be signed by the access token obtained previously.

To understand the full capabilities of the APIs and get more conceived and production-ready examples, please check the Swagger documentation of your patient portal under path /api-docs.

Appointment booking

Note: With client_credentials grant type the bookings will not be tied to any patient – we call them guest bookings. You won’t be able to book subsequent bookings for that same patient or control that appointment (cancel, reschedule).

Step 1: Getting the available insurance

First, retrieve the available insurances for your patient portal:

curl -X GET 'https://your-patient-portal.com/api/patient/v1/insurances'\ -H "Authorization: Bearer ACCESS_TOKEN"

After fetching a list of insurances, you need to prompt your user about which insurance they would like to use. In this example, we’ll use insurance ID(136) for future usage.

Step 2: Getting the appointment category

To get the appointment categories specified on the Institution, by making use of the selected insurance’s ID (136), make the following request as in the cURL example below, as:

curl -X GET 'https://your-patient-portal.com/api/patient/v1/appointment_categories?insurance_id=136&page=1' \ -H "Authorization: Bearer ACCESS_TOKEN"

The response contains a list categories with their IDs and names. Make note of an ID of one of those appointment categories(e.g., 53).

Step 3: Getting the appointment type

Now, to get the appointment types specified on the Institution, make the following cURL request using the previous category id 53, plus the insurance id 136 we’ve fetched in the previous steps,

curl -X GET 'https://your-patient-portal.com/api/patient/v1/appointment_types?page=1&appointment_category_id=53&insurance_id=136' \ -H "Authorization: Bearer ACCESS_TOKEN"

The response provides a set of appointment types. Make a note of the ID of one of them. Example: 198

Step 4: Getting availabilities

To get availabilities (the times you could book an appointment for), we will now need to use the values we’ve found on the earlier steps, being:

  • appointment category: 53

  • appointment type: 198

  • insurance id: 136

It’s worth noting that we must also specify a time range for the search with parameter from and to. The request will be:

curl -X 'GET' 'https://your-patient-portal.com/api/patient/v1/appointment_types/198/availabilities?appointment_category_id=53&insurance_id=136&from=2025-01-01&to=2025-01-10' \ -H "Authorization: Bearer ACCESS_TOKEN"

Pick a time and note its id from response for request in the next step. Example: 7r8Uq4AD9Rjk9XNN0FSC6UFR5kkqNICCTjpPCbX1uOUJKPfcuRijxYTW_kVCJ0LOWE9pnCfm4thH8sS4XHdPf8OUWWikWmXWLn3e2nngB6ZzQF5q4xp2i6L+8Y75FXW8r3FktJ_qldsXUvgm6cPXl7q1DFjlAm3k8ANNqGBHDQZb+YTSZAMh6xeY--FFj0c3l1F_pUuY9N--ITaASrPXMda95yi_TjAYsw==

Step 5: Booking the appointment using the selected availability

We will now use the /booking endpoint on a POST request to make the appointment.

We add a few parameters to the body of the request, besides the availability ID fetched in previous Step 4 . Here’s an example using curl to make the request:

curl -X POST https://your-patient-portal.com/api/patient/v1/booking \ -H "Content-Type: application/json"\ -H "Authorization: Bearer ACCESS_TOKEN"\ -d '{"availability_id":"7r8Uq4AD9Rjk9XNN0FSC6UFR5kkqNICCTjpPCbX1uOUJKPfcuRijxYTW_kVCJ0LOWE9pnCfm4thH8sS4XHdPf8OUWWikWmXWLn3e2nngB6ZzQF5q4xp2i6L+8Y75FXW8r3FktJ_qldsXUvgm6cPXl7q1DFjlAm3k8ANNqGBHDQZb+YTSZAMh6xeY--FFj0c3l1F_pUuY9N--ITaASrPXMda95yi_TjAYsw==", "patient_data": {"first_name": "John", "last_name": "Doe", "mobile": "1234567890", "phone": "12345", "title": "Sir", "email": "jdoe@example.com", "gender": "m", "insurance": "TK", "born_on": "2024-05-23", "accepts_email": true}, "structured_comment": {}, "notify_with": {"first_name": "John", "last_name": "Doe", "title": "Sir", "email": "jdoe@example.com", "mobile": "+11 1111 1111", "gender": "m", "insurance": "TK", "born_on": "2024-05-23"}}'

And on the response, you’ll get the Appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo)

Rescheduling an appointment

Note: This is available only for access tokens acquired with authorization code (with user present)

Step 1: Getting availabilities (user booking only)

Given the appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo), you can request new availabilities under the same appointment type and category.

curl -X GET 'https://your-patient-portal.com/api/patient/v1/appointments/xbCuVVTNU6rT6E5m8p6Y8h7opzfo/availabilities' \ -H 'accept: application/json' \ -H 'Authorization: ACCESS_TOKEN'

The response contains a list of availabilities and their times, in the same pattern as they are in the previous section.

Step 2: Rescheduling appointment

With the availability ID for a selected time, you are able to reschedule the appointment.

Availability ID example:

7r8Uq4AD9Rjk9XNN0FSC6UFR5kkqNICCTjpPCbX1uOUJKPfcuRijxYTW_kVCJ0LOWE9pnCfm4thH8sS4XHdPf8OUWWikWmXWLn3e2nngB6ZzQF5q4xp2i6L+8Y75FXW8r3FktJ_qldsXUvgm6cPXl7q1DFjlAm3k8ANNqGBHDQZb+YTSZAMh6xeY--FFj0c3l1F_pUuY9N--ITaASrPXMda95yi_TjAYsw==

curl -X POST 'https://your-patient-portal.com/api/patient/v1/reschedule' \ -H 'accept: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"availability_id":"7r8Uq4AD9Rjk9XNN0FSC6UFR5kkqNICCTjpPCbX1uOUJKPfcuRijxYTW_kVCJ0LOWE9pnCfm4thH8sS4XHdPf8OUWWikWmXWLn3e2nngB6ZzQF5q4xp2i6L+8Y75FXW8r3FktJ_qldsXUvgm6cPXl7q1DFjlAm3k8ANNqGBHDQZb+YTSZAMh6xeY--FFj0c3l1F_pUuY9N--ITaASrPXMda95yi_TjAYsw==","patient_id": "c877209f-fedd-41ed-99fe-10d379a008b9", "notify_with": {"first_name": "John", "last_name": "Doe", "title": "Sir", "email": "jdoe@example.com", "mobile": "+11 1111 1111", "gender": "m", "insurance": "TK", "born_on": "2024-05-23"}}'

A successful rescheduling moves only the appointment time. It won’t change the original appointment ID.

Cancelling an appointment

Note: This is available only for access tokens acquired with authorization code (with user present)

By using the previously created appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo)

curl -X POST https://your-patient-portal.com/api/patient/v1/appointments/m8ehhdciA69CaaT5bDQyJxMjuujA/cancel \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN"

The success response contains ID of the cancelled appointment.

Using ASAP list

Note: This is available only for access tokens acquired with authorization code (with user present)

ASAP list is an appointment feature that patients can opt into. They are then notified via email when earlier availability becomes available for their booked appointments.

Configuring appointment type

A prerequisite for a subscribable ASAP list is that institution enable the feature in appointment type configuration by ticking the checkbox 'Allow patients to register for earlier appointment notifications'. In the payload of appointment types request (as shown in step 3 in the previous section), the parameter asap_notifications_enabled indicates the state of the feature.

Booking appointment with ASAP list subscription

An appointment can be booked with ASAP list subscription by using parameter asap_list_opt_in . Considering the aforementioned booking example, the request body will be extended as in the following cURL request example:

curl -X POST https://your-patient-portal.com/api/patient/v1/booking \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" \ -d '{"availability_id":"7r8Uq4AD9Rjk9XNN0FSC6UFR5kkqNICCTjpPCbX1uOUJKPfcuRijxYTW_kVCJ0LOWE9pnCfm4thH8sS4XHdPf8OUWWikWmXWLn3e2nngB6ZzQF5q4xp2i6L+8Y75FXW8r3FktJ_qldsXUvgm6cPXl7q1DFjlAm3k8ANNqGBHDQZb+YTSZAMh6xeY--FFj0c3l1F_pUuY9N--ITaASrPXMda95yi_TjAYsw==", "patient_data": {"first_name": "John", "last_name": "Doe", "mobile": "1234567890", "phone": "12345", "title": "Sir", "email": "jdoe@example.com", "gender": "m", "insurance": "TK", "born_on": "2024-05-23"}, "structured_comment": {}, "notify_with": {"first_name": "John", "last_name": "Doe", "title": "Sir", "email": "jdoe@example.com", "mobile": "+11 1111 1111", "gender": "m", "insurance": "TK", "born_on": "2024-05-23"}, "asap_list_opt_in": {"email": "jdoe@example.com"}}'

As before, it responds with the new appointment ID in the response payload.

ASAP list un-/subscription after booking

It’s also possible to enter or leave the ASAP list after appointments have been booked. As an ASAP list is always appointment-specific, the appointment ID is always required in requests.

Subscription

Email must be provided in the request payload: An example of the curl request with an appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo):

curl -X PUT 'https://your-patient-portal.com/api/patient/v1/appointments/xbCuVVTNU6rT6E5m8p6Y8h7opzfo/asap_list_subscription' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" \ -d '{"asap_list_opt_in": { "email": "jdoe@example.com" }}'

The appointment ID will be in the response payload for a successful subscription.

Unsubscription

Taking the same appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo) for the CURL request,

curl -X DELETE 'https://your-patient-portal.com/api/patient/v1/appointments/xbCuVVTNU6rT6E5m8p6Y8h7opzfo/asap_list_subscription' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN"

The shape of the response will be the same as that for subscription.

Getting earlier availability

With an ASAP list subscription, you can request an earlier appointment availability.
By using the appointment ID (example: xbCuVVTNU6rT6E5m8p6Y8h7opzfo), the cURL can be built as follows:

curl -X 'GET' \ 'https://your-patient-portal.com/api/patient/v1/appointments/xbCuVVTNU6rT6E5m8p6Y8h7opzfo/asap_availability' \ -H 'accept: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN'

The response contains the appointment detail and an earlier availability, which is in the same format as previously discussed.

Rescheduling appointment to an earlier availability

It works the same way as described in the previous section.