How to Access Claims Data
Learn how to access claims data for both the sandbox and production environments and use Beneficiary Claims Data API (BCDA) endpoints.
The sandbox and production environments follow similar instructions. They support the same workflow, endpoints, parameters, and resource types.
Sandbox | Production |
---|---|
Available to everyone via test credentials | Must complete the steps for production credentials |
Contains test claims data | Contains real Medicare enrollee data |
sandbox.bcda.cms.gov |
api.bcda.cms.gov |
BCDA recommends using v2 of the API
This is the latest version which follows the FHIR R4 specification. REACH ACOs must use v2 for partially adjudicated claims data.
Instructions
1. Get a bearer token
You will need a bearer token to call the API. The process requires credentials, which are formatted as a client ID and client secret.
Jobs will not be interrupted when the bearer token expires. In progress and queued jobs will continue to run.
2. Start a job
Make a GET
request to the /Group or /Patient endpoint to start a data export job. The examples below are sandbox curl requests to /Group. Follow along in your terminal or using a tool like Postman.
Request all resource types
By default, the GET
request returns all available resource types.
GET /api/v2/Group/all/$export
Use the _type parameter to specify which resource types you’d like returned.
Request header
The header must contain your bearer token. You may receive a 401
response if your credentials are invalid or expired. Bearer
must be included in the header with a capital B and followed by a space.
Authorization: Bearer {bearer_token}
Accept: application/fhir+json
Prefer: respond-async
Example curl commands to start a job
- Combine your
GET
request for resources with the request header. - The dollar sign
$
beforeexport
in the URL indicates the endpoint is an operation, rather than a CRUD interaction. - PowerShell users will need to replace backslash characters
\
with backticks ( ` ) to properly escape the$export
operation.
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/Group/all/\$export" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {bearer_token}" \
-i
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/Group/all/\$export?_type=ExplanationOfBenefit,Patient" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {bearer_token}" \
-i
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/Group/all/\$export?_type=Patient" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {bearer_token}" \
-i
Response example: successful request
A 202 Accepted
response with a Content-Location header indicates a successful request.
Response header example
You’ll need the job ID in the Content-Location header to check your job status.
Content-Location: https://sandbox.bcda.cms.gov/api/v2/jobs/{job_id}
Response example: too many requests
A 429 Too Many Requests
response can occur due to 2 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.
Wait until the period of time specified in the Retry-After: <delay-seconds>
header passes before making any more requests. This makes sure your client can adapt without manual intervention, even if the rate-limiting parameters change.
3. Check job status
Make a GET
request to check the status using the job ID from step 2. You may need another bearer token if it’s been over 20 minutes since it was generated.
Request to check the job status
GET https://sandbox.bcda.cms.gov/api/v2/jobs/{job_id}
Request header
Authorization: Bearer {bearer_token}
Accept: application/fhir+json
curl command to check the job status
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/jobs/{job_id}" \
-H "Accept: application/fhir+json" \
-H "Authorization: Bearer {bearer_token}" \
-i
Response example: incomplete job
A 202
response indicates your job is still processing. The status will change to 200 OK
when the export is complete and the data is ready for download.
202 Accepted
Response header example: incomplete job
The X-Progress will have a percentage indicating your estimated progress.
X-Progress: In Progress, 80%
Response example: completed job
You’ll receive a 200 OK
response with the output URL(s) needed to download the data. In the example URLs below, 42
indicates the job ID.
There is a separate URL for each resource type requested. The following example shows a request for all resource types for adjudicated claims data.
{
"transactionTime": "2019-12-09T20:44:01.705398Z",
"request": "https://sandbox.bcda.cms.gov/api/v2/Group/all/$export",
"requiresAccessToken": true,
"output": [
{
"type": "ExplanationOfBenefit",
"url": "https://sandbox.bcda.cms.gov/data/42/afd22dfa-c239-4063-8882-eb2712f9f638.ndjson"
},
{
"type": "Coverage",
"url": "https://sandbox.bcda.cms.gov/data/42/f76a0b76-48ed-4033-aad9-d3eec37e7e83.ndjson"
},
{
"type": "Patient",
"url": "https://sandbox.bcda.cms.gov/data/42/f92dcf16-63a2-448e-a12a-3bf677f966ed.ndjson"
}
],
"error": [],
"JobID": 42
}
4. Download the data
Make a GET
request to download your data using the URL(s) from step 3.
If you’re downloading from more than 1 URL, make multiple download requests concurrently to save time. Large files may take significantly longer to download.
Request to download the data
GET https://sandbox.bcda.cms.gov/data/{job_id}/{file_name}
Request header: compressed data files
Request compressed data files with the optional Accept-Encoding: gzip
header in your requests for faster download times. Afterward, decompress (unzip) the files into NDJSON format.
Authorization: Bearer {bearer_token}
Accept-Encoding: gzip
curl command to download the data
curl -X GET "https://sandbox.bcda.cms.gov/data/{job_id}/{file_name}" \
-H "Accept-Encoding: gzip" \
-H "Authorization: Bearer {bearer_token}"
If some of the data can’t be exported due to errors, details can be found at the URLs in the error field. The errors are provided in an NDJSON file as FHIR OperationOutcome resources.
Response example
By default, you’ll receive the requested data as FHIR resources in NDJSON format. Each resource type will appear as a separate, labeled file.
Other BCDA endpoints
Cancel a job
Cancel any active job. If the request is successful, you’ll receive a 202
response.
Request to cancel a job
DELETE /api/v2/jobs/{job_id}
Request header
Authorization: Bearer {bearer_token}
curl command to cancel a job
curl -X DELETE "https://sandbox.bcda.cms.gov/api/v2/jobs/{job_id}" \
-H "Accept: application/fhir+json" \
-H "Authorization: Bearer {bearer_token}"
Request job history
Retrieve details on your organization’s historical requests, including the start and end datetime, unique ID, original valueString request, and status.
Request to retrieve all past jobs
If your organization has no jobs to return, you’ll receive a 404 ERROR
response.
GET /api/v2/jobs
Request that filters jobs by end state
Supply the _status parameter to filter for jobs with a specific end state. BCDA jobs have 9 possible end states: Completed, Archived, Expired, Failed, FailedExpired, In Progress, Pending, Cancelled, and CancelledExpired.
These are how the job end states map to the 4 supported values you can receive in the response body:
Archived
,Expired
,Completed
→completed
FailedExpired
,Failed
→failed
Pending
,In Progress
→in-progress
CancelledExpired
,Cancelled
→cancelled
The example below is a filtered request for all past archived jobs. If any are found, the response will list the status as completed
. Even so, the filter will only return archived jobs; it will exclude expired and completed jobs.
GET /api/v2/jobs?_status=Archived
Request header
Authorization: Bearer {bearer_token}
Accept: application/fhir+json
Prefer: respond-async
curl command to check the job status
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/jobs" \
-H "Accept: application/fhir+json" \
-H "Prefer: respond-async" \
-H "Authorization: Bearer {bearer_token}" \
-i
Response example: completed job
The response will contain a bundle of resources for each historical job. Each resource section in the response represents a single past job request.
This example shows 1 historical job with a completed
status. Since this was an unfiltered request, the job could either be archived, expired, or completed.
{
"entry": [
{
"resource": {
"executionPeriod": {
"end": "2021-08-14T00:07:48+00:00",
"start": "2021-08-13T00:07:48+00:00"
},
"identifier": [
{
"system": "https://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"
}
Request attribution status
Check your attribution status for a timestamp of when your attribution data was last updated. By comparing the timestamp to the date of your most recent job, you can determine if your organization has new claims data to download.
Request to check attribution status
GET /api/v2/attribution_status
Request header
Authorization: Bearer {bearer_token}
Accept: application/json
curl command to check attribution status
curl -X GET "https://sandbox.bcda.cms.gov/api/v2/attribution_status" \
-H "Accept: application/json" \
-H "Authorization: Bearer {bearer_token}"
Response example
If BCDA has never ingested an attribution or runout file for your organization, you’ll receive a 404 not found
response.
{
"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 API status
Retrieve metadata to view the current status and release or FHIR version of the API. A bearer token, and therefore a response header, is not required.
Request to check API status
GET /api/v2/metadata
curl command to check API status
curl "https://sandbox.bcda.cms.gov/api/v2/metadata"
Response example
The response will contain a FHIR Capability Statement resource in JSON format. The example below shows the API is active, using FHIR Release 4.0.1, and that the API release version is r231.
{
"date": "2024-09-09T13:35:05+00:00",
"fhirVersion": "4.0.1",
"format": [
"application/json",
"application/fhir+json"
],
"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"
},
"instantiates": [
"https://prod.bfd.cms.gov/v2/fhir/metadata",
"https://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data"
],
"kind": "instance",
"publisher": "Centers for Medicare & Medicaid Services",
"resourceType": "CapabilityStatement",
"rest": [
{
"interaction": [
{
"code": "batch"
},
{
"code": "search-system"
}
],
"mode": "server",
"resource": [
{
"operation": [
{
"definition": "https://hl7.org/fhir/uv/bulkdata/OperationDefinition/patient-export",
"name": "patient-export"
}
],
"type": "Patient"
},
{
"operation": [
{
"definition": "https://hl7.org/fhir/uv/bulkdata/OperationDefinition/group-export",
"name": "group-export"
}
],
"type": "Group"
}
],
"security": {
"cors": true,
"extension": [
{
"extension": [
{
"url": "token",
"valueUri": "https://sandbox.bcda.cms.gov/auth/token"
}
],
"url": "https://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris"
}
],
"service": [
{
"coding": [
{
"code": "OAuth",
"display": "OAuth",
"system": "https://terminology.hl7.org/CodeSystem/restful-security-service"
}
],
"text": "OAuth"
}
]
}
}
],
"software": {
"name": "Beneficiary Claims Data API",
"releaseDate": "2024-09-09T13:35:05+00:00",
"version": "r231"
},
"status": "active"
}