MDsave GraphQL API

The MDsave GraphQL API enables an Employer or TPA partner to interact with the MDsave platform to perform actions like search for offers by location and provider, create shopping carts, and purchase the shopping cart through an invoicing process. This API allows a partner to develop their own application or interface to their internal system to create workflows that will transact with MDsave allowing them to purchase the care for their employees directly on their platform of choice and integrated into whatever workflow works best for them.

Reach out to your sales rep or account manager, or send an email to mdsaveapi@tendo.com if you are interested in developing on the API. We will generate sandbox credentials that you can use to develop and test your application in our sandbox environment.

Are you a part of an Medical Provider or Hospital organization that is looking to use the MDsave API? We do not currently support providers to transact on the MDsave API, but if you are interested in ideas for developing a provider integration with MDsave, speak to your Sales Rep or Account Manager about what you would like to accomplish, and we can work with you.

Invoicing

Purchases made through the MDsave API are completed through an invoicing process. Your account manager or sales rep can provide you with more information on how we can fit our invoicing process with your existing workflows.

What You Can do with the API

Search for Offers

Build a unique search experience for medical procedures that can index our entire Marketplace that can be customized by location, provider network, specialty, and more.

Build Shopping Carts

Create MDsave shopping carts with unique URLs that are pre-loaded with the services and patient information. These carts can be sent via email or SMS to the patient to purchase themselves or to a patient representative who can purchase the voucher and schedule them at the same time.

Checkout Shopping Carts

Complete a transaction using the MDsave API and generate Vouchers that the patient can use to cover the services rendered by the provider.

Retrieve Voucher Purchases

Use the MDsave API to retrieve data about previous Voucher purchases, including their current status. These will contain URLs to PDFs that are available for 24 hours. These PDFs can also be optionally automatically emailed to the patient, and would also be available through your internal portal login where you can see all previous purchases as well.

Contact

MDsave API Support

mdsaveapi@tendo.com

API Endpoints
https://demo-api.mdsave.com
Version

1.0.1

Getting Started

Here is what you need to get started developing an application with the MDsave GraphQL API. Below are some links you can find about GraphQL APIs and clients you can use to interface with it.

Introduction to GraphQL

Authentication

You can authenticate with the MDsave API one of two ways: using a secret key to generate a JWT or by using a Static Token. Generating a JWT will give you access to all the Queries and Mutations. Using a static token will give you access to the searchLocations, searchOffers, and searchProcedures queries only. MDsave will generate separate secret keys and static tokens for our test (demo) and production environments.

Generate a JWT

MDsave uses JSON Web Token for authorization.

Obtain a secret key

Contacting the MDsave dev team who will register your account and generate the secret key and securely send it to you.

Create the payload

  {
    "id": "12345",
    "email": "your-email@acme.com",
    "exp": "1578596842"
  }

The exp field should be the timestamp you need the token to expire in UTC e.g. Math.round((Date.now()+250)/1000)

Encrypt the payload

Use the HS256 algorithm with the secret key to generate the JWT. MDsave accepts a standard JWT header { "alg": "HS256", "typ": "JWT" }

Using the header above and the payload from step 2, base64 encode and concatinate both and encrypt the result using the secret key from step 1.

  HMACSHA256(
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    your-secret
  )  

JWT.io is a useful tool to generate JWTs while developing and testing.

Use the JWT

The token generated in the steps above can be included in the header of requests to the API

  {
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjM5ODY0IiwiZW1haWwiOiJkZW1vK2VtcGxveWVyQG1kc2F2ZS5jb20iLCJleHAiOjExODEyMzczNDJ9.45l6lG5Q48ec1beY-tNBfrt4ryyLvONCJtwxeEpXr9o"
  }

Use a Static Token

You can also use a static token to authenticate with some of our queries so that you don't have to generate a new JWT every time it expires.

  1. Obtain a static token by contact the MDsave dev team. We will register an account in our demo or production environment and generate the token for you.

  2. Set the Authorization and payload headers in the requests using the static token along with a payload with timestamp and email. The email address used here should be the same as the one used to generate the static token. | { "Authorization": "Bearer {Static Token}", "payload": "{"id":"243190","email":"your-email@acme.com","exp":1628009118}" }

Note that the value of the payload header needs to be JSON encoded with the quotes escaped.

Sandbox Environment

The URL of the MDsave Sandbox GraphQL API is: https://demo-api.mdsave.com. You can send queries and mutations to that URL with a valid JWT in the Authentication HTTP header. Or you can use the Apollo studio to try things out.

Data Refresh

The database for the sandbox environment will refresh every day so all test purchases made on the platform will removed overnight.

Try it out!

Use the demo playground to try out the queries and mutations from pre-built examples. You can fill in the Authentication headers and data in each tab by clicking on the Query Variables and HTTP Headers buttons at the bottom left of the window. The requests sent through the playground will be sent to our demo API environment.


MDsave API Types

The MDsave GraphQL API uses defined Types that correspond to how the MDsave Marketplace data is structured and are used to interact with the platform across the defined Queries and Mutations. Here are some high level descriptions of what the Types and the data they contain represent and how they map to each other and how they can be used in the API.

Procedure

A Procedure is a high level idea of a medical procedure or service that can be offered on the Marketplace. These include single services like ‘X-ray’ or ‘MRI without Contrast’, that may map to single CPT codes, as well as bundled services like ‘Knee Replacement’ that may encapsulate many CPT codes that are grouped under a single service. These are the basic components of a procedure:

  • name

  • description

  • default included CPT codes

Offer

An Offer is a specific instance of a Procedure that is listed in the Marketplace under a single provider. This offer has a specific price for that provider at a specific location, and is the purchasable entity. An Offer is something that is put into a shopping cart and when the checkout is completed, a Voucher is created for each Offer in the cart that is purchased.

  • procedure - this is linked to the Procedure Type above and is the general description of the procedure

  • provider - this is the provider that will perform the procedure in this offer

    • a provider contains a reference to a “Hospital” which acts as the parent organization to the provider. Hospitals can be referenced using their unique NPI (National Provider Identifier)
  • price - this is unique price for this procedure as offered by the provider. This is the up-front purchase price for this procedure at this provider

  • included cpt codes - this provider may have a custom set of CPT codes that correspond to this particular offer

Shopping Cart

The ShoppingCart type functions the exact same way a shopping cart in the marketplace web experience does, with one important distinction: the API currently only supports a createShoppingCart mutation currently, so you will need to send all the selected Offers along with a patient object when creating the cart. However, also like the web experience, you can only add offers from the same Provider to a shopping cart.

Voucher

A Voucher represents a purchase of ShoppingCart for a specific Patient and functions as a proof of purchase for the patient to receive services. Each Offer in a ShoppingCart that is purchased will generate a Voucher that all have the same order number and will have a unique voucher number. For example, purchasing a ShoppingCart with 3 Offers in it will produce 3 Vouchers with the order number 1234567 and the voucher numbers will be:

  • 1234567-01

  • 1234567-02

  • 1234567-03

Each of which will also have a link to a PDF version of the voucher with all of the information needed to schedule and verify the services.

Vouchers have one of three different statuses:

  • Available

    • The voucher is purchased but is not yet redeemed. The voucher is still good for the patient to redeem the services.
  • Used

    • Once the patient receives services, the voucher is redeemed and the payment is sent to the provider.
  • Cancelled

    • The voucher was purchased but has been cancelled and refunded.

Sample Workflows

In this example, we are going to step through a commonly used workflow and provide code samples for each step.

1. Search for Procedures

You can use the searchProcedures query to search for medical procedures that are available on the MDsave Marketplace. This query can be used to power your own search functionality in your application and can be used to surface the many procedures that are bundled in different ways. The results will generally include a bundle of CPT codes that are valid for those services at that provider. You can also search for procedures by CPT code.

By Procedure Name with Autocomplete

You can use the MDsave API to power autocomplete search functionality on your own platform to surface MDsave procedures by name. To demonstrate how this can be done, we will simulate a user typing a procedure name into a search box while we are actively sending the requests as they type. To do this, we will use the searchProcedures query to send these snippets of text, which will return a list of potential matches.

Let’s simulate a user typing “ct scan with contrast” into a search box. You application can start querying the API as they start typing a few letters.

We’ll start by sending “ct s” as the procedure name in the query as if the user was beginning to type their search.

