Payerbox Docs

$bulk-member-match

Matches a batch of member bundles submitted by a requesting payer against the responding payer's Patients and produces up to three Group resources, defined by the Da Vinci PDex IG v2.2.0. The MatchedMembers Group id is the input to $davinci-data-export with exportType = hl7.fhir.us.davinci-pdex#payertopayer for the Payer-to-Payer bulk export.

The operation is always asynchronous and follows the FHIR Bulk Data kick-off pattern: kick-off returns 202 Accepted with Content-Location, the client polls the status URL, and downloads the result as a single-line ndjson Parameters resource.

Test dataset

Request and Response examples on this page reference this dataset. Load it first to reproduce them.

Load from the Aidbox REST Console — the bundle goes through the normal FHIR write path so AccessPolicies and Clients become active immediately:

Click to view test dataset bundle JSON
POST /fhir
Content-Type: application/fhir+json

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "request": {"method": "PUT", "url": "/Client/test-payer-client"},
      "resource": {
        "resourceType": "Client",
        "id": "test-payer-client",
        "secret": "test-payer-secret",
        "grant_types": ["basic"],
        "details": {"identifier": [{"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"}]}
      }
    },
    {
      "request": {"method": "PUT", "url": "/Client/test-provider-client"},
      "resource": {
        "resourceType": "Client",
        "id": "test-provider-client",
        "secret": "test-provider-secret",
        "grant_types": ["basic"],
        "details": {"identifier": [{"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}]}
      }
    },
    {
      "request": {"method": "PUT", "url": "/AccessPolicy/allow-test-payer-client"},
      "resource": {
        "resourceType": "AccessPolicy",
        "id": "allow-test-payer-client",
        "engine": "allow",
        "link": [{"resourceType": "Client", "id": "test-payer-client"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/AccessPolicy/allow-test-provider-client"},
      "resource": {
        "resourceType": "AccessPolicy",
        "id": "allow-test-provider-client",
        "engine": "allow",
        "link": [{"resourceType": "Client", "id": "test-provider-client"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Organization/test-payer-001"},
      "resource": {
        "resourceType": "Organization",
        "id": "test-payer-001",
        "name": "Test Payer Organization",
        "identifier": [{"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Organization/test-provider-001"},
      "resource": {
        "resourceType": "Organization",
        "id": "test-provider-001",
        "name": "Test Provider Organization",
        "identifier": [{"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Organization/other-payer-001"},
      "resource": {
        "resourceType": "Organization",
        "id": "other-payer-001",
        "name": "Other Payer (not the requester)",
        "identifier": [{"system": "http://hl7.org/fhir/sid/us-npi", "value": "9999999999"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Patient/test-member-001"},
      "resource": {
        "resourceType": "Patient",
        "id": "test-member-001",
        "name": [{"family": "Johnson", "given": ["Robert"]}],
        "gender": "male",
        "birthDate": "1952-07-25",
        "identifier": [{"system": "http://example.org/member-id", "value": "M12345"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Patient/test-member-002"},
      "resource": {
        "resourceType": "Patient",
        "id": "test-member-002",
        "name": [{"family": "Williams", "given": ["Sarah"]}],
        "gender": "female",
        "birthDate": "1985-03-12",
        "identifier": [{"system": "http://example.org/member-id", "value": "M67890"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Coverage/test-coverage-001"},
      "resource": {
        "resourceType": "Coverage",
        "id": "test-coverage-001",
        "status": "active",
        "subscriberId": "SUB-001",
        "beneficiary": {"reference": "Patient/test-member-001"},
        "payor": [{"reference": "Organization/test-payer-001"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Coverage/test-coverage-002"},
      "resource": {
        "resourceType": "Coverage",
        "id": "test-coverage-002",
        "status": "active",
        "subscriberId": "SUB-002",
        "beneficiary": {"reference": "Patient/test-member-002"},
        "payor": [{"reference": "Organization/test-payer-001"}]
      }
    },
    {
      "request": {"method": "PUT", "url": "/Consent/test-optout-member-002"},
      "resource": {
        "resourceType": "Consent",
        "id": "test-optout-member-002",
        "status": "active",
        "scope": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/consentscope", "code": "patient-privacy"}]},
        "patient": {"reference": "Patient/test-member-002"},
        "category": [{"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/pdex-consent-api-purpose", "code": "provider-access"}]}],
        "provision": {"type": "deny"},
        "policyRule": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN"}]}
      }
    }
  ]
}

Auth

SMART Backend Services. See Authentication.

Kick-off

Endpoint

POST <base>/fhir/Group/$bulk-member-match

Prefer: respond-async is required. Requests without it are rejected with 400.

Parameters

The request body is a Parameters resource with one or more MemberBundle entries, validated against the pdex-parameters-multi-member-match-bundle-in profile.

DirectionParameterTypeCardinalityDescription
INMemberBundlepart group1..*One per submitted member; contains MemberPatient, CoverageToMatch, Consent, optional CoverageToLink
INMemberBundle.MemberPatientPatient1..1HRex Patient Demographics — family, given[0], birthDate, gender are all required for matching; identifier entries are added to the matching query as identifier search tokens
INMemberBundle.CoverageToMatchCoverage1..1HRex Coverage; subscriberId (when present) is added to the matching query as _has:Coverage:beneficiary:subscriber-id
INMemberBundle.ConsentConsent1..1HRex Consent; status, provision.period, provision.actor[role=IRCP], and policy.uri are evaluated at match time (see Matching behavior)
INMemberBundle.CoverageToLinkCoverage0..1HRex Coverage
OUT (kick-off)202 Accepted with Content-Location header pointing at the status URL

Example

POST /fhir/Group/$bulk-member-match
Authorization: Basic dGVzdC1wYXllci1jbGllbnQ6dGVzdC1wYXllci1zZWNyZXQ=
Content-Type: application/fhir+json
Prefer: respond-async

{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "MemberBundle",
      "part": [
        {"name": "MemberPatient", "resource": {
          "resourceType": "Patient",
          "name": [{"family": "Johnson", "given": ["Robert"]}],
          "gender": "male", "birthDate": "1952-07-25"
        }},
        {"name": "CoverageToMatch", "resource": {
          "resourceType": "Coverage", "status": "active",
          "subscriberId": "SUB-001",
          "beneficiary": {"reference": "Patient/test-member-001"},
          "payor": [{"reference": "Organization/test-payer-001"}]
        }},
        {"name": "Consent", "resource": {
          "resourceType": "Consent", "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/test-member-001"},
          "dateTime": "2026-04-01T08:00:00Z",
          "policy": [{"uri": "http://hl7.org/fhir/us/davinci-hrex/StructureDefinition-hrex-consent.html#sensitive"}],
          "provision": {
            "type": "permit",
            "period": {"start": "2026-01-01T00:00:00Z", "end": "2027-01-01T00:00:00Z"},
            "actor": [{
              "role": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", "code": "IRCP"}]},
              "reference": {"reference": "Organization/test-payer-001"}
            }]
          }
        }}
      ]
    },
    {
      "name": "MemberBundle",
      "part": [
        {"name": "MemberPatient", "resource": {
          "resourceType": "Patient",
          "name": [{"family": "Williams", "given": ["Sarah"]}],
          "gender": "female", "birthDate": "1985-03-12"
        }},
        {"name": "CoverageToMatch", "resource": {
          "resourceType": "Coverage", "status": "active",
          "subscriberId": "SUB-002",
          "beneficiary": {"reference": "Patient/test-member-002"},
          "payor": [{"reference": "Organization/test-payer-001"}]
        }},
        {"name": "Consent", "resource": {
          "resourceType": "Consent", "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/test-member-002"},
          "dateTime": "2026-04-01T08:00:00Z",
          "policy": [{"uri": "http://hl7.org/fhir/us/davinci-hrex/StructureDefinition-hrex-consent.html#sensitive"}],
          "provision": {
            "type": "permit",
            "period": {"start": "2026-01-01T00:00:00Z", "end": "2027-01-01T00:00:00Z"},
            "actor": [{
              "role": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", "code": "IRCP"}]},
              "reference": {"reference": "Organization/other-payer-001"}
            }]
          }
        }}
      ]
    },
    {
      "name": "MemberBundle",
      "part": [
        {"name": "MemberPatient", "resource": {
          "resourceType": "Patient",
          "name": [{"family": "Unknown", "given": ["Nobody"]}],
          "gender": "male", "birthDate": "2000-01-01"
        }},
        {"name": "CoverageToMatch", "resource": {
          "resourceType": "Coverage", "status": "active",
          "subscriberId": "SUB-999",
          "beneficiary": {"reference": "Patient/test-member-001"},
          "payor": [{"reference": "Organization/test-payer-001"}]
        }},
        {"name": "Consent", "resource": {
          "resourceType": "Consent", "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/test-member-001"},
          "dateTime": "2026-04-01T08:00:00Z",
          "policy": [{"uri": "http://hl7.org/fhir/us/davinci-hrex/StructureDefinition-hrex-consent.html#sensitive"}],
          "provision": {
            "type": "permit",
            "period": {"start": "2026-01-01T00:00:00Z", "end": "2027-01-01T00:00:00Z"},
            "actor": [{
              "role": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", "code": "IRCP"}]},
              "reference": {"reference": "Organization/test-payer-001"}
            }]
          }
        }}
      ]
    }
  ]
}

Three submitted MemberBundles drive the three output buckets:

  • Johnson → demographics match Patient/test-member-001; Consent recipient = Organization/test-payer-001 (the caller) → MatchedMembers
  • Williams → demographics match Patient/test-member-002; Consent recipient = Organization/other-payer-001 (not the caller) → fails recipient match → ConsentConstrainedMembers
  • Unknown → demographics do not match any seeded Patient → NonMatchedMembers
HTTP/1.1 202 Accepted
Content-Location: <base>/fhir/Group/$bulk-member-match-status/<task-id>
HTTP/1.1 400 Bad Request
Content-Type: application/fhir+json

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "processing",
    "diagnostics": "This operation requires Prefer: respond-async header"
  }]
}
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/fhir+json

The body is the OperationOutcome returned by Aidbox $validate against the input profile.

Status polling

Endpoint

GET <base>/fhir/Group/$bulk-member-match-status/<task-id>

<task-id> is the id at the end of the Content-Location from kick-off. Calls from a client other than the originating requester get 404 (cross-tenant guard).

Parameters

Response shape depends on the underlying Task status:

Task statusHTTPHeadersBody
requested202Retry-After: 5
in-progress202Retry-After: 5, X-Progress: Processing members
completed200Content-Type: application/jsonBulk Data manifest
failed500OperationOutcome
cancelled / not found / hard-deleted404OperationOutcome

Example

GET /fhir/Group/$bulk-member-match-status/<task-id>
HTTP/1.1 202 Accepted
Retry-After: 5
X-Progress: Processing members
HTTP/1.1 200 OK
Content-Type: application/json

{
  "transactionTime": "2026-05-15T13:17:56Z",
  "request": "<base>/fhir/Group/$bulk-member-match",
  "requiresAccessToken": true,
  "output": [
    {"type": "Parameters", "url": "<base>/output/<task-id>.ndjson"}
  ],
  "error": []
}
HTTP/1.1 500 Internal Server Error
Content-Type: application/fhir+json

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "exception",
    "diagnostics": "Internal error processing request"
  }]
}

Output download

Endpoint

GET <base>/output/<task-id>.ndjson

URL comes from output[0].url in the manifest. Body is a single ndjson line — a Parameters resource conforming to the pdex-parameters-multi-member-match-bundle-out profile. MatchedMembers is always present (1..1 per the output profile); the other two buckets appear only when non-empty.

Parameters

DirectionParameterTypeCardinalityDescription
OUTMatchedMembersGroup1..1pdex-member-match-group; members matched, consent passed, opt-out clear, and the submitted Consent persisted. Group id is the input to $davinci-data-export with exportType = hl7.fhir.us.davinci-pdex#payertopayer. quantity = 0 and member omitted when empty.
OUTNonMatchedMembersGroup0..1pdex-member-no-match-group; no match found. Submitted Patients are carried in Group.contained[] (fragment refs #1, #2, …).
OUTConsentConstrainedMembersGroup0..1pdex-member-no-match-group with code consentconstraint; matched member whose Consent failed a match-time check, has an active opt-out, or whose Consent could not be persisted.

Example

GET /output/<task-id>.ndjson
HTTP/1.1 200 OK
Content-Type: application/fhir+ndjson

Body (single ndjson line, formatted for readability):

{
  "resourceType": "Parameters",
  "meta": {"profile": ["http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-parameters-multi-member-match-bundle-out"]},
  "parameter": [
    {
      "name": "MatchedMembers",
      "resource": {
        "resourceType": "Group",
        "id": "<task-id>-matched",
        "meta": {"profile": ["http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-member-match-group"]},
        "active": true, "type": "person", "actual": true,
        "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "match"}]},
        "characteristic": [{
          "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "match"}]},
          "valueReference": {
            "identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"},
            "reference": "Organization/test-payer-001"
          },
          "exclude": false
        }],
        "quantity": 1,
        "member": [{"entity": {"reference": "Patient/test-member-001", "display": "Johnson, Robert"}, "inactive": false}]
      }
    },
    {
      "name": "NonMatchedMembers",
      "resource": {
        "resourceType": "Group",
        "id": "<task-id>-nomatch",
        "meta": {"profile": ["http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-member-no-match-group"]},
        "active": true, "type": "person", "actual": true,
        "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "nomatch"}]},
        "contained": [{"resourceType": "Patient", "id": "1", "name": [{"family": "Unknown", "given": ["Nobody"]}], "gender": "male", "birthDate": "2000-01-01"}],
        "characteristic": [{
          "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "nomatch"}]},
          "valueBoolean": true,
          "exclude": false
        }],
        "quantity": 1,
        "member": [{
          "entity": {
            "reference": "#1",
            "extension": [{
              "url": "http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/base-ext-match-parameters",
              "valueReference": {"reference": "#1"}
            }]
          },
          "inactive": false
        }]
      }
    },
    {
      "name": "ConsentConstrainedMembers",
      "resource": {
        "resourceType": "Group",
        "id": "<task-id>-consent",
        "meta": {"profile": ["http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-member-no-match-group"]},
        "active": true, "type": "person", "actual": true,
        "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "consentconstraint"}]},
        "characteristic": [{
          "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "consentconstraint"}]},
          "valueReference": {
            "identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"},
            "reference": "Organization/test-payer-001"
          },
          "exclude": false
        }],
        "quantity": 1,
        "member": [{"entity": {"reference": "Patient/test-member-002", "display": "Williams, Sarah"}, "inactive": false}]
      }
    }
  ]
}

MatchedMembers and ConsentConstrainedMembers carry the requesting payer's NPI in characteristic[0].valueReference.identifier; the literal Organization/<id> reference is added when the responding payer has an Organization registered for that NPI. Patient.identifier entries submitted on MemberPatient are used as additional matching tokens but are not echoed back on the matched Group.

Cancellation

Endpoint

DELETE <base>/fhir/Group/$bulk-member-match-cancel/<task-id>

A custom URL is used (rather than DELETE on the status URL) because Aidbox operation dispatch is keyed on method + URL. Cross-tenant calls return 404.

Parameters

Behaviour depends on the current Task status:

Task statusActionResponse
requested / in-progressSet Task.status = "cancelled". The background worker stops at its next checkpoint (per-member loop + pre-persist) without writing Groups, the Binary, or persisted Consents.202 Accepted
completed / failed / cancelledDelete the Task and every resource referenced from Task.output (Groups, Binary, and persisted Consents).202 Accepted
not found / already hard-deleted404 with OperationOutcome

Example

DELETE /fhir/Group/$bulk-member-match-cancel/<task-id>
HTTP/1.1 202 Accepted

Matching behavior

Each submitted member is evaluated independently. Per-member failures never fail the batch — problematic members are routed to NonMatchedMembers or ConsentConstrainedMembers.

Demographic match. Same algorithm as $provider-member-match: all four of family, given[0], birthDate, gender are required and queried against payer Patients. Patient.identifier entries become identifier search tokens (FHIR AND semantics — every submitted identifier must match). Identifier-AND is bulk-specific: $provider-member-match ignores submitted Patient.identifier entries, because provider-side systems carry MRNs the payer does not store. Coverage.subscriberId, when present, becomes _has:Coverage:beneficiary:subscriber-id. Zero or ambiguous (>1) results route to NonMatchedMembers.

Match-time consent checks. A matched member is moved to ConsentConstrainedMembers if any of the following is true (the opt-out category code below uses the pdex-consent-api-purpose CodeSystem from PDex 2.2.0):

CheckConstrains when
Consent.statusnot "active"
Consent.provision.periodabsent, unparseable, or does not cover the current time
Consent.provision.actor[role=IRCP] recipientdoes not resolve to the requesting payer's Organization/<id> reference
Consent.policy[*].urinot #sensitive — #regular and missing/unknown policy URIs both constrain (fail-safe; Payerbox does not yet redact sensitive data, so non-#sensitive consents cannot be honored)
Active provider-access deny Consent on the matched Patient (opt-out)any active hit; a failing opt-out query (non-2xx) fails safe to constrained

The opt-out check reuses the same Aidbox search as $provider-member-match: Consent?patient=<id>&status=active&category=http://hl7.org/fhir/us/davinci-pdex/CodeSystem/pdex-consent-api-purpose|provider-access&provision-type=deny.

Consent persistence. For each remaining matched member the submitted Consent is upserted into Aidbox with a deterministic id (SHA-1(payer-org-id|patient-id)); Consent.patient is rewritten to the matched payer Patient and Consent.organization to the requesting payer's Organization (FHIR shape is 0..*; today exactly one element is written). The persisted Consent is what the later $davinci-data-export?exportType=payertopayer query reads against. If persistence fails — including the case where the requesting payer's NPI has no Organization registered in the responding payer's Aidbox — the member is re-bucketed to ConsentConstrainedMembers.

Stale Consent deactivation. If a later $bulk-member-match for the same (matched-patient, requesting-payer) lands the member in ConsentConstrainedMembers (failed match-time check, opt-out hit, or persistence failure), the prior persisted Consent at the deterministic id is flipped to status = inactive. The row is retained for audit, but $davinci-data-export?exportType=payertopayer will not honor it on subsequent reads.

Group lifecycle

Output Groups carry no period.end and no TTL extension today. Until lifecycle management ships, $bulk-member-match output Groups remain active = true indefinitely; the only removal path is $bulk-member-match-cancel on a completed Task, which sweeps the Task and every resource referenced from Task.output (Groups, Binary, and persisted Consents).

Errors

StatusWhereCause
400Kick-offPrefer: respond-async header missing
403Kick-offRequesting payer identity could not be resolved from the OAuth client
404Status / outputUnknown <task-id>, Task.status = cancelled, or caller is not the originating requester
404CancelUnknown <task-id> (hard-deleted), or caller is not the originating requester (cancel on a cancelled Task returns 202 and sweeps outputs)
409Kick-offRequesting payer identity is ambiguous — more than one Organization in the responding payer's directory matches; resolve duplicates and retry
422Kick-offInput Parameters failed $validate against the input profile
500Kick-offFailed to resolve requesting payer Organization (transient Aidbox read failure)
500StatusBackground processing failed; generic OperationOutcome returned (real cause in interop-app logs)
500Kick-off / status / cancelUpstream Aidbox read or write failed transiently

Individual member failures (validation issues, exceptions while evaluating one member, Consent persistence failures) route to NonMatchedMembers or ConsentConstrainedMembers with a reason recorded in Task logs — they do not fail the batch.

After a MatchedMembers Group is returned, the requesting payer uses its id with $davinci-data-export (exportType = hl7.fhir.us.davinci-pdex#payertopayer) to pull the matched members' clinical data. Architectural context lives in the Payer-to-Payer pillar.

Last updated: