Exchange Payer-to-Payer Member Data (PDex)

Match a member against their prior health plan, then export that member's payer-to-payer clinical and claims data with Sandbox endpoints, view request/response shapes, and error handling expectations.

When a member switches health plans, CMS-0057-F requires the new plan to be able to pull that member's clinical and claims history from their prior plan. This guide covers b.well's implementation of that payer-to-payer exchange: your health plan calls b.well's CMS Network to match the member against their old plan, then export that member's data from it.

Two steps, each an async submit-then-poll pair:

StepWhat you doEndpoint
1Submit a member match, then poll for the matched GroupPOST .../fhir/r4/Group/$bulk-member-matchGET .../fhir/r4/Group/$bulk-member-match/{job_id}
2Submit a data export for that Group, then poll for the manifestPOST .../fhir/r4/Group/{group_id}/$davinci-data-exportGET .../fhir/r4/Group/{group_id}/$davinci-data-export
❗️

Step 1 is not optional

Step 2's {group_id} must come from a Group a prior member match returned. b.well rejects an export request against a Group id it didn't just hand you.



Before you begin

b.well issues these to your organization during onboarding:

  • OAuth client id and client secret, per environment
  • Your organization's scope for PDex payer-to-payer access
👍

Begin in Sandbox

Examples below use the Sandbox base URL directly. Substitute your own client id, client secret, and access token — all example data is fictional.

Base URL

EnvironmentBase URL
Sandboxhttps://partner-api.client-sandbox.icanbwell.com

b.well provides two environments for API access: Sandbox (non-production) and Production. Each environment has dedicated endpoints for both GraphQL and REST APIs

Production Environment

Provided during onboarding


Authenticate

curl --request POST \
  --url https://auth.partner-api.client-sandbox.icanbwell.com/oauth2/v1/apps/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=<your_client_id> \
  --data client_secret=<your_client_secret> \
  --data resource=https://partner-api.client-sandbox.icanbwell.com

Response — 200:

{
  "access_token": "{jwt}",
  "token_type": "Bearer",
  "expires_in": 3600
}

Use access_token as Authorization: Bearer {access_token} on every call below. Tokens last 3600 seconds; re-authenticate on a 401 rather than caching one for the life of a batch job.


Step 1 — Submit a member match

curl -X POST 'https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/$bulk-member-match' \
  -H "Authorization: Bearer <access_token>" \
  -H "Prefer: respond-async" \
  -H "Content-Type: application/json" \
  -d '@member-match.json'

Request body — a FHIR Parameters resource per the Da Vinci PDex multi-member-match profile:

{
  "resourceType": "Parameters",
  "id": "91c52548-8845-42d8-9473-70e1b7cb6c1d",
  "meta": {
    "profile": ["http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-parameters-multi-member-match-bundle-in"]
  },
  "parameter": [{
    "name": "MemberBundle",
    "part": [
      {
        "name": "MemberPatient",
        "resource": {
          "resourceType": "Patient",
          "id": "patient-1",
          "identifier": [{
            "type": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MB"}]},
            "system": "http://example.org/old-payer/identifiers/member",
            "value": "55678",
            "assigner": {"display": "Old Payer"}
          }],
          "name": [{"use": "official", "family": "Person", "given": ["Patricia", "Ann"]}],
          "gender": "female",
          "birthDate": "1974-12-25"
        }
      },
      {
        "name": "CoverageToMatch",
        "resource": {
          "resourceType": "Coverage",
          "id": "coverage-1",
          "status": "draft",
          "subscriberId": "1234564321",
          "beneficiary": {"reference": "Patient/1"},
          "relationship": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/subscriber-relationship", "code": "self"}]},
          "payor": [{"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "9876543210"}, "display": "Old Health Plan"}]
        }
      },
      {
        "name": "Consent",
        "resource": {
          "resourceType": "Consent",
          "id": "consent-1",
          "status": "active",
          "scope": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/consentscope", "code": "patient-privacy"}]},
          "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "IDSCL"}]}],
          "patient": {"reference": "Patient/1"},
          "provision": {
            "type": "permit",
            "action": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/consentaction", "code": "disclose"}]}]
          }
        }
      },
      {
        "name": "CoverageToLink",
        "resource": {
          "resourceType": "Coverage",
          "id": "coverage-link-1",
          "status": "draft",
          "subscriberId": "432156789",
          "beneficiary": {"reference": "Patient/1"},
          "payor": [{"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "0123456789"}, "display": "New Health Plan"}]
        }
      }
    ]
  }]
}

Response — 202 Accepted, empty body:

Content-Location: https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/$bulk-member-match/{job_id}

Errors

StatusWhenBody
401Missing, invalid, or expired bearer tokenOperationOutcome, issue code security
403Token or caller isn't scoped for PDexOperationOutcome, issue code forbidden
5XXb.well-side issueOperationOutcome, issue code transient — retry after a delay

Step 2 — Poll the member match

curl 'https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/$bulk-member-match/{job_id}' \
  -H "Authorization: Bearer <access_token>"

{job_id} comes from Step 1's Content-Location header.

Response — 200. Body shape follows the $multi-member-match payer example response in the Da Vinci PDex v2.1.0 spec.

Capture the Group id

The matched Group.id in this response is what Step 3 needs as {group_id}.

Errors: same 401 / 403 shapes as Step 1.


Step 3 — Submit a data export

curl -X POST 'https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/{group_id}/$davinci-data-export?exportType=hl7.fhir.us.davinci-pdex%23payertopayer' \
  -H "Authorization: Bearer <access_token>" \
  -H "Prefer: respond-async"

{group_id} must be a Group id returned by Step 2 — b.well rejects export requests against any other Group id.

exportType is required and must equal exactly hl7.fhir.us.davinci-pdex#payertopayer, URL-encoded as %23 for #. Any other value fails validation.

Optional query params _since, _until, _typeFilter, and _type are accepted and persisted, not yet format-validated.

No request body.

Response — 202 Accepted, empty body:

Content-Location: https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/{group_id}/$davinci-data-export?exportType=hl7.fhir.us.davinci-pdex%23payertopayer
📘

Content-Location works differently here

Unlike Steps 1–2, this is the literal request URL — including your query string — echoed back, not a separate job-id path.

Errors

StatusWhen
401Missing, invalid, or expired bearer token
403Caller isn't PDex-enabled
404{group_id} doesn't resolve to a real Group
503b.well-side issue — retry after a delay

Step 4 — Poll and retrieve the data export

curl 'https://partner-api.client-sandbox.icanbwell.com/fhir/r4/Group/{group_id}/$davinci-data-export' \
  -H "Authorization: Bearer <access_token>"

Response — 200:

{
  "transactionTime": "2027-01-04T18:22:11.000Z",
  "request": "/Group/{group_id}/$davinci-data-export",
  "requiresAccessToken": false,
  "output": [
    { "type": "Claim", "url": "https://example.com/claim.ndjson", "count": 20 }
  ],
  "error": []
}

Each entry in output is one resource type's NDJSON file. Fetch each url directly.requiresAccessToken tells you whether that fetch also needs your bearer token.

Errors: 401 / 403 (same scopes as Step 3), 404 if {group_id} doesn't resolve.


Errors

StatusMeaning
401Token missing, invalid, or expired. Re-authenticate and retry.
403Your credentials aren't scoped for PDex payer-to-payer. Contact b.well.
404The {group_id} in your request doesn't resolve to a real Group. Confirm it came from a member match response.
5XX / 503b.well-side issue. Retry after a delay.

Did this page help you?