query searchProcedures(
  $query: SearchProceduresInput!,
  $pagination: Pagination
) {
  searchProcedures(
    query: $query,
    pagination: $pagination
  ) {
    procedures {
      id
      name
      url
    }
  }
}  

{
  "query": {
    "name": "ct s"
  },
  "pagination": {"offset": 0, "limit": 10}
}  

The API will return this list of procedures. Since there were only a few letters sent, the results will be broad but will narrow as the user types more of their search.

{
    "data": {
        "searchProcedures": {
            "procedures": [
                {
                    "id": 1792,
                    "name": "Low Dose CT Lung Screening",
                    "url": "https://demo.mdsave.com/procedures/low-dose-ct-lung-screening/d785f5cf?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1435,
                    "name": "Cardiac CT Coronary Angiography",
                    "url": "https://demo.mdsave.com/procedures/cardiac-ct-coronary-angiography/d786ffc8?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1425,
                    "name": "CT Scan Limited/Follow-up Study",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-limited-follow-up-study/d786fec8?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1391,
                    "name": "CT Scan with Contrast",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-with-contrast/d781f5cc?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1399,
                    "name": "CT Scan of Abdomen and Pelvis with Contrast",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-of-abdomen-and-pelvis-with-contrast/d781f5c4?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1061,
                    "name": "PET Scan",
                    "url": "https://demo.mdsave.com/procedures/pet-scan/d782facc?utm_medium=affiliate&utm_source=Example+API+Employer"
                }
            ]
        }
    }
}  

Now let’s send another query with more text “ct scan with” to continue narrowing the results.

query searchProcedures(
  $query: SearchProceduresInput!,
  $pagination: Pagination
) {
  searchProcedures(
    query: $query,
    pagination: $pagination
  ) {
    procedures {
      id
      name
      url
    }
  }
}  

{
  "query": {
    "name": "ct scan with"
  },
  "pagination": {"offset": 0, "limit": 10}
}  

The API returns these procedures:

{
    "data": {
        "searchProcedures": {
            "procedures": [
                {
                    "id": 1391,
                    "name": "CT Scan with Contrast",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-with-contrast/d781f5cc?utm_medium=affiliate&utm_source=Example+API+Employer"
                },
                {
                    "id": 1399,
                    "name": "CT Scan of Abdomen and Pelvis with Contrast",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-of-abdomen-and-pelvis-with-contrast/d781f5c4?utm_medium=affiliate&utm_source=Example+API+Employer"
                }
            ]
        }
    }
}

The url field is the landing page for this procedure on MDsave (they will be mdsave.com urls in production). You can send a user to this page where they can use the MDsave marketplace to continue searching and purchase on the marketplace web site.

The id field returned for each procedure will be the value you will use to reference any of these procedures in future queries. For example, in the next step, we will use the procedure id to search for offers of that procedure.

{
    "id": 1391,
    "name": "CT Scan with Contrast",
    "url": "https://demo.mdsave.com/procedures/ct-scan-with-contrast/d781f5cc?utm_medium=affiliate&utm_source=Example+API+Employer"
}  

By CPT Code

You can also use the searchProcedures query to find procedures by searching their bundled CPT codes. Generally any query will return _any _procedure that contains any of the CPT codes and some common codes are used in many related bundles on MDsave.

Use the searchProcedures query to send a list of CPT codes to find any procedures that contain those codes. In this example, we will use the CPT code 71260 , which is included in some kinds of CT Scan with Contrast.

query searchProcedures(
  $query: SearchProceduresInput!,
  $pagination: Pagination
) {
  searchProcedures(
    query: $query,
    pagination: $pagination
  ) {
    procedures {
      id
      name
      url
    }
  }
}  

{
  "query": {
    "procedureCodes": {
        "cptCodes": ["71260"]
    }
  },
  "pagination": {"offset": 0, "limit": 10}
}  

{
    "data": {
        "searchProcedures": {
            "procedures": [
                {
                    "id": 1399,
                    "name": "CT Scan of Abdomen and Pelvis with Contrast",
                    "url": "https://demo.mdsave.com/procedures/ct-scan-of-abdomen-and-pelvis-with-contrast/d781f5c4?utm_medium=affiliate&utm_source=Example+API+Employer"
                }
            ]
        }
    }
}  

2. Search for Offers by Location

Now let’s say the user has selected the “CT Scan with Contrast” procedure from the results in step 1 (id: 1391) and we now want to search for offers for that procedure within 50 miles of a certain zip code: 75001 (Dallas, TX).

Use the searchOffers query to look for offers at a location for this procedure:

  • In the query data, we will provider a location with zip code 75001 and radius 50, as well as a procedureId in procedureCodes that corresponds to the procedure we searched for (id 1391). This will return all offers for a ‘CT Scan with Contrast’ procedure within 50 miles of that zip code.
  • We can order these results as well, we will send total_price in orderBy.field value. This will return the lowest prices at the top.
  • You can also order by distance as well that will return the offers closes to the zip code first.
query searchOffers(
    $query: SearchOffersInput!,
    $pagination: Pagination,
    $orderBy: [OrderBy]
) {
    searchOffers(
    query: $query,
    pagination: $pagination,
    orderBy: $orderBy
    ) {
    items {
        offer {
        id
        description
        price
        schedulePhone
        procedure {
            id
            name
        }
        provider {
            id
            fullName
            providerName
            hospital {
                id
                name
                npi
            }
        }
        }
    }
    messages {
        type
        message
    }
    requestId
    }
}  

{
  "query": {
    "location": {
        "zipCode": "75001",
        "radius": 50
    },
    "procedureCodes": {
        "procedureIds": [
            1391
        ]
    }
  },
  "pagination": {"offset": 0, "limit": 15},
  "orderBy": {
    "field": "total_price",
    "direction": "ASC"
  }
}  

This returns the results below. Each offer has a unique description that is customized by the provider that is offering it which may show different included services. There is also a schedulePhone value that is the office number that can be called to schedule the patient.

{
"data": {
    "searchOffers": {
        "items": [
            {
                "offer": {
                    "id": 335067,
                    "description": "Procedure Details: This is a CT scan with dye of ANY ONE body part: Spine, Lumbar, Chest, Orbit, Face, Neck, Sinus, Abdomen, Pelvis, Brain or Lower/Upper Extremity. If the patient needs more than one body part scanned, the appropriate number of scans must be purchased.<br/><br/>Price Details: Your purchase includes the following services:<br/>Facility fee - technical (equipment) fee for the imaging<br/>Physician fee - physician interpretation fee",
                    "url": "https://demo.mdsave.com/p/medical-city-dallas-imaging-center-imaging-and-radiology/ct-scan-with-contrast/d581f9cd64da?utm_medium=affiliate&utm_source=Example+API+Employer",
                    "price": 278,
                    "schedulePhone": "(972) 566-2900",
                    "procedure": {
                        "id": 1391,
                        "name": "CT Scan with Contrast"
                    },
                    "provider": {
                        "id": 13030,
                        "fullName": "Medical City Dallas Imaging Center",
                        "providerName": "Medical City Dallas Imaging Center",
                        "hospital": {
                            "id": 2665,
                            "name": "Medical City Dallas Imaging Center",
                            "npi": "1235199829"
                        }
                    }
                }
            },
            {
                "offer": {
                    "id": 335684,
                    "description": "Procedure Details: This is a CT scan with dye of ANY ONE body part: Spine, Lumbar, Chest, Orbit, Face, Neck, Sinus, Abdomen, Pelvis, Brain or Lower/Upper Extremity. If the patient needs more than one body part scanned, the appropriate number of scans must be purchased.<br/><br/>Price Details: Your purchase includes the following services:<br/>Facility fee - technical (equipment) fee for the imaging<br/>Physician fee - physician interpretation fee",
                    "url": "https://demo.mdsave.com/p/preferred-imaging-of-plano-lp-imaging-and-radiology/ct-scan-with-contrast/d581f9cb6ad9?utm_medium=affiliate&utm_source=Example+API+Employer",
                    "price": 304,
                    "schedulePhone": "(972) 312-0799",
                    "procedure": {
                        "id": 1391,
                        "name": "CT Scan with Contrast"
                    },
                    "provider": {
                        "id": 13070,
                        "fullName": "Preferred Imaging Of Plano Lp",
                        "providerName": "Preferred Imaging Of Plano Lp",
                        "hospital": {
                            "id": 2705,
                            "name": "Preferred Imaging Of Plano Lp",
                            "npi": "1861575615"
                        }
                    }
                }
            },
            {
                "offer": {
                    "id": 335594,
                    "description": "Procedure Details: This is a CT scan with dye of ANY ONE body part: Spine, Lumbar, Chest, Orbit, Face, Neck, Sinus, Abdomen, Pelvis, Brain or Lower/Upper Extremity. If the patient needs more than one body part scanned, the appropriate number of scans must be purchased.<br/><br/>Price Details: Your purchase includes the following services:<br/>Facility fee - technical (equipment) fee for the imaging<br/>Physician fee - physician interpretation fee",
                    "url": "https://demo.mdsave.com/p/preferred-imaging-of-frisco-imaging-and-radiology/ct-scan-with-contrast/d581f9c86bd9?utm_medium=affiliate&utm_source=Example+API+Employer",
                    "price": 304,
                    "schedulePhone": "(469) 300-2025",
                    "procedure": {
                        "id": 1391,
                        "name": "CT Scan with Contrast"
                    },
                    "provider": {
                        "id": 13065,
                        "fullName": "Preferred Imaging Of Frisco",
                        "providerName": "Preferred Imaging Of Frisco",
                        "hospital": {
                            "id": 2700,
                            "name": "Preferred Imaging Of Frisco",
                            "npi": "1881028397"
                        }
                    }
                }
            }
        ],
        "messages": [
            {
                "type": "Success",
                "message": ""
            }
        ],
        "requestId": "1e4f4b04-3cb3-40c8-9746-ffeebbf678e0"
    }
}
}

