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.
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.
-
Apollo Client (JavaScript)
-
Apollo iOS (Swift / Objective-C)
-
Strawberry Shake (C# / .NET)
-
GQL (Python 3+)
-
genqlient (Go)
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.
-
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.
-
Set the
Authorization
andpayload
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 aprocedureId
inprocedureCodes
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"
- use the
-
procedureCodes
(ProcedureCodesInput)- in
offerIds
add the Offerid
:335067
- in
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
Response
Returns a SearchInsuranceProvidersResponse!
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
Example
{
"street": "abc123",
"city": "abc123",
"state": State,
"zipCode": ZipCode,
"latitude": 987.65,
"longitude": 987.65
}
AddressInput
Boolean
Description
The Boolean
scalar type represents true
or false
.
CacheControlScope
Values
Enum Value | Description |
---|---|
|
|
|
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 |
---|---|
|
|
|
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
Example
{"publicUserId": 123, "portalId": 123, "ssoId": 987}
EncryptionKeyDetailsInput
EncryptionKeyDetailsInterface
Possible Types
EncryptionKeyDetailsInterface Types |
---|
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 |
---|
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 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
Example
{
"id": 987,
"name": "abc123",
"npi": "abc123"
}
HospitalInput
Hours
Fields
Field Name | Description |
---|---|
weekDay - WeekDaysEnum!
|
|
closed - Boolean!
|
|
workStart - String
|
|
workEnd - String
|
Example
{
"weekDay": "Sunday",
"closed": true,
"workStart": "abc123",
"workEnd": "xyz789"
}
Insurance
InsuranceInput
Description
The input payload needed store insurance information
Example
{
"groupId": "abc123",
"memberId": "xyz789",
"plan": "xyz789"
}
InsuranceProvider
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
LocationInput
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 |
---|---|
|
|
|
|
|
|
|
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 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
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.
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 |
---|---|
|
|
|
|
|
|
|
|
|
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
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.
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 |
---|---|
|
An exact match, where one provider was selected. |
|
An ambiguous match, where multiple providers were selected. |
Example
"Exact"
RemoveShoppingCartItemsInput
Description
The input payload needed to remove items from an existing Shopping Cart.
Example
{
"shoppingCartId": "abc123",
"offerIds": [987]
}
ResponseInterface
Fields
Field Name | Description |
---|---|
messages - [Message!]
|
|
requestId - String!
|
Possible Types
ResponseInterface Types |
---|
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
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 match: All CPTs are covered by one procedure |
|
Ambiguous: Some CPTs could be in more than one different procedure |
|
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 |
---|---|
|
The shopping cart has been created. Items can be added or removed from the cart. |
|
The shopping cart has been expired. The cart can no longer be modified. |
|
The shopping cart has been purchased. |
|
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 |
---|---|
|
|
|
|
|
Example
"Available"
WeekDaysEnum
Values
Enum Value | Description |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
Example
"Sunday"
ZipCode
Description
ZipCode custom scalar type
Example
ZipCode