Node SDK for Blue Button 2.0 API
The Node software development kit (SDK) provides tools and resources for developers integrating with the CMS Blue Button 2.0 (BB2.0) API.
Table of contents
Prerequisites
You'll need a sandbox account and sample access token to access data from the Blue Button 2.0 API.
To learn how to create a sandbox account and generate a sample access token, see Try the API.
Installation
npm
npm install cms-bluebutton-sdk
npm with TypeScript
npm install --save-dev @types/cms-bluebutton-sdk
Yarn
yarn add cms-bluebutton-sdk
Yarn with TypeScript
yarn add --dev @types/cms-bluebutton-sdk
Configuration Parameters
Required SDK configuration parameters include:
Parameter | Value | Default | Description |
---|
environment | SANDBOX or PRODUCTION | SANDBOX | Blue Button 2.0 API environment |
version | 1 or 2 | 2 | Blue Button 2.0 version |
clientId | your_client_id | | OAuth2.0 client ID of the app |
clientSecret | your_client_secret | | OAuth2.0 client secret of the app |
callbackUrl | https://www.example.com/callback | | OAuth2.0 callback URL of the app |
Access Token Refresh on Expire - tokenRefreshOnExpire
SDK FHIR requests check whether the access token is expired before the data endpoint call. By default, an expired token will refresh. To disable token refresh, set tokenRefreshOnExpire
to false
.
Note: If an application’s authorization for accessing user data has expired, the corresponding access token will not be able to be refreshed; see here for more details.
FHIR Requests Retry Settings - retrySettings
Retry is enabled by default for FHIR requests. The folllowing parameters are available for exponential back off retry algorithm.
Retry parameter | Value (default) | Description |
---|
backoffFactor | 5 | Backoff factor in seconds |
total | 3 | Max retries |
statusForcelist | [500 , 502 , 503 , 504 ] | Error response codes to retry on |
The exponential backoff factor (in seconds) is used to calculate interval between retries using the formula backoffFactor * (2 ** (i - 1))
where i
starts from 0.
Example: A backoffFactor
of 5 seconds generates the wait intervals: 2.5, 5, 10, ...
To disable the retry, set total = 0
.
Configuration Methods
There are two ways to configure the SDK when instantiating a BlueButton
class instance:
JSON object literal
- Configuration
key:value
pairs can be used. - Configuration values can be provided from your own application's configuration method.
Example:
const bb = BlueButton({
"environment": "PRODUCTION",
"clientId": "foo",
"clientSecret": "bar",
"callbackUrl": "https://www.fake.com/callback",
"version": 2,
"retrySettings": {
"total": 3,
"backoffFactor": 5,
"statusForcelist": [500, 502, 503, 504]
}
}
JSON config file
The configuration is in JSON format and stored in a local file. The default location is the current working directory with file name: .bluebutton-config.json
By default, tokenRefreshOnExpire
is true.
Example code:
const bb = BlueButton("settings/my_bb2_sdk_conf.json");
Example JSON in file:
{
"environment": "SANDBOX",
"clientId": "foo",
"clientSecret": "bar",
"callbackUrl": "https://www.fake.com/callback",
"version": 2,
"retrySettings": {
"total": 3,
"backoffFactor": 5,
"statusForcelist": [500, 502, 503, 504]
}
}
Environments and Data
The Blue Button 2.0 API is available in V1 and V2 in a sandbox and production environment.
Version data formats:
Sample configuration JSON with default version and environment:
{
"clientId": "your_client_id",
"clientSecret": "your_client_secret",
"callbackUrl": "https://www.example.com/"
}
If needed, you can set your application's target environment and API version.
Example:
{
"clientId": "your_client_id",
"clientSecret": "your_client_secret",
"callbackUrl": "https://www.example.com/",
"version": "2",
"environment": "PRODUCTION"
}
Usage
The following code shows the SDK used with a Node JS Express server. This code walks through:
- Obtaining an access token with scope chosen by a user
- Passing the token to query for FHIR data
- Using URL links from the response to page through data
- Using the SDK paging support to return all data in one call
import express, { Request, Response } from 'express';
import { BlueButton } from 'cms-bluebutton-sdk';
import { AuthorizationToken } from 'cms-bluebutton-sdk';
const app = express();
const bb = new BlueButton();
const authData = bb.generateAuthData();
let authToken: AuthorizationToken;
app.get('/', (req, res) => {
const redirectUrl = bb.generateAuthorizeUrl(authData);
res.redirect(redirectUrl);
})
app.get('api/bluebutton/callback', async (req: Request, res: Response) => {
let results = {};
try {
authToken = await bb.getAuthorizationToken(authData, req.query.code, req.query.state, req.query.error);
const scopes: string[] = authToken.scope;
if (authToken.scope.index("patient/Patient.read") > -1) {
}
eobResults = await bb.getExplanationOfBenefitData(authToken);
authToken = eobResults.token;
patientResults = await bb.getPatientData(authToken);
authToken = patientResults.token;
coverageResults = await bb.getCoverageData(authToken);
authToken = coverageResults.token;
profileResults = await bb.getProfileData(authToken);
authToken = profileResults.token;
const eobbundle = eobResults.response?.data;
const eobs = await bb.getPages(eobbundle, authToken);
authToken = eobs.token;
const firstPgURL = bb.extractPageNavUrl(eobbundle, "first");
if (firstPgURL) {
const fistPage = await this.getCustomData(firstPgURL, authToken);
authToken = firstPage.token;
const firstBundle = firstPage.response?.data;
}
const lastPgURL = bb.extractPageNavUrl(eobbundle, "last");
if (lastPgURL) {
const lastPage = await this.getCustomData(lastPgURL, authToken);
authToken = lastPage.token;
const lastBundle = lastPage.response?.data;
}
const nextPgURL = bb.extractPageNavUrl(eobbundle, "next");
if (nextPgURL) {
const nextPage = await this.getCustomData(nextPgURL, authToken);
authToken = nextPage.token;
const nextBundle = nextPage.response?.data;
}
const prevPgURL = bb.extractPageNavUrl(eobbundle, "previous");
if (prevPgURL) {
const prevPage = await this.getCustomData(prevPgURL, authToken);
authToken = prevPage.token;
const prevBundle = prevPage.response?.data;
}
const ptbundle = patientResults.response?.data;
const pts = await bb.getPages(ptbundle, authToken);
authToken = pts.token;
const coveragebundle = coverageResults.response?.data;
const coverages = await bb.getPages(coveragebundle, authToken);
authToken = coverages.token;
const pfbundle = profileResults.response?.data;
const pfs = await bb.getPages(pfbundle, authToken);
authToken = pfs.token;
results = {
eob: eobs.pages,
patient: pts.pages,
coverage: coverages.pages,
profile: pfs.pages,
};
} catch (e) {
console.log(e);
}
res.json(results)
});
Sample App
For a complete Node JS sample app, see CMS Blue Button Node JS Sample App.
About the Blue Button 2.0 API
The Blue Button 2.0 API provides Medicare enrollee claims data to applications using the OAuth2.0 authorization flow. We aim to provide a developer-friendly, standards-based API that enables people with Medicare to connect their claims data to the applications, services, and research programs they trust.
License
The CMS Blue Button 2.0 Node SDK is licensed under the Creative Commons Zero v1.0 Universal. For more details, see License.
Security
We do our best to keep our SDKs up to date with vulnerability patching and security testing, but you are responsible for your own review and testing before implementation.
To report vulnerabilities, please see the CMS Vulnerability Disclosure Policy and follow the directions for reporting.
Help and Support
Got questions? Need help troubleshooting? Want to propose a new feature? Contact the Blue Button 2.0 team and connect with the community in our Google Group.