We will capture the offer id and the hospital npi values for one of these offers for the next steps.

3. Create a Shopping Cart

Next, let’s say the user has selected one of these offers. The $155 CT Scan with Contrast at Medical City – Offer id 335067 with hospital NPI 1235199829.

{
    "offer": {
        "id": 335067,
        "description": "Procedure Details: This is a CT scan with dye of ANY ONE body part: Spine, Lumbar, Chest, Orbit, Face, Neck, Sinus, Abdomen, Pelvis, Brain or Lower/Upper Extremity. If the patient needs more than one body part scanned, the appropriate number of scans must be purchased.<br/><br/>Price Details: Your purchase includes the following services:<br/>Facility fee - technical (equipment) fee for the imaging<br/>Physician fee - physician interpretation fee",
        "url": "https://demo.mdsave.com/p/medical-city-dallas-imaging-center-imaging-and-radiology/ct-scan-with-contrast/d581f9cd64da?utm_medium=affiliate&utm_source=Example+API+Employer",
        "price": 278,
        "schedulePhone": "(972) 566-2900",
        "procedure": {
            "id": 1391,
            "name": "CT Scan with Contrast"
        },
        "provider": {
            "id": 13030,
            "fullName": "Medical City Dallas Imaging Center",
            "providerName": "Medical City Dallas Imaging Center",
            "hospital": {
                "id": 2665,
                "name": "Medical City Dallas Imaging Center",
                "npi": "1235199829"
            }
        }
    }
}  

Now we will building a shopping cart with that Offer in it. We will need to provide patient demographic information as well that will be used when checking out the ShoppingCart. It will be up to you to fill in the patient information, but it could come from a user typing in their information in the context of a web application or filled in from some another data source.

To do this, we will use the createShoppingCart mutation, which takes these objects in the query:

  • patient (PatientInput)

    • email, firstName, lastName, dateOfBirth, phoneNumber
  • hospital (HospitalInput)

    • use the npi value from the Offer: "1235199829"
  • procedureCodes (ProcedureCodesInput)

    • in offerIds add the Offer id : 335067
mutation createShoppingCart(
    $patient: PatientInput,
    $hospital: HospitalInput,
    $procedureCodes: ProcedureCodesInput
) {
    createShoppingCart(
    patient: $patient,
    hospital: $hospital,
    procedureCodes: $procedureCodes
    ) {
    shoppingCart {
        id
        url
        patient {
        email
        firstName
        lastName
        dateOfBirth
        phoneNumber
        }
        items {
        offer {
            id
        }
        quantity
        price
        }
        totalPrice
        status
    }
    messages {
        type
        message
    }
    requestId
    }
}

{
  "patient": {
    "email": "testpatient@mdsave.com",
    "firstName": "abc123",
    "lastName": "xyz789",
    "dateOfBirth": "2000-01-01",
    "phoneNumber": "5555555555"
  },
  "hospital": {
    "npi": "1235199829"
  },
  "procedureCodes": {
    "offerIds": [335067]
  }
}  

The Shopping Cart URLs can be sent to the patient or to someone who has authorization to transact for the patient to checkout directly on the MDsave website. Since these carts can be created programmatically, the URLs to the pre-built shopping cart could be emailed out or surfaced in another system to reference and complete the checkout.

The API returned a “Success” message with the shoppingCart id and url. The id is the value that we will use to checkout this cart in the next step.

{
    "data": {
        "createShoppingCart": {
            "shoppingCart": {
                "id": "66ccf071b929e1.92169779",
                "url": "https://demo.mdsave.com/carepackage/66ccf071b929e1.92169779?utm_medium=affiliate&utm_source=Example+API+Employer",
                "patient": {
                    "email": "testpatient@mdsave.com",
                    "firstName": "Abc123",
                    "lastName": "Xyz789",
                    "dateOfBirth": "2000-01-01",
                    "phoneNumber": "5555555555"
                },
                "items": [
                    {
                        "offer": {
                            "id": 335067
                        },
                        "quantity": 1,
                        "price": 278
                    }
                ],
                "totalPrice": 278,
                "status": "Active"
            },
            "messages": [
                {
                    "type": "Success",
                    "message": ""
                }
            ],
            "requestId": "1e4f4b04-3cb3-40c8-9746-ffeebbf678e0"
        }
    }
}  

4. Checkout a Shopping Cart

Now we can checkout that shopping cart to purchase Vouchers for the patient for all the Offers that were in the shopping cart. In this example, we will use the shopping cart that we built in the previous step:

"shoppingCart": {
  "id": "66ccf071b929e1.92169779",
  "url": "https://demo.mdsave.com/carepackage/66ccf071b929e1.92169779?utm_medium=affiliate&utm_source=Example+API+Employer",
}  

Build the checkout mutation and send it to complete the transaction. Note that invoice purchases are the only type of transaction that can be completed through the API right now.

  • shoppingCartId - returned from the createShoppingCart query in step 3

  • paymentMethods - in production this will always need to be {"invoicing": true}

  • isScheduled - in a normal workflow when checking out, the patient is asked if they need to be scheduled. If this value is set to true, the provider is notified by MDsave that the patient needs scheduling, and they will reach out.

  • sendEmail - If this is checked, then the patient’s email in the shopping cart will receive an email from MDsave with the voucher and any instructions from the provider. The sandbox will not send emails out.

mutation checkout($data: CheckoutInput!) {
    checkout(data: $data) {
    voucherNumbers
    voucherPDFUrl
    messages {
        type
        message
    }
    isSuccess
    requestId
    }
}

{
    "data": {
        "shoppingCartId": "66ccf071b929e1.92169779",
        "paymentMethods": {"invoicing": true},
        "address": {
            "street": "123 Main St",
            "city": "Dallas",
            "state": "TX",
            "zipCode": "75001"
        },
        "isScheduled": false,
        "sendEmail": true
    }
}  

An isSuccess:true in the response means the transaction went through. There will be a voucherPDFUrl link also in the response that will be active for 24 hours that can be used to download a copy of the Voucher as a PDF.

{
    "data": {
        "checkout": {
            "voucherNumbers": [
                "8614600-01"
            ],
            "voucherPDFUrl": "https://demo.mdsave.com/ExportPdf/8614600/de84fdc964dd1331aff40459c73bc463913b634b88f0cc1a212e66f5a958a6141327fdeb106e/print",
            "messages": [
                {
                    "type": "Success",
                    "message": "Thank you! Your purchase has been successfully submitted"
                }
            ],
            "isSuccess": true,
            "requestId": "1e4f4b04-3cb3-40c8-9746-ffeebbf678e0"
        }
    }
}  

5. Retrieve Previous Voucher Purchases

Now that we’ve made a purchase, we can use the searchVouchers query to return the previously purchased voucher data. Note that the URLs to the Voucher PDFs will only work for 24 hours after the voucher is purchased.

You can query within a purchasedDate time period as well as by status.

