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/$exportUse 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-asyncExample curl commands to start a job
- Combine your
GETrequest for resources with the request header. - The dollar sign
$beforeexportin 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$exportoperation.
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}" \
-icurl -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}" \
-icurl -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}" \
-iResponse 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+jsoncurl 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}" \
-iResponse 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 AcceptedResponse 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: gzipcurl 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/jobsRequest 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→completedFailedExpired,Failed→failedPending,In Progress→in-progressCancelledExpired,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=ArchivedRequest header
Authorization: Bearer {bearer_token}
Accept: application/fhir+json
Prefer: respond-asynccurl 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}" \
-iResponse 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_statusRequest header
Authorization: Bearer {bearer_token}
Accept: application/jsoncurl 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/metadatacurl 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"
}