BCDA User Guide Documentation
For each request and operation, we provide example requests and example cURL commands. We will highlight any common errors or unique attributes of our API. Lastly, we provide an example response from the API.
This documentation is for the production environment (api.bcda.cms.gov). To access this API, your organization must obtain production credentials and add its IP address. If you do not have credentials, you can access synthetic data using the sandbox environment (sandbox.bcda.cms.gov). After adding IP addresses to 4i / ACO-MS, it may take up to an hour for the IPs to be added to the allow list.
Request Metadata
You may want to retrieve metadata to check what version of the API is currently active or to check on the status of the API.
Metadata about the Beneficiary Claims Data API is available as a FHIR CapabilityStatement resource. A token is not required to access this information.
Metadata Examples
Metadata Request
GET /api/v2/metadata
Metadata cURL Command
curl https://api.bcda.cms.gov/api/v2/metadata
Metadata Response Example
{
"resourceType": "CapabilityStatement",
"status": "active",
"date": "2020-10-15",
"publisher": "Centers for Medicare & Medicaid Services",
"kind": "instance",
"instantiates": [
"https://prod-sbx.bfd.cms.gov/baseDstu3/metadata/",
"http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data"
],
"software": {
"name": "Beneficiary Claims Data API",
"version": "r79",
"releaseDate": "2020-10-15"
},
"implementation": {
"description": "The Beneficiary Claims Data API (BCDA) enables Accountable Care Organizations (ACOs) participating in the Shared Savings Program to retrieve Medicare Part A, Part B, and Part D claims data for their prospectively assigned or assignable beneficiaries.",
"url": "https://sandbox.bcda.cms.gov"
},
"fhirVersion": "3.0.1",
"acceptUnknown": "extensions",
"format": [
"application/json",
"application/fhir+json"
],
"rest": [
{
"mode": "server",
"security": {
"extension": [
{
"extension": [
{
"url": "token",
"valueUri": "https://sandbox.bcda.cms.gov/auth/token"
}
],
"url": "http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris"
}
],
"cors": true,
"service": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/restful-security-service",
"code": "OAuth",
"display": "OAuth"
}
],
"text": "OAuth"
}
]
},
"interaction": [
{
"code": "batch"
},
{
"code": "search-system"
}
],
"operation": [
{
"name": "patient-export",
"definition": {
"reference": "http://hl7.org/fhir/uv/bulkdata/OperationDefinition/patient-export"
}
},
{
"name": "group-export",
"definition": {
"reference": "http://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export"
}
}
]
}
]
}
Metadata Explanation
This operation will return data about the API in an NDJSON format. You may view the release version and the FHIR version of the BCDA API that is currently active and other useful information.
Requesting Data
To obtain all the available data (as far back as 2014) for all of your beneficiaries, you can make a request to either the /Patient or /Group endpoint. You may want to do this as a first call, as a way to check for BCDA files against CCLF files, or to create a database.
BCDA data will be updated weekly, so you will be able to make requests and expect to retrieve new data on a weekly basis.
List of Requests
You can make a few different unfiltered requests for data:
- Request all three Resource Types at once
- Request any two Resource Types
- Request a single Resource Type
Steps
Each request will follow the same four step process:
- Obtain an access token
- Start a job to acquire data
- Check the job status
- Download the data
Request All Three Resource Types
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Start a job to acquire data
Requests to start a job
GET /api/v2/Group/all/$export
GET /api/v2/Group/all/$export?_type=ExplanationOfBenefit,Patient
GET /api/v2/Group/all/$export?_type=Patient
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
Prefer: respond-async
cURL Commands to start a job
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/all/\$export" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/all/\$export?_type=ExplanationOfBenefit,Patient" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/all/\$export?_type=Patient" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
Response Example: Successful Request
202 Accepted
Response Example: Too Many Requests
429 Too Many Requests
Response Headers
Content-Location: https://api.bcda.cms.gov/api/v2/jobs/{job_id}
Start a Job Explanation
This operation will start a data export job. We have provided three example requests and three example cURL statements to start a job for:
- All three resource types
- Any two resource types (we use EOB and Patient as an example)
- Any single resource type (we use Patient as an example)
For all three resource types, a GET request is made to the /Patient endpoint without the _type query parameter. For one or two resource types, the desired resources are set in the _type query parameter. Notice that, for multiple resource types, they must be separated by commas.
Your access token is required and set as a header. Accept and Prefer headers are also required. The dollar sign ('$') before the word "export" in the URL indicates that the endpoint is an action rather than a resource. The format is defined by the FHIR Bulk Data Export spec.
If the request was successful, a 202 Accepted response code will be returned and the response will include a Content-Location header. The value of this header indicates the location to check for job status and outcome. In the example header below, the number 42 in the URL represents the ID of the export job.
If you're already requesting data from one endpoint and try to request data from that endpoint again while the first request is processing, you'll receive a 429 Too Many Requests error.
Step 3: Check the job status
Request to check the job status
GET https://api.bcda.cms.gov/api/v2/jobs/{job_id}
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
cURL Command to check the job status
curl -X GET "https://api.bcda.cms.gov/api/v2/jobs/{job_id}" \
-H "accept: application/fhir+json" \
-H "Authorization: Bearer {access_token}"
Response Example: Completed Job
{
"transactionTime": "2019-12-09T20:44:01.705398Z",
"request": "https://api.bcda.cms.gov/api/v2/Group/all/$export",
"requiresAccessToken": true,
"output": [
{
"type": "ExplanationOfBenefit",
"url": "{output_url}"
},
{
"type": "Coverage",
"url": "{output_url}"
},
{
"type": "Patient",
"url": "{output_url}"
}
],
"error": [],
"JobID": {job_id}
}
Response Headers: Incomplete Job
X-Progress: In Progress
Check the Job Status Explanation
This operation will check on the status of a job and return its progress if it has not finished. Notice that the GET request is simply the URL found in the Content-Location header. The Content Location header is found from the previous step (starting a job) within the response section.
Within the response, a 202 Accepted indicates that the job is processing. The response headers will include the X-Progress header. The X-Progress header value will include text indicating the job's status in BCDA's workflow and an estimated progress percentage. For example, X-Progress: In Progress, 80%.
The status will change from 202 Accepted to 200 OK when the export job is complete and the data is ready to be downloaded.
Claims data can be found at the URLs within the output field. The number 42 in the data file URLs is the same job ID from the Content-Location header URL in the previous step. If some of the data cannot be exported due to errors, details of the errors can be found at the URLs in the error field. The errors are provided in an NDJSON file as FHIR OperationOutcome resources.
Step 4: Download the data
Request to download the data
GET {output_url}
Request Headers
Authorization: Bearer {access_token}
Accept-Encoding: gzip
cURL Command to download the data
curl -X GET "{output_url}" \
-H "Accept-Encoding: gzip" \
-H "Authorization: Bearer {access_token}" \
--output "your-file-name"
Response Example
Response Headers
Content-Encoding: gzip
Downloading the Data Explanation
This operation will allow you to obtain the exported data. Notice that the request contains the output URL for a job that is complete (200 OK status).
The "Accept-Encoding: gzip" header is optional, but will return a significantly smaller (about 30X smaller) file with a faster download speed. Follow our recommended best practices for speeding up downloads. Note that the file downloaded will be a gzip file which you will need to extract into its ndjson format.
The response will be the requested data as FHIR resources in NDJSON format. Each file related to a different resource type will appear separately and labeled as to which resource type it contains. Examples of data from each Resource Type are available in the guide to working with BCDA data.
Cancelling a Job
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Send a Request to Cancel a Job
Request to Cancel a Job
DELETE /api/v2/jobs/{job_id}
Request Headers
Authorization: Bearer {access_token}
Cancel a Job Explanation
This operation will send a request to cancel any active job. You may want to do this for very long-running jobs or to preserve resources.
If the request is successful, the active job will be terminated and a 202 response will be returned.
Request Jobs History
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Send a Request to the Jobs Endpoint
Requests to retrieve data on all past jobs
GET /api/v2/jobs
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
Prefer: respond-async
cURL Command to check the job status
curl -X GET "https://api.bcda.cms.gov/api/v2/jobs" \
-H "accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {access_token}"
Response Example: Completed Job
{
"entry":[
{
"resource":{
"executionPeriod":{
"end":"2021-08-14T00:07:48+00:00",
"start":"2021-08-13T00:07:48+00:00"
},
"identifier":[
{
"system":"http://bcda.cms.gov/api/v2/jobs",
"use":"official",
"value":"1"
}
],
"input":[
{
"type":{
"text":"BULK FHIR Export"
},
"valueString":"GET https://bcda.test.gov/this-is-a-test"
}
],
"intent":"order",
"resourceType":"Task",
"status":"completed"
}
}
],
"resourceType":"Bundle",
"total":1,
"type":"searchset"
}
Retrieve Historical Data on Past Job Requests Explanation
This operation will return a Bundle of resources containing information about jobs sent by your organization historically. Each resource represents a single job request. Notice that each resource contains a start date/time, an end date/time, a unique identifier, and the original request (contained in valueString).
Your jobs in the BCDA system have nine possible end states: Completed, Archived, Expired, Failed, FailedExpired, In Progress, Pending, Cancelled, and CancelledExpired. Notice that, in the above example, we did not supply any parameters; we’ve made an unfiltered request for all past jobs. To filter by the status of the job, you may supply a ‘status’ parameter. However, the status parameter has only four possible values supported by the FHIR Task resource: Completed, Failed, In Progress, and Cancelled.
The nine possible job states map to the four supported FHIR Task status values as follows:
- Archived, Expired, Completed -> Completed
- FailedExpired, Failed -> Failed
- Pending, In Progress -> In Progress
- CancelledExpired, Cancelled-> Cancelled
For example, if your organization had jobs Archived in the BCDA system, you could make a filtered request for those as follows: GET /api/v2/Jobs?_status=Archived
. You would receive a list of jobs with the status “Completed”. All of these jobs were Archived in the BCDA system. If your organization also had jobs with the end state of Expired or Completed in the BCDA system, they would also hold the status of Completed. But, they would not be returned in your request for Archived jobs.
If your organization has no jobs to return, you will receive a 404 ERROR in your response.
Request Attribution Status
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Send a Request to the Attribution Status Endpoint
Requests to check the last updated date of your attribution data
GET /api/v2/attribution_status
Request Headers
Authorization: Bearer {access_token}
Accept: application/json
cURL Command to retrieve the attribution status
curl -X GET "https://api.bcda.cms.gov/api/v2/attribution_status" \
-H "accept: application/json" \
-H "Authorization: Bearer {access_token}"
Response Example
{
“Ingestion_dates”: [
{
“type”: “last_attribution_update”,
“timestamp”: “2020-12-22 22:31:40.397916+00”
},
{
“type”: “last_runout_update”,
“timestamp”: “2020-12-22 22:31:40.397916+00”
}
]
}
Check the Last Updated Date of your Attribution Data Explanation
This operation will return a timestamp of the last time your attribution data was updated in the BCDA system. You may want to use this timestamp to check whether to run a new job request. You can do so by comparing it to the last date/time your organization requested data from BCDA.
If BCDA has never ingested an attribution file or a runout file for your organization, you will receive a NOT FOUND 404 response.
Requesting Filtered Data
You may want to obtain filtered data for all of your beneficiaries (or for a subset of your beneficiaries) in order to reduce file size and download time. You may also want to target specific data, such as your runouts data.
To reduce file size, use the _since parameter with either the /Patient or /Group endpoints, but be wary that you understand the difference regarding newly added beneficiaries. You may want to do this as a repeating call or as a way to check for new data.
To obtain claims runout data, use the 'runout' parameter with the /Group endpoint, which returns data for beneficiaries who were attributed to your model entity the previous year but not the current year. These claims will have a service date no later than December 31 of the previous year.
List of Requests
You can make a few different filtered requests for data:
- Request the most recent data for all beneficiaries: Use _since within the /Patient endpoint
- Request the most recent data for all beneficiaries AND historical data for newly added beneficiaries: Use _since within the /Group endpoint
- Request runouts data: Use 'runout' within the /Group endpoint
Steps
Each request will follow the same four step process as an unfiltered request:
- Obtain an access token
- Start a job to acquire data (you will input the _since parameter here)
- Check the job status
- Download the data
The only difference appears in the request of Step 2: Start a job to acquire data. We show examples of this step below.
When using _since, format dates and times by the FHIR standard
Dates and times submitted in _since must be listed in the FHIR instant format (YYYY-MM-DDThh:mm:sss+zz:zz).
- Sample Date: February 20, 2020 12:00 PM EST
- instant Format: YYYY-MM-DDThh:mm:sss+zz:zz
- Formatted Sample: 2020-02-20T12:00:00.000-05:00
For more information consult FHIR Datatypes page.
Requesting using _since with the /Patient endpoint
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Start a job
Request to start a job using the _since parameter within the /Patient endpoint
GET /api/v2/Patient/$export?_type=Patient&_since=2020-02-13T08:00:00.000-05:00
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
Prefer: respond-async
cURL Command using the _since parameter within the /Patient endpoint
curl -X GET "https://api.bcda.cms.gov/api/v2/Patient/\$export?_type=Patient&_since=2020-02-13T08:00:00.000-05:00" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {access_token}" \
-i
Response Example: Successful Request
202 Accepted
Response Example: Too Many Requests
429 Too Many Requests
Response Headers
Content-Location: https://api.bcda.cms.gov/api/v2/jobs/{job_id}
Start a Job using _since within the /Patient endpoint Explanation
This operation will start a job for data for all beneficiaries since the selected date: February 13, 2020. Notice that we are seeking data from the /Patient endpoint. This request would behave differently if it was made from the /Group endpoint. In the example, we request the Patient resource type. The steps and format would work similarly for other resource types.
You must provide a _since date in the FHIR format. An access token as well as Accept and Prefer headers are required. The dollar sign ($) before the word "export" in the URL indicates that the endpoint is an action rather than a resource. The format is defined by the FHIR Bulk Data Export spec.
If the request was successful, a 202 Accepted response code will be returned and the response will include a Content-Location header. The value of this header indicates the location to check for job status and outcome. In the example header above, the number 42 in the URL represents the ID of the export job.
Step 3: Check the job status
See Step 3: Check the job status in the Request Data section above.
Step 4: Download the data
See Step 4: Download the data in the Request Data section above.
Requesting using _since with the /Group endpoint
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Start a job
Request to Start a job using the _since parameter within the /Group endpoint
GET /api/v2/Group/all/$export?_type=Patient&_since=2020-02-13T08:00:00.000-05:00
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
Prefer: respond-async
cURL Command using the _since parameter within the /Group endpoint
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/all/\$export?_type=Patient&_since=2020-02-13T08:00:00.000-05:00" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {access_token}" \
-i
Response Example: Successful Request
202 Accepted
Response Example: Too Many Requests
429 Too Many Requests
Response Headers
Content-Location: https://api.bcda.cms.gov/api/v2/jobs/{job_id}
Start a Job using _since within the /Group endpoint Explanation
This operation will start a job for filtered data for existing beneficiaries since 8PM EST on February 13th, 2020 and going as far back as 2014 for historical data for beneficiaries assigned to your organization in the last month. In the example, we request the Patient resource type. The steps and format would work similarly for other resource types.
You must provide the groupID of "all" as well as a _since date in the FHIR format. An access token as well as Accept and Prefer headers are required. The dollar sign ($) before the word "export" in the URL indicates that the endpoint is an action rather than a resource. The format is defined by the FHIR Bulk Data Export spec.
If the request was successful, a 202 Accepted response code will be returned and the response will include a Content-Location header. The value of this header indicates the location to check for job status and outcome. In the example header above, the number 42 in the URL represents the ID of the export job.
Step 3: Check the job status
See Step 3: Check the job status in the Request Data section above.
Step 4: Download the data
See Step 4: Download the data in the Request Data section above.
Request runouts data with /Group and `runout`
Step 1: Obtain an Access Token
See Authentication and Authorization above.
Step 2: Start a job to acquire data
Requests to start a job
GET /api/v2/Group/runout/$export
GET /api/v2/Group/runout/$export?_type=ExplanationOfBenefit,Patient
GET /api/v2/Group/runout/$export?_type=Patient
Request Headers
Authorization: Bearer {access_token}
Accept: application/fhir+json
Prefer: respond-async
cURL Commands to start a job
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/runout/\$export" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/runout/\$export?_type=ExplanationOfBenefit,Patient" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
-
curl -X GET "https://api.bcda.cms.gov/api/v2/Group/runout/\$export?_type=Patient" \ -H "accept: application/fhir+json" \ -H "Prefer: respond-async" \ -H "Authorization: Bearer {access_token}" \ -i
Response Example: Successful Request
202 Accepted
Response Headers
Content-Location: https://api.bcda.cms.gov/api/v2/jobs/{job_id}
Start a Job using 'runout' with /Group Explanation
This operation will start a data export job. We have provided three example requests and three example cURL statements to start a job for:
- All three resource types
- Any two resource types (we use EOB and Patient as an example)
- Any single resource type (we use Patient as an example)
For all of the requests, a GET request is made to the /Group endpoint with the `runout` identifier. To retrieve all three resource types, simply exclude the _type query parameter. For one or two resource types, the desired resources are set in the _type query parameter. Notice that, for multiple resource types, they must be separated by commas.
Your access token is required and set as a header. Accept and Prefer headers are also required. The dollar sign ('$') before the word "export" in the URL indicates that the endpoint is an action rather than a resource. The format is defined by the FHIR Bulk Data Export spec.
If the request was successful, a 202 Accepted response code will be returned and the response will include a Content-Location header. The value of the Content-Location header indicates the location to check for job status and outcome. In the example header above, the number 42 in the URL represents the ID of the export job. The claims returned in the job will be filtered to have a serviceDate of 12/31/2020 or before.
If you're already requesting data from one endpoint and try to request data from that endpoint again while the first request is processing, you'll receive a 429 Too Many Requests error. For guidance on how to handle 429 errors, refer to our best practices.
Step 3: Check the job status
See Step 3: Check the job status in the Request Data section above.
Step 4: Download the data
See Step 4: Download the data in the Request Data section above.
Best Practices
Handling 429 status codes
A status code of 429
indicates “Too Many Requests.” This can occur due to two reasons:
- Making too many HTTP requests within a period of time
- Trying to recreate jobs already marked as "In-Progress.” For reference, you can view both existing and past jobs using the /jobs endpoint. See Request Jobs History for more details.
Regardless of the reason, you will see a Retry-After response in the header. Wait until the period of time specified in the header has passed before making any more requests. This makes sure your client can adapt without manual intervention, even if the rate-limiting parameters change.
Speeding up downloads
Requesting compressed data
Requesting compressed data can help increase your download speed. You can request compressed data files by specifying the `Accept-Encoding: gzip` header in your download requests. Note that the file downloaded will be a gzip file which you will need to extract into its ndjson format.
Sample cURL Command to Download the Data
curl "{output_url}" \
-H "Authorization: Bearer {access_token}" \
-H "Accept-Encoding: gzip" \
--output "your-file-name"
Downloading files concurrently
When multiple files are available, you don't need to wait for one download to complete before starting the next. You may make multiple download requests concurrently.