query searchVouchers(
  $query: SearchVouchersInput!,
  $pagination: Pagination
) {
  searchVouchers(
    query: $query,
    pagination: $pagination
  ) {
    items {
      id
      voucherNumber
      status
      price
      purchasedDate
      patient {
        firstName
        lastName
        email
      }
      offer {
        id
        provider {
            hospital {
                id
                npi
            }
        }
        procedure {
            id
        }
      }
    }
    messages {
      type
      message
    }
    requestId
  }
}  

{
  "query": {
    "status": "Available",
    "purchasedDate": {
      "start": "2024-08-01",
      "end": "2024-08-31"
    }
  },
  "pagination": { "offset": 0, "limit": 100}
}  

The results will return the voucher that was just purchased through the checkout mutation showing a status of Available.

{
    "data": {
        "searchVouchers": {
            "items": [
                {
                    "id": 861940,
                    "voucherNumber": "8619401-01",
                    "status": "Available",
                    "price": 278,
                    "purchasedDate": "2024-08-27",
                    "patient": {
                        "firstName": "Abc123",
                        "lastName": "Xyz789",
                        "email": "testpatient@mdsave.com"
                    },
                    "offer": {
                        "id": 335067,
                        "provider": {
                            "hospital": {
                                "id": 2665,
                                "npi": "1235199829"
                            }
                        },
                        "procedure": {
                            "id": 1399
                        }
                    }
                }
            ],
            "messages": [
                {
                    "type": "Success",
                    "message": ""
                }
            ],
            "requestId": "1e4f4b04-3cb3-40c8-9746-ffeebbf678e0"
        }
    }
}  

Once the patient receives care and MDsave receives payment from your organization, in the Voucher will go into a Used status, and will be available to query in that status in perpetuity.

How to Get help

If you or your team have additional questions about the GraphQL API or issues getting started with the Sandbox Environment, you can reach out to our API support email mdsaveapi@tendo.com and our Engineering team can assist you.

API Limitations

Current API Limitations

The following outlines current limitations of the MDsave API. These constraints reflect features that are planned or under consideration, but not yet supported. We encourage you to review this list when designing your integration workflows

Platform Scope

  • Care Navigation Only: The API is intended for use by care navigation organizations (purchasers on MDsave), not providers (sellers on MDsave).

Voucher Management

  • Voucher Redemption Not Supported: The API cannot be used to process or cancel vouchers, only to purchase them.
  • Voucher Visibility: Only vouchers purchased by the partner organization are accessible.
  • No Voucher Change Notifications: There is no webhook or subscription support for voucher updates.

Cart Management

  • Quantity Edits Require Multiple Calls: To adjust quantities in the cart, you must issue multiple addShoppingCartItems calls (e.g., to add a quantity of 2, call the method twice).
  • Cart Sharing: The API supports cart sharing via a generated URL, but sharing must be handled by the partner. Split payment for shared carts is not supported.

Pricing and Payment

  • No Price Context: Estimated commercial rates and Medicare benchmark percentages are not currently returned.

  • Pricing Groups:

    • Group names (e.g., Consumer or Employer-Only) are not displayed in search results.
    • You cannot specify a pricing group when searching; results are limited to the partner's default and public access.
  • Payment Options: Supported methods include credit card and employer invoicing.

    • Split payments, PayPal, multiple card support, and Care Credit are not available.
    • Invoice download is not supported.

User and Employer Features

  • No User Management: Partners cannot create care navigator users or manage organizational settings via the API.
  • No Deductible Check: Real-time deductible or benefits checks are not supported.
  • Insurance & Plan of Care Fields: The following fields are not available. Employers requiring any of the above for claims submission or tracking will not be able to complete checkouts or share carts via the API.
    • Insurance Plan
    • Member ID
    • Group ID
    • Plan of Care Identifier

Clinical Data

  • Quality Ratings: Provider quality ratings are not included in search or offer data.

We are continuously working to enhance the MDsave API and welcome your feedback on what features would be most useful in future releases. For questions or suggestions, please contact mdsaveapi@tendo.com.

Queries

searchInsuranceProviders

Description

Search insurance providers returns the list of insurance providers that are accepted at a particular hospital

Arguments
Name Description
query - SearchInsuranceProvidersInput!
pagination - Pagination

Example

Query
query searchInsuranceProviders(
  $query: SearchInsuranceProvidersInput!,
  $pagination: Pagination
) {
  searchInsuranceProviders(
    query: $query,
    pagination: $pagination
  ) {
    insuranceProviders {
      ...InsuranceProviderFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{
  "query": SearchInsuranceProvidersInput,
  "pagination": Pagination
}
Response
{
  "data": {
    "searchInsuranceProviders": {
      "insuranceProviders": [InsuranceProvider],
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

searchLocations

Description

Search for location data using a free-form text query. The text input can be a city, city/state, or zip code. The response will be a list of matching cities and all the zip codes those cities contain.

Response

Returns a SearchLocationResponse!

Arguments
Name Description
query - SearchLocationInput!

Example

Query
query searchLocations($query: SearchLocationInput!) {
  searchLocations(query: $query) {
    items {
      ...LocationFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{"query": SearchLocationInput}
Response
{
  "data": {
    "searchLocations": {
      "items": [Location],
      "messages": [Message],
      "requestId": "abc123"
    }
  }
}

searchOffers

Description

Search for MDsave offers - returns paginated Offer results

Response

Returns a SearchOffersResponse!

Arguments
Name Description
query - SearchOffersInput!
pagination - Pagination
orderBy - [OrderBy]

Example

Query
query searchOffers(
  $query: SearchOffersInput!,
  $pagination: Pagination,
  $orderBy: [OrderBy]
) {
  searchOffers(
    query: $query,
    pagination: $pagination,
    orderBy: $orderBy
  ) {
    items {
      ...SearchOffersItemFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{
  "query": SearchOffersInput,
  "pagination": Pagination,
  "orderBy": [OrderBy]
}
Response
{
  "data": {
    "searchOffers": {
      "items": [SearchOffersItem],
      "messages": [Message],
      "requestId": "abc123"
    }
  }
}

searchProcedures

Description

Search for MDsave procedures by name. This query will accept a partial, case-insensitive string and will return a paginated list of all matching results.

Response

Returns a SearchProceduresResponse!

Arguments
Name Description
query - SearchProceduresInput!
pagination - Pagination

Example

Query
query searchProcedures(
  $query: SearchProceduresInput!,
  $pagination: Pagination
) {
  searchProcedures(
    query: $query,
    pagination: $pagination
  ) {
    procedures {
      ...ProcedureFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{
  "query": SearchProceduresInput,
  "pagination": Pagination
}
Response
{
  "data": {
    "searchProcedures": {
      "procedures": [Procedure],
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

searchVouchers

Description

Search for MDsave vouchers -- returns paginated Voucher results

Response

Returns a SearchVouchersResponse!

Arguments
Name Description
query - SearchVouchersInput!
pagination - Pagination

Example

Query
query searchVouchers(
  $query: SearchVouchersInput!,
  $pagination: Pagination
) {
  searchVouchers(
    query: $query,
    pagination: $pagination
  ) {
    items {
      ...VoucherFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{
  "query": SearchVouchersInput,
  "pagination": Pagination
}
Response
{
  "data": {
    "searchVouchers": {
      "items": [Voucher],
      "messages": [Message],
      "requestId": "abc123"
    }
  }
}

shoppingCart

Description

Retrive data for an already created ShoppingCart using its id

Response

Returns a ShoppingCartResponse

Arguments
Name Description
id - String!

Example

Query
query shoppingCart($id: String!) {
  shoppingCart(id: $id) {
    shoppingCart {
      ...ShoppingCartFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{"id": "xyz789"}
Response
{
  "data": {
    "shoppingCart": {
      "shoppingCart": ShoppingCart,
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

validateKey

Description

Validate the token

Response

Returns a ValidateKeyResponse!

Example

Query
query validateKey {
  validateKey {
    isSuccess
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Response
{
  "data": {
    "validateKey": {
      "isSuccess": false,
      "messages": [Message],
      "requestId": "abc123"
    }
  }
}

Mutations

addShoppingCartItems

Description

Add items to an existing Shopping Cart. If a specified procedure already exists on the Shopping Cart, the procedure quantity will be increased.

Response

Returns a ShoppingCartResponse

Arguments
Name Description
input - AddShoppingCartItemsInput Input for adding items to a shopping cart.

Example

Query
mutation addShoppingCartItems($input: AddShoppingCartItemsInput) {
  addShoppingCartItems(input: $input) {
    shoppingCart {
      ...ShoppingCartFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{"input": AddShoppingCartItemsInput}
Response
{
  "data": {
    "addShoppingCartItems": {
      "shoppingCart": ShoppingCart,
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

checkout

Description

Automatically complete the checkout of a Shopping Cart

Response

Returns a CheckoutResponse!

Arguments
Name Description
data - CheckoutInput Deprecated. Use 'input' argument instead.
input - CheckoutInput Input for completing the checkout of a shopping cart.

Example

Query
mutation checkout(
  $data: CheckoutInput,
  $input: CheckoutInput
) {
  checkout(
    data: $data,
    input: $input
  ) {
    voucherNumbers
    voucherPDFUrl
    messages {
      ...MessageFragment
    }
    isSuccess
    paymentMethods {
      ...PaymentMethodsFragment
    }
    requestId
  }
}
Variables
{
  "data": CheckoutInput,
  "input": CheckoutInput
}
Response
{
  "data": {
    "checkout": {
      "voucherNumbers": ["xyz789"],
      "voucherPDFUrl": "abc123",
      "messages": [Message],
      "isSuccess": false,
      "paymentMethods": PaymentMethods,
      "requestId": "xyz789"
    }
  }
}

createShoppingCart

Description

Create a Shopping Cart using patient, hospital, and Procedure codes. If a CPT code for a procedure is included in the Procedure Codes two or more times, multiple instances of the procedure will be added to the cart.

Response

Returns a ShoppingCartResponse

Arguments
Name Description
patient - PatientInput Deprecated. Use the 'patient' field in the 'input' argument instead.
hospital - HospitalInput Deprecated. Use the 'hospital' field in the 'input' argument instead.
procedureCodes - ProcedureCodesInput Deprecated. Use the 'procedureCodes' field in the 'input' argument instead.
provider - ProviderInput Deprecated. Use the 'providers' field in the 'input' argument instead.
input - CreateShoppingCartInput Input for creating a shopping cart.

Example

Query
mutation createShoppingCart(
  $patient: PatientInput,
  $hospital: HospitalInput,
  $procedureCodes: ProcedureCodesInput,
  $provider: ProviderInput,
  $input: CreateShoppingCartInput
) {
  createShoppingCart(
    patient: $patient,
    hospital: $hospital,
    procedureCodes: $procedureCodes,
    provider: $provider,
    input: $input
  ) {
    shoppingCart {
      ...ShoppingCartFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{
  "patient": PatientInput,
  "hospital": HospitalInput,
  "procedureCodes": ProcedureCodesInput,
  "provider": ProviderInput,
  "input": CreateShoppingCartInput
}
Response
{
  "data": {
    "createShoppingCart": {
      "shoppingCart": ShoppingCart,
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

removeShoppingCartItems

Description

Remove items from an existing Shopping Cart.

Response

Returns a ShoppingCartResponse

Arguments
Name Description
input - RemoveShoppingCartItemsInput Input from removing items from a shopping cart.

Example

Query
mutation removeShoppingCartItems($input: RemoveShoppingCartItemsInput) {
  removeShoppingCartItems(input: $input) {
    shoppingCart {
      ...ShoppingCartFragment
    }
    messages {
      ...MessageFragment
    }
    requestId
  }
}
Variables
{"input": RemoveShoppingCartItemsInput}
Response
{
  "data": {
    "removeShoppingCartItems": {
      "shoppingCart": ShoppingCart,
      "messages": [Message],
      "requestId": "xyz789"
    }
  }
}

Types

AddShoppingCartItemsInput

Description

The input payload needed to add items to an existing Shopping Cart.

Fields
Input Field Description
shoppingCartId - String! Id of shopping cart to add procedures to.
hospital - HospitalInput Hospital at which the specified procedures are offered.
procedureCodes - ProcedureCodesInput Procedures to add to the shopping cart.
provider - ProviderInput Provider who provides the specified procedures.
Example
{
  "shoppingCartId": "xyz789",
  "hospital": HospitalInput,
  "procedureCodes": ProcedureCodesInput,
  "provider": ProviderInput
}

Address

Fields
Field Name Description
street - String!
city - String!
state - State!
zipCode - ZipCode!
latitude - Float! latitude of the center of the zip code area
longitude - Float! longitude of the center of the zip code area
Example
{
  "street": "abc123",
  "city": "abc123",
  "state": State,
  "zipCode": ZipCode,
  "latitude": 987.65,
  "longitude": 987.65
}

AddressInput

Fields
Input Field Description
street - String!
city - String!
state - State!
zipCode - ZipCode!
Example
{
  "street": "xyz789",
  "city": "xyz789",
  "state": State,
  "zipCode": ZipCode
}

Boolean

Description

The Boolean scalar type represents true or false.

CacheControlScope

Values
Enum Value Description

PUBLIC

PRIVATE

Example
"PUBLIC"

CheckoutInput

Description

The input payload needed to complete the checkout of a Shopping Cart

Fields
Input Field Description
shoppingCartId - String! Id of the shopping cart to complete -- This is returned when creating a Shopping Cart.
paymentMethods - PaymentMethodsInput! The methods of payment to be used to complete checkout.
isScheduled - Boolean! Whether or not the patient this cart is for has already been scheduled for an appointment or not.
sendEmail - Boolean Whether to send the patient an email with a copy of the voucher or not. Default = true
Example
{
  "shoppingCartId": "xyz789",
  "paymentMethods": PaymentMethodsInput,
  "isScheduled": true,
  "sendEmail": false
}

CheckoutResponse

Description

The result of a checkout request. Will return whether or not the action was successful and more details in the message object.

Fields
Field Name Description
voucherNumbers - [String!] List of voucher numbers that were generated as part of the checkout process.
voucherPDFUrl - String A link directly to a PDF report of the vouchers generated.
messages - [Message!] Technical details about the result of the checkout.
isSuccess - Boolean! Whether or not the checkout was successful.
paymentMethods - PaymentMethods All payment methods that were used to complete the checkout.
requestId - String!
Example
{
  "voucherNumbers": ["abc123"],
  "voucherPDFUrl": "xyz789",
  "messages": [Message],
  "isSuccess": false,
  "paymentMethods": PaymentMethods,
  "requestId": "abc123"
}

Consultation

Fields
Field Name Description
requiresOfficeVisit - Boolean! Whether or not the offer requires an office visit with the provider before being performed. The office visit is not included in the purchase of this offer. For some providers, this office visit can be purchased as a separate procedure through the API.
requiresOrder - Boolean! Whether or not the offer requires a physician’s order before being performed. The order can be faxed or brought to the appointment unless required when scheduling. For out-of-state orders, please verify with the provider that they accept it.
Example
{"requiresOfficeVisit": true, "requiresOrder": false}

CptCode

Description

CptCode custom scalar type

Example
CptCode

CreateShoppingCartInput

Description

The input payload needed to create a Shopping Cart.

Fields
Input Field Description
patient - PatientInput Patient for whom the shopping cart is for.
hospital - HospitalInput Hospital at which the specified procedures are offered.
procedureCodes - ProcedureCodesInput Procedures to add to the shopping cart.
provider - ProviderInput Provider who provides the specified procedures.
planOfCareIdentifier - String Id for patient's plan of care.
Example
{
  "patient": PatientInput,
  "hospital": HospitalInput,
  "procedureCodes": ProcedureCodesInput,
  "provider": ProviderInput,
  "planOfCareIdentifier": "xyz789"
}

CreditCard

Description

A credit card that was used for a checkout returned from the checkout mutation.

Fields
Field Name Description
number - String! All but the last 4 digits of the Credit Card number will be masked with asterisks
expDate - CreditCardExpDate! Expiration date of the ccard in the format mm/dd
Example
{
  "number": "xyz789",
  "expDate": CreditCardExpDate
}

CreditCardExpDate

Description

CreditCardExpDate custom scalar type

Example
CreditCardExpDate

CreditCardInput

Description

The input payload representing a credit card to be used for checkout.

Fields
Input Field Description
number - CreditCardNumber! 16 digit number on the card
cvv - String! The CVV code (usually on the back of the card)
firstName - String First name of the card's owner
lastName - String Last name of the card's owner
expDate - CreditCardExpDate! Expiration date of the card in the format mm/dd
zipCode - ZipCode! Zip code of the card
Example
{
  "number": CreditCardNumber,
  "cvv": "abc123",
  "firstName": "xyz789",
  "lastName": "abc123",
  "expDate": CreditCardExpDate,
  "zipCode": ZipCode
}

CreditCardNumber

Description

CreditCardNumber custom scalar type

Example
CreditCardNumber

Date

Description

Date custom scalar type

Example
"2007-12-03"

DateRange

Fields
Input Field Description
start - ShortDate!
end - ShortDate
Example
{
  "start": ShortDate,
  "end": ShortDate
}

DirectionsEnum

Values
Enum Value Description

ASC

DESC

Example
"ASC"

EncryptionKey

Description

Contains information about the unique id, private key, public key, last used date, it is production key or no, previous encryption key and more details about encryption key. This object represents an Encryption Key

Fields
Field Name Description
id - Int! It is unique number of EncryptionKey
private_key - String! It is private key encrypted by RSA
public_key - String! It is public key encrypted by RSA
last_used_at - Date Default it is null, but if the encryption key used at least once than it should be last used date
prod - Boolean! True if EncryptionKey is production.
previous - EncryptionKey It is previous EncryptionKey (optional)
encryptionKeyDetails - EncryptionKeyDetails It is additional data about EncryptionKey (optional)
Example
{
  "id": 123,
  "private_key": "xyz789",
  "public_key": "xyz789",
  "last_used_at": "2007-12-03",
  "prod": false,
  "previous": EncryptionKey,
  "encryptionKeyDetails": EncryptionKeyDetails
}

EncryptionKeyDetails

Description

Contains information about the public user id, portal id, sso id. This object represents an Encryption Key Details

Fields
Field Name Description
publicUserId - Int It is public user id of EncryptionKey owner
portalId - Int It is portal id of EncryptionKey owner
ssoId - Int It is sso id of EncryptionKey owner
Example
{"publicUserId": 123, "portalId": 123, "ssoId": 987}

EncryptionKeyDetailsInput

Description

The input representing a encryption key details to be used for set in Redis

Fields
Input Field Description
publicUserId - Int
portalId - Int
ssoId - Int
Example
{"publicUserId": 123, "portalId": 123, "ssoId": 123}

EncryptionKeyDetailsInterface

Fields
Field Name Description
publicUserId - Int
portalId - Int
ssoId - Int
Possible Types
EncryptionKeyDetailsInterface Types

EncryptionKeyDetails

Example
{"publicUserId": 987, "portalId": 123, "ssoId": 123}

EncryptionKeyInput

Description

The input representing a encryption key to be used for set in Redis

Fields
Input Field Description
id - Int!
private_key - String!
public_key - String!
last_used_at - Date
prod - Boolean!
previous - EncryptionKeyInput
encryptionKeyDetails - EncryptionKeyDetailsInput
Example
{
  "id": 987,
  "private_key": "xyz789",
  "public_key": "xyz789",
  "last_used_at": "2007-12-03",
  "prod": false,
  "previous": EncryptionKeyInput,
  "encryptionKeyDetails": EncryptionKeyDetailsInput
}

EncryptionKeyInterface

Fields
Field Name Description
id - Int!
private_key - String!
public_key - String!
last_used_at - Date
prod - Boolean!
previous - EncryptionKey
encryptionKeyDetails - EncryptionKeyDetails
Possible Types
EncryptionKeyInterface Types

EncryptionKey

Example
{
  "id": 123,
  "private_key": "abc123",
  "public_key": "xyz789",
  "last_used_at": "2007-12-03",
  "prod": false,
  "previous": EncryptionKey,
  "encryptionKeyDetails": EncryptionKeyDetails
}

FeeEnum

Values
Enum Value Description

Facility

Physician

Radiology

Anesthesia

Pathology

BundlingProcessing

ThirdPartyNetwork

Example
"Facility"

Float

Description

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

Example
123.45

Hospital

Description

A specific hospital's representation in MDsave. Includes an MDsave unique identifier as well as the unique NPI number.

Fields
Field Name Description
id - Int! MDsave's unique identifier
name - String! The hospital's name
npi - String 10 digit unique NPI number representing the hospital
Example
{
  "id": 987,
  "name": "abc123",
  "npi": "abc123"
}

HospitalInput

Fields
Input Field Description
id - Int
name - String
npi - String
Example
{
  "id": 987,
  "name": "xyz789",
  "npi": "xyz789"
}

Hours

Fields
Field Name Description
weekDay - WeekDaysEnum!
closed - Boolean!
workStart - String
workEnd - String
Example
{
  "weekDay": "Sunday",
  "closed": true,
  "workStart": "abc123",
  "workEnd": "xyz789"
}

Insurance

Description

Information representing insurance information

Fields
Field Name Description
groupId - String Group id for the insurance plan.
memberId - String Member id of insured party.
plan - String Insurance plan identifier.
Example
{
  "groupId": "abc123",
  "memberId": "xyz789",
  "plan": "xyz789"
}

InsuranceInput

Description

The input payload needed store insurance information

Fields
Input Field Description
groupId - String Group id for the insurance plan.
memberId - String Member id of insured party.
plan - String Insurance plan identifier.
Example
{
  "groupId": "abc123",
  "memberId": "xyz789",
  "plan": "xyz789"
}

InsuranceProvider

Description

Contains information about the unique id and name insurance provider. This object represents an Insurance Provider

Fields
Field Name Description
id - Int! It is unique id of InsuranceProvider
name - String! It is name of InsuranceProvider
Example
{"id": 987, "name": "abc123"}

Int

Description

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.

Example
123

Location

Fields
Field Name Description
city - String!
state - String!
zipCode - ZipCode!
Example
{
  "city": "xyz789",
  "state": "abc123",
  "zipCode": ZipCode
}

LocationInput

Description

Values used in a location-based search.

Fields
Input Field Description
zipCode - ZipCode 5 Digit US Postal Zip Code
radius - Int Max Distance in miles from this location to include results.
Example
{"zipCode": ZipCode, "radius": 123}

Message

Description

Messages are objects returned by the checkout endpoint that contain information about the result of the request.

Message types:

Error: The checkout was unsuccessful, and the message contains information about what went wrong.

Info: The checkout was successful and the message contains non-critical information about the result.

Success: The checkout was successful and there were no issues.

Warning : The checkout was successful but there were issues that need to be addressed.

Fields
Field Name Description
type - MessageEnum! The type of message is determined by the results of the request.
message - String! The text of the message.
Example
{"type": "Error", "message": "xyz789"}

MessageEnum

Description

Message Types can be one of the following strings

Values
Enum Value Description

Error

Info

Success

Warning

Example
"Error"

Notification

Description

The notifications related to MDsave medical procedures and services the partner is required to show.

Fields
Field Name Description
key - NotificationEnum! Uniquely identified type of the notification
label - String! Brief title or heading for the notification
value - String! Detailed message or information of the notification. May contain HTML formatting.
Example
{
  "key": "TermsAndConditions",
  "label": "xyz789",
  "value": "xyz789"
}

NotificationEnum

Values
Enum Value Description

TermsAndConditions

RequiresOrder

RequiresOfficeVisit

StandardDisclaimer

AdditionalFees

Virtual

Example
"TermsAndConditions"

Offer

Description

An Offer represents a grouping of CPT codes for a provider that has a total price precalculated and information about the procedure included.

Fields
Field Name Description
id - Int!
provider - Provider! Medical provider this offer was build for.
procedure - Procedure! Specific procedure in the offer.
procedureFees - [ProcedureFee!] Procedure fees in the offer.
price - Float! Total price for the entire procedure in this offer including the promotional discount.
originalPrice - Float! Original price for the entire procedure in this offer.
promotionalDiscount - Float! Promotional discount for the entire procedure in this offer.
scheduleType - String
scheduleUrl - String
schedulePhone - PhoneNumber
description - String!
url - String!
cptCodes - [CptCode!] All CPT codes that are in this offer.
mnemonicCodes - [String!] List of 4 letter codes
createdTime - Date!
lastUpdatedTime - Date!
isPublic - Boolean
canonicalUrl - String
excludedCPTCodes - [CptCode!] The list of CPT codes this provider does not perform as part of this offer.
consultationType - Consultation!
notifications - [Notification!]
placeOfService - PlaceOfServiceEnum! Place of service is used to designate the type of visit, virtual or in-person, and if in-person, the type of facility.
displayName - String!
Example
{
  "id": 987,
  "provider": Provider,
  "procedure": Procedure,
  "procedureFees": [ProcedureFee],
  "price": 123.45,
  "originalPrice": 987.65,
  "promotionalDiscount": 987.65,
  "scheduleType": "xyz789",
  "scheduleUrl": "abc123",
  "schedulePhone": "+17895551234",
  "description": "abc123",
  "url": "abc123",
  "cptCodes": [CptCode],
  "mnemonicCodes": ["abc123"],
  "createdTime": "2007-12-03",
  "lastUpdatedTime": "2007-12-03",
  "isPublic": true,
  "canonicalUrl": "xyz789",
  "excludedCPTCodes": [CptCode],
  "consultationType": Consultation,
  "notifications": [Notification],
  "placeOfService": "Facility",
  "displayName": "abc123"
}

OfferInput

Description

The input payload needed to select the offers that are under promotions

Fields
Input Field Description
promotedProcedures - Boolean Whether to offers are under promotions or not. If the value is true then should be selected under promotions only otherwise selected all. Default = false
Example
{"promotedProcedures": true}

OrderBy

Description

Information representing the portion of the data requested from a larger dataset.

Fields
Input Field Description
field - String The name of the field to sort the result
direction - DirectionsEnum The direction to sort the array: ASC or DESC
Example
{"field": "xyz789", "direction": "ASC"}

Pagination

Description

Information representing the portion of the data requested from a larger dataset.

Fields
Input Field Description
offset - Int How many items into the dataset that are requested. Defaults to 0. Default = 0
limit - Int Maximum items to be returned. Defaults to 50. Default = 50
Example
{"offset": 987, "limit": 987}

Patient

Description

Information representing a specific patient.

Fields
Field Name Description
id - Int! MDsave's unique identifier for this patient
email - String Format: xxx@xxx.xxx
firstName - String!
lastName - String!
dateOfBirth - ShortDate! Date format required: YYYY-mm-dd, e.g. 1988-12-22
phoneNumber - PhoneNumber Format: 10 digit number without spaces or special characters
address - Address Address information for this patient
insurance - Insurance Insurance information for this patient
Example
{
  "id": 123,
  "email": "xyz789",
  "firstName": "abc123",
  "lastName": "xyz789",
  "dateOfBirth": ShortDate,
  "phoneNumber": "+17895551234",
  "address": Address,
  "insurance": Insurance
}

PatientInput

Fields
Input Field Description
id - Int MDsave ID of the patient, for use in creating carts for existing MDsave patients. If this field is provided, other fields will be ignored
email - String The patient’s email address
firstName - String The patient’s first name
lastName - String The patients last name
dateOfBirth - ShortDate The patient’s date of birth
phoneNumber - PhoneNumber The patient’s phone number
address - AddressInput
insurance - InsuranceInput
Example
{
  "id": 987,
  "email": "abc123",
  "firstName": "abc123",
  "lastName": "abc123",
  "dateOfBirth": ShortDate,
  "phoneNumber": "+17895551234",
  "address": AddressInput,
  "insurance": InsuranceInput
}

PaymentMethods

Description

Method of payment that was used to complete a checkout. The values in the returned payload will be masked except for the last 4 digits of the credit card number.

Fields
Field Name Description
creditCards - [CreditCard!]
Example
{"creditCards": [CreditCard]}

PaymentMethodsInput

Description

Input values used to determine the method of payment for completing a checkout. There are two methods available for completing a checkout: 1.) Credit Card transaction - The credit card payload should be an array of credit card details in plain text. 2.) Invoicing - set the boolean value to true to use invoicing to complete the checkout.

Fields
Input Field Description
creditCards - [CreditCardInput!]
invoicing - Boolean
Example
{"creditCards": [CreditCardInput], "invoicing": true}

PhoneNumber

Description

PhoneNumber custom scalar type

Example
"+17895551234"

PlaceOfServiceEnum

Values
Enum Value Description

Facility

NonFacility

Inpatient

ASC

VirtualHealth

Example
"Facility"

Procedure

Description

Information about a specific medical procedure and includes the unique identifier and a URL directly to the page on MDsave.

Fields
Field Name Description
id - Int! Unique MDsave identifier for this specific procedure
name - String! Common name of the procedure
url - String! Link to MDsave.com with more information about the procedure
nationalAverage - Float The average price of this procedure across all providers nationwide
cptCodes - [CptCode!] List of cpt codes of procedures
createdTime - Date!
lastUpdatedTime - Date!
Example
{
  "id": 987,
  "name": "xyz789",
  "url": "xyz789",
  "nationalAverage": 987.65,
  "cptCodes": [CptCode],
  "createdTime": "2007-12-03",
  "lastUpdatedTime": "2007-12-03"
}

ProcedureCodesInput

Description

Values that can be used to search for procedures.

Fields
Input Field Description
offerIds - [Int!] List of MDsave's unique identifiers for offers
encodedOfferIds - [String!] List of MDsave's unique encoded identifiers for offers
procedureIds - [Int!] List of MDsave's unique identifiers for procedures that can be obtained through the searchProcedures query.
offerUrls - [String!] List of urls to offers that procedures are included in.
cptCodes - [CptCode!] List of cpt codes of procedures. Not currently supported for searchOffers.
mnemonicCodes - [String!] List of mnemonic codes of procedures. Not currently supported for searchProcedures.
Example
{
  "offerIds": [123],
  "encodedOfferIds": ["abc123"],
  "procedureIds": [123],
  "offerUrls": ["xyz789"],
  "cptCodes": [CptCode],
  "mnemonicCodes": ["xyz789"]
}

ProcedureFee

Fields
Field Name Description
feeType - FeeEnum!
fee - Float!
discount - Float
Example
{"feeType": "Facility", "fee": 987.65, "discount": 123.45}

Provider

Description

A healthcare provider that belongs to a specific hospital and has a unique NPI number. Contains information about the provider, including specialty, hours, and rating. If isOrganization is true, then this object represents an organization (i.e. a practice or clinic), otherwise it is a person.

Fields
Field Name Description
id - Int!
prefix - String
suffix - String
firstName - String
lastName - String
fullName - String!
orderType - String!
emailAddress - String!
isOrganization - Boolean! True if Provider is not a specific person.
providerName - String!
specialty - String!
npi - String Unique 10 digit number.
faxNumber - PhoneNumber Fax Number
hospital - Hospital! The hospital entity that this provider belongs to.
imageUrl - String! Link to a brand logo for the provider
hours - [Hours!] Hours that this provider is generally available
providerUrl - String!
createdTime - Date!
lastUpdatedTime - Date!
addresses - [Address!]!
ratingCount - Int!
ratingAverage - Float!
isPublic - Boolean
canonicalUrl - String
licensedStates - [State!]!
Example
{
  "id": 987,
  "prefix": "abc123",
  "suffix": "xyz789",
  "firstName": "xyz789",
  "lastName": "xyz789",
  "fullName": "xyz789",
  "orderType": "abc123",
  "emailAddress": "abc123",
  "isOrganization": false,
  "providerName": "xyz789",
  "specialty": "xyz789",
  "npi": "xyz789",
  "faxNumber": "+17895551234",
  "hospital": Hospital,
  "imageUrl": "xyz789",
  "hours": [Hours],
  "providerUrl": "abc123",
  "createdTime": "2007-12-03",
  "lastUpdatedTime": "2007-12-03",
  "addresses": [Address],
  "ratingCount": 123,
  "ratingAverage": 987.65,
  "isPublic": true,
  "canonicalUrl": "abc123",
  "licensedStates": [State]
}

ProviderInput

Description

A specific provider's representation in MDsave. Includes an MDsave unique identifier as well as the unique NPI number.

Fields
Input Field Description
id - Int MDsave's unique identifier
name - String The provider's name
npi - String 10 digit unique NPI number representing the provider
Example
{
  "id": 987,
  "name": "abc123",
  "npi": "abc123"
}

ProviderMatchTypeEnum

Description

Shopping cart provider match types can be one of the following strings

Values
Enum Value Description

Exact

An exact match, where one provider was selected.

Ambiguous

An ambiguous match, where multiple providers were selected.
Example
"Exact"

RemoveShoppingCartItemsInput

Description

The input payload needed to remove items from an existing Shopping Cart.

Fields
Input Field Description
shoppingCartId - String! Id of shopping cart to remove offers from.
offerIds - [Int!] List of offer ids to remove from the shopping cart.
Example
{
  "shoppingCartId": "abc123",
  "offerIds": [987]
}

ResponseInterface

Example
{
  "messages": [Message],
  "requestId": "abc123"
}

SearchInsuranceProvidersInput

Description

The input represents the fields in Insurance ProvidersInput that can be searched by

Fields
Input Field Description
hospitalInputs - [HospitalInput]! List of particular hospitals that contains information about the unique id, npi and name
name - String It is name of InsuranceProvider
Example
{
  "hospitalInputs": [HospitalInput],
  "name": "abc123"
}

SearchInsuranceProvidersResponse

Description

This will return the list of insurance providers that are accepted at a particular hospital and a list of messages with more details about the response if relevant.

Fields
Field Name Description
insuranceProviders - [InsuranceProvider!]
messages - [Message!]
requestId - String!
Example
{
  "insuranceProviders": [InsuranceProvider],
  "messages": [Message],
  "requestId": "abc123"
}

SearchLocationInput

Description

Input for searching for location. Text can be city, city/state, zip code, etc...

Fields
Input Field Description
text - String!
Example
{"text": "xyz789"}

SearchLocationResponse

Description

Contains data returned from a location search. The items returned will be Location types which include city, state, and zipCode information.

Fields
Field Name Description
items - [Location!]
messages - [Message!]
requestId - String!
Example
{
  "items": [Location],
  "messages": [Message],
  "requestId": "xyz789"
}

SearchOffersInput

Description

Represents the fields in Offers that can be searched by.

Fields
Input Field Description
hospitalInput - HospitalInput
location - LocationInput
procedureCodes - ProcedureCodesInput
offerInput - OfferInput
providerInput - ProviderInput
Example
{
  "hospitalInput": HospitalInput,
  "location": LocationInput,
  "procedureCodes": ProcedureCodesInput,
  "offerInput": OfferInput,
  "providerInput": ProviderInput
}

SearchOffersItem

Description

Wrapper item for results of an offer search. Includes the Offer and the distance the provider is from the search location.

Fields
Field Name Description
offer - Offer!
distance - Float
Example
{"offer": Offer, "distance": 987.65}

SearchOffersResponse

Description

Contains a List of offers returned from a procedure search query. This will return a list of offers and a list of messages with more details about the response if relevant.

Fields
Field Name Description
items - [SearchOffersItem!] Search results
messages - [Message!]
requestId - String!
Example
{
  "items": [SearchOffersItem],
  "messages": [Message],
  "requestId": "xyz789"
}

SearchProceduresInput

Description

Values that a procedure can be searched by.

Fields
Input Field Description
name - String Partial matching case-insensitive string matching the procedure name.
procedureCodes - ProcedureCodesInput Values that can be used to search for procedures.
Example
{
  "name": "abc123",
  "procedureCodes": ProcedureCodesInput
}

SearchProceduresResponse

Description

Contains a List of procedures returned from an offer search query. This will return a list of matching procedures and a list of messages with more details about the response if relevant.

Fields
Field Name Description
procedures - [Procedure!]
messages - [Message!]
requestId - String!
Example
{
  "procedures": [Procedure],
  "messages": [Message],
  "requestId": "xyz789"
}

SearchVouchersInput

Fields
Input Field Description
status - VoucherStatusEnum
purchasedDate - DateRange
voucherNumbers - [String!]
Example
{
  "status": "Available",
  "purchasedDate": DateRange,
  "voucherNumbers": ["xyz789"]
}

SearchVouchersResponse

Fields
Field Name Description
items - [Voucher!]
messages - [Message!]
requestId - String!
Example
{
  "items": [Voucher],
  "messages": [Message],
  "requestId": "xyz789"
}

ShoppingCart

Fields
Field Name Description
id - String! Unique identifier that can be used to retrieve the ShoppingCart from the MDsave API after it has been created
url - String! Link to the ShoppingCart that can be sent to the patient and accessed externally
patient - Patient!
items - [ShoppingCartItem!]!
totalPrice - Float! The total price for all procedures included in the Offer
notifications - [Notification!]
procedureMatchType - ShoppingCartMatchTypeEnum Match type is only returned for carts created using CPT codes. In other cases it returns null.
status - ShoppingCartStatusEnum
providerMatchType - ProviderMatchTypeEnum
purchasedTime - Date Time at which the cart was purchased. If the cart has not been purchased, it returns null.
planOfCareIdentifier - String Id for patient's plan of care.
Example
{
  "id": "xyz789",
  "url": "xyz789",
  "patient": Patient,
  "items": [ShoppingCartItem],
  "totalPrice": 987.65,
  "notifications": [Notification],
  "procedureMatchType": "Exact",
  "status": "Active",
  "providerMatchType": "Exact",
  "purchasedTime": "2007-12-03",
  "planOfCareIdentifier": "abc123"
}

ShoppingCartItem

Fields
Field Name Description
offer - Offer!
quantity - Int!
price - Float! Total price for the procedure after any discounts. The discounts include any promotional discounts (see Offer.promotionalDiscount) and/or mppr discounts (see MPPRDiscount) where applicable.
MPPRDiscount - Float MPPR discount is the reduction of price for procedures when one patient receives multiple services eligible for an MPPR discounts on a single day. MPPR discounts align MDsave pricing with CMS Multiple Procedure Payment Reduction for services administered to the same patient on a single day. Please note that not all procedures are eligible for an MPPR discount.
Example
{
  "offer": Offer,
  "quantity": 123,
  "price": 987.65,
  "MPPRDiscount": 123.45
}

ShoppingCartMatchTypeEnum

Description

Shopping cart match types can be one of the following strings

Values
Enum Value Description

Exact

Exact match: All CPTs are covered by one procedure

Ambiguous

Ambiguous: Some CPTs could be in more than one different procedure

Missing

Missing procedures: Not all CPTs end up in a procedure
Example
"Exact"

ShoppingCartResponse

Description

A Shopping Cart represents an a prebuilt package that is customized for a specific patient with an offer and total price. Each Shopping Cart has a static URL that a patient can visit and complete the checkout process. Once a Shopping Cart has been created, it can be retrieved through the API using the id returned here.

Fields
Field Name Description
shoppingCart - ShoppingCart
messages - [Message!]
requestId - String!
Example
{
  "shoppingCart": ShoppingCart,
  "messages": [Message],
  "requestId": "xyz789"
}

ShoppingCartStatusEnum

Description

Shopping cart status can be one of the following strings

Values
Enum Value Description

Active

The shopping cart has been created. Items can be added or removed from the cart.

Expired

The shopping cart has been expired. The cart can no longer be modified.

Purchased

The shopping cart has been purchased.

Deleted

The shopping cart has been deleted. The cart can no longer be modified.
Example
"Active"

ShortDate

Description

ShortDate custom scalar type

Example
ShortDate

State

Description

State custom scalar type

Example
State

String

Description

The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

Example
"abc123"

ValidateKeyResponse

Fields
Field Name Description
isSuccess - Boolean
messages - [Message!]
requestId - String!
Example
{
  "isSuccess": false,
  "messages": [Message],
  "requestId": "xyz789"
}

Voucher

Fields
Field Name Description
id - Int!
offer - Offer!
voucherNumber - String!
status - VoucherStatusEnum!
patient - Patient!
purchasedBy - String!
purchasedDate - ShortDate!
serviceDate - ShortDate
price - Float!
reason - String
icdCode - String
comment - String
expirationDate - ShortDate Expiration date for the purchased voucher. Funds from expired vouchers will be refunded back to the purchaser or credited to the purchaser's account.
MPPRDiscount - Float See ShoppingCartItem.MPPRDiscount
voucherPdfUrl - String! The URL to download a PDF of the voucher. The URL will expire 15 minutes after the request.
Example
{
  "id": 987,
  "offer": Offer,
  "voucherNumber": "abc123",
  "status": "Available",
  "patient": Patient,
  "purchasedBy": "abc123",
  "purchasedDate": ShortDate,
  "serviceDate": ShortDate,
  "price": 123.45,
  "reason": "xyz789",
  "icdCode": "xyz789",
  "comment": "abc123",
  "expirationDate": ShortDate,
  "MPPRDiscount": 123.45,
  "voucherPdfUrl": "abc123"
}

VoucherStatusEnum

Values
Enum Value Description

Available

Used

Cancelled

Example
"Available"

WeekDaysEnum

Values
Enum Value Description

Sunday

Monday

Tuesday

Wednesday

Thursday

Friday

Saturday

Example
"Sunday"

ZipCode

Description

ZipCode custom scalar type

Example
ZipCode