Aidbox Docs

$provider-member-match

The $provider-member-match operation implements the Da Vinci PDex Provider Access API. It lets a provider submit a batch of members (patient demographics, coverage, and a treatment-relationship attestation) and receive one or more Group resources whose IDs can then be used with $davinci-data-export to pull clinical data in bulk.

The operation follows the FHIR Bulk Data async pattern: the kick-off request POST [base]/fhir/Group/$provider-member-match returns 202 Accepted with a Content-Location header, the client polls the status URL, and once processing is complete downloads an ndjson file containing the output Parameters resource.

$provider-member-match is not part of Aidbox core. It is delivered by the Aidbox PDex / Provider Access interop app, which registers itself with Aidbox as a FHIR App resource and handles the operation via HTTP-RPC. You must run and register the interop app against your Aidbox instance before these endpoints are available. The PDex 2.1 FHIR package (hl7.fhir.us.davinci-pdex#2.1.0) also needs to be loaded in Aidbox so the input/output profiles are known to $validate.

$provider-member-match is always asynchronous. Clients must include the Prefer: respond-async header on the kick-off request. Requests without this header are rejected with 400 Bad Request.

Overview

Each submitted member goes through a deterministic evaluation pipeline and lands in exactly one of three output buckets:

BucketProfileCodeMeaning
MatchedMemberspdex-treatment-relationshipmatchDemographics matched a payer member, treatment attestation is valid, and the member has not opted out. The Group ID of this bucket is what the provider feeds into $davinci-data-export.
NonMatchedMemberspdex-member-no-match-groupnomatchNo match was found, the match was ambiguous, or the treatment attestation was invalid.
ConsentConstrainedMemberspdex-member-opt-outconsentconstraintDemographics matched, but the member has an active opt-out Consent on file.

Per-member failures do not fail the whole batch — problematic members are routed to NonMatchedMembers.

Per-member evaluation pipeline

valid matched invalid no match opted out not opted out Input member Validate attestation Match demographics Check opt-out NonMatchedMembers ConsentConstrainedMembers MatchedMembers

Per-member edge cases

The pipeline never rejects an entire batch. Every input member resolves to exactly one bucket, even when the input is malformed:

ConditionBucket
Consent part missing or status not activeNonMatchedMembers
Submitted Patient missing any of family, given[0], birthDate, genderNonMatchedMembers
Demographic search returns zero payer PatientsNonMatchedMembers
Demographic search returns more than one payer Patient (ambiguous)NonMatchedMembers
Coverage.subscriberId is present but no payer Patient has a matching CoverageNonMatchedMembers
Unhandled exception while evaluating a single memberNonMatchedMembers (with reason in Task logs)
Match succeeds and matched Patient has an active opt-out ConsentConsentConstrainedMembers
Match succeeds and no opt-out existsMatchedMembers

Workflow

1

Kick-off. POST a Parameters resource listing one or more MemberBundle entries. Include Prefer: respond-async. The server responds with 202 Accepted and a Content-Location header pointing at the status URL.

2

Poll status. GET the URL from Content-Location. While processing is running you get 202 Accepted with a Retry-After header. Once complete you get 200 OK with a Bulk Data manifest whose output[].url points to an ndjson file.

3

Download output. GET the ndjson URL from the manifest. The body is a single-line Parameters resource containing the output Group resources inline.

4

(Optional) Cancel or delete. DELETE the cancel URL to stop a running job or clean up a completed one.

Async sequence

alt [Task in-progress] [Task completed] loop [Poll] POST /fhir/Group/$provider-member-matchPrefer: respond-async HTTP-RPC kick-off PUT Task (status=requested) 202 + Content-Location 202 + Content-Location GET .../$provider-member-match-status/{id} HTTP-RPC status 202 + Retry-After 202 + Retry-After 200 + Bulk Data manifest 200 + manifest GET /output/{id}.ndjson HTTP-RPC ndjson 200 + Parameters (ndjson) 200 + Parameters (ndjson) background future:match → opt-out → group build Provider client Aidbox Interop app

Authorization

$provider-member-match is a backend-services API: callers are provider organizations, not end users. The interop app authenticates the request via the OAuth client that Aidbox issues a token to (typically through the SMART Backend Services / client_credentials flow).

ConcernRequirement
Auth flowOAuth 2.0 client_credentials (SMART Backend Services). The bearer token is presented to Aidbox; Aidbox forwards the resolved oauth/client to the interop app over HTTP-RPC.
Provider identityThe OAuth Client resource representing the provider organization must carry an NPI in Client.identifier[*] with system = http://hl7.org/fhir/sid/us-npi. The interop app reads this entry and stamps it on Task.requester and on the MatchedMembers Group. If no NPI is found the provider is recorded as "unknown".
Required Aidbox accessThe interop app needs read access to Patient, Coverage, Consent, Organization (for payer NPI lookup) and read/write access to Task, Group, Binary in the same Aidbox instance. The app is registered as a FHIR App resource on startup; granting the App an access policy that allows these resource types is sufficient.
App registrationThe interop app must be running and registered (its App resource present in Aidbox). Without it, POST /fhir/Group/$provider-member-match returns Aidbox's default "operation not found" response.

UDAP B2B token validation, mTLS, and dynamic client registration are not implemented today — see Limitations.

Input

A FHIR Parameters resource with one or more MemberBundle parameters. Each MemberBundle contains:

PartCard.TypeProfile
MemberPatient1..1PatientHRex Patient Demographics
CoverageToMatch1..1CoverageHRex Coverage
Consent1..1ConsentProvider Treatment Relationship Consent
CoverageToLink0..1CoverageHRex Coverage

The whole Parameters body is first validated with Aidbox $validate against the provider-parameters-multi-member-match-bundle-in profile. If validation fails, the server returns 422 Unprocessable Entity with the OperationOutcome from $validate and no background job is created.

Matching algorithm

Matching is deterministic and exact. The following demographic fields are all required on the submitted Patient and must all match a payer-side Patient:

FieldLogic
Patient.name[0].familyCase-insensitive exact
Patient.name[0].given[0]Case-insensitive exact
Patient.birthDateExact
Patient.genderExact

When CoverageToMatch.subscriberId is present the matching query additionally requires _has:Coverage:beneficiary:subscriber-id=<subscriberId> so only Patients with a matching Coverage subscriber ID are considered.

A member is treated as unmatched when the demographic search returns zero entries or more than one entry (ambiguous matches are rejected conservatively).

Treatment attestation

The Consent part is the provider's attestation that a treatment relationship exists with the member. The attestation is accepted when the Consent resource is present and Consent.status = "active". There is no deeper verification of the attestation claim itself — the attestation is the declaration.

Opt-out check

After a successful demographic match, the server searches for an active opt-out Consent on the matched payer-side Patient:

GET /fhir/Consent
  ?patient=<matched-patient-id>
  &status=active
  &category=http://hl7.org/fhir/us/davinci-pdex/CodeSystem/pdex-consent-api-purpose|provider-access
  &provision-type=deny

If at least one such Consent exists, the member is placed in ConsentConstrainedMembers. Revocations (provision.type = "permit") are not returned by this query and therefore do not block the member.

All opt-out scopes (global, provider-specific, purpose-specific, payer-specific, provider-category) are currently treated the same — any active deny opts the member out. Scope-aware enforcement is not yet implemented.

Kick-off example

POST /fhir/Group/$provider-member-match
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",
            "identifier": [
              {"system": "http://example.org/member-id", "value": "M12345"}
            ]
          }
        },
        {
          "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": "treatment"
              }]
            },
            "category": [
              {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "IDSCL"}]},
              {"coding": [{"system": "http://loinc.org", "code": "64292-6"}]}
            ],
            "patient": {"reference": "Patient/test-member-001"},
            "dateTime": "2026-01-15T10:00:00Z",
            "performer": [
              {"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}}
            ],
            "policyRule": {
              "coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN"}]
            }
          }
        }
      ]
    }
  ]
}

Status

202 Accepted

Headers

  • Content-Location — status URL, e.g. [base]/fhir/Group/$provider-member-match-status/<task-id>

Status

422 Unprocessable Entity

Body

{
  "resourceType": "OperationOutcome",
  "id": "validationfail",
  "issue": [
    {
      "severity": "error",
      "code": "invariant",
      "diagnostics": "..."
    }
  ]
}

Status

400 Bad Request

Body

{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "processing",
      "diagnostics": "This operation requires Prefer: respond-async header"
    }
  ]
}

Status polling

GET [base]/fhir/Group/$provider-member-match-status/<task-id>

The operation tracks progress with a standard FHIR Task resource. Responses map from the Task status as follows:

Task statusHTTPHeadersBody
requested202Retry-After: 5
in-progress202Retry-After: 5, X-Progress: Processing members
completed200Content-Type: application/jsonBulk Data manifest
failed500OperationOutcome with failure diagnostics
not found404OperationOutcome

Status

202 Accepted

Headers

HeaderValue
Retry-After5
X-ProgressProcessing members

Status

200 OK

Body

{
  "transactionTime": "2026-04-20T12:34:56Z",
  "request": "[base]/fhir/Group/$provider-member-match",
  "requiresAccessToken": true,
  "output": [
    {
      "type": "Parameters",
      "url": "[base]/output/<task-id>.ndjson"
    }
  ],
  "error": []
}

Status

500 Internal Server Error

Body

{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "error",
      "code": "exception",
      "diagnostics": "<reason from Task.statusReason>"
    }
  ]
}

Output

The manifest's output[0].url points at an ndjson endpoint served by Aidbox:

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

The body is a single line — a Parameters resource conforming to the provider-parameters-multi-member-match-bundle-out profile. Each non-empty output bucket appears as one parameter whose resource is the full inline Group. Empty buckets are omitted.

GET /output/<task-id>.ndjson

Status

200 OK

Headers

HeaderValue
Content-Typeapplication/fhir+ndjson

Body (single ndjson line, formatted for readability)

{
  "resourceType": "Parameters",
  "meta": {
    "profile": [
      "http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/provider-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-treatment-relationship"
          ]
        },
        "active": true,
        "type": "person",
        "actual": true,
        "code": {
          "coding": [{
            "system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS",
            "code": "match"
          }]
        },
        "identifier": [
          {"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}
        ],
        "managingEntity": {
          "identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"},
          "display": "Payer Organization"
        },
        "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": "1982947230"},
            "display": "Provider Organization"
          },
          "exclude": false,
          "period": {"start": "2026-04-20", "end": "2026-05-20"}
        }],
        "quantity": 1,
        "member": [
          {"entity": {"reference": "Patient/test-member-001", "display": "Johnson, Robert"}, "inactive": false}
        ]
      }
    },
    {
      "name": "ConsentConstrainedMembers",
      "resource": {
        "resourceType": "Group",
        "id": "<task-id>-consent",
        "meta": {
          "profile": [
            "http://hl7.org/fhir/us/davinci-pdex/StructureDefinition/pdex-member-opt-out"
          ]
        },
        "active": true,
        "type": "person",
        "actual": true,
        "code": {
          "coding": [{
            "system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS",
            "code": "consentconstraint"
          }]
        },
        "managingEntity": {
          "identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "5555555555"},
          "display": "Payer Organization"
        },
        "characteristic": [{
          "code": {"coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/PdexMultiMemberMatchResultCS", "code": "consentconstraint"}]},
          "valueCodeableConcept": {
            "coding": [{"system": "http://hl7.org/fhir/us/davinci-pdex/CodeSystem/opt-out-scope", "code": "provider-specific"}]
          },
          "exclude": false,
          "period": {"start": "2026-04-20", "end": "2026-05-20"}
        }],
        "quantity": 1,
        "member": [
          {"entity": {"reference": "Patient/test-member-002", "display": "Williams, Sarah"}, "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,
          "period": {"start": "2026-04-20", "end": "2026-05-20"}
        }],
        "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
          }
        ]
      }
    }
  ]
}

Output Group fields

All output Groups share type = "person", actual = true, and active = true. Additional fields depend on the bucket:

MatchedMembers and ConsentConstrainedMembers

  • managingEntity.identifier — the payer's NPI, resolved from the first submitted member's Coverage.payor[0].reference (an Organization with an identifier of system http://hl7.org/fhir/sid/us-npi). If the Organization is missing or has no NPI, this falls back to "unknown".
  • member[].entity.reference — a literal reference to the payer-side Patient that was matched.
  • characteristic[].period — 30-day validity window, period.start is today, period.end is 30 days out.

MatchedMembers only

  • identifier — array containing the provider's NPI (derived from the authenticated OAuth client's identifier entry with system http://hl7.org/fhir/sid/us-npi).
  • characteristic[0].valueReference — a logical reference by NPI to the provider Organization.

NonMatchedMembers

  • The submitted Patient demographics are not persisted as standalone Patient resources. Instead, each submitted Patient is carried in Group.contained[] with a local id ("1", "2", …).
  • member[].entity.reference is a fragment reference ("#1", "#2", …) into contained, plus a base-ext-match-parameters extension carrying the same fragment reference.
  • characteristic[0].valueBoolean = true.

Cancellation and deletion

DELETE [base]/fhir/Group/$provider-member-match-cancel/<task-id>

Cancellation is cooperative. The background worker checks the Task status before starting, after each evaluated member, and again before persisting results — so a cancelled job stops at the next checkpoint without ever writing Groups or the Binary.

Task statusActionResponse
requested / in-progressSet Task to cancelled. The background processor stops at its next checkpoint.202 Accepted
completed / failed / cancelledDelete the Task and every resource referenced from Task.output (Groups and the Binary).202 Accepted
not found404 OperationOutcome

Cancellation uses a custom $provider-member-match-cancel URL rather than DELETE on the status URL, because Aidbox operation dispatch is keyed on HTTP method and distinct method/URL combinations must be registered separately.

Group lifecycle and cleanup

Each output Group carries a 30-day validity window on Group.characteristic[0].period:

"period": {"start": "2026-04-20", "end": "2026-05-20"}

A background job inside the interop app runs hourly and:

  1. Deactivates expired Groups — Groups whose characteristic.period.end has passed and whose active = true are flipped to active = false.
  2. Hard-deletes old inactive Groups — Groups with active = false whose characteristic.period.end is more than 90 days in the past are removed along with the Task and Binary they belong to.

Cleanup only touches PDex Groups — the scan filters on _profile=<pdex-treatment-relationship,pdex-member-no-match-group,pdex-member-opt-out>. Non-PDex Groups in the same Aidbox instance are left alone.

Error responses

StatusCondition
202Async request accepted (kick-off) or cancellation acknowledged.
200Polling complete, manifest returned.
400Prefer: respond-async header is missing.
404Unknown task-id on status, cancel, or output.
422Input Parameters failed profile validation.
500Background processing failed; see Task.statusReason.

Individual member failures (validation issues, exceptions while evaluating one member) do not fail the whole batch — the affected members are routed to NonMatchedMembers with a reason string.

End-to-end example

The snippets below reproduce the three-bucket demo used in internal testing. They assume an Aidbox instance with the PDex STU 2.1 package loaded, the interop app registered, and an OAuth client authorized to call it.

1. Seed the payer-side test data

Post this Bundle once to create the Organization, payer-side Patients, Coverages, and an opt-out Consent for test-member-002.

POST /fhir
Content-Type: application/fhir+json
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "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": "/Patient/test-member-001"},
      "resource": {
        "resourceType": "Patient", "id": "test-member-001",
        "name": [{"family": "Johnson", "given": ["Robert"]}],
        "gender": "male", "birthDate": "1952-07-25"
      }
    },
    {
      "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"
      }
    },
    {
      "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"}]}
      }
    }
  ]
}

2. Kick off

Submit three members: one will match, one will hit the opt-out, one has no match.

POST /fhir/Group/$provider-member-match
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": "treatment"}]}, "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "IDSCL"}]}, {"coding": [{"system": "http://loinc.org", "code": "64292-6"}]}], "patient": {"reference": "Patient/test-member-001"}, "dateTime": "2026-01-15T10:00:00Z", "performer": [{"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}}], "policyRule": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN"}]}}}
      ]
    },
    {
      "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": "treatment"}]}, "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "IDSCL"}]}, {"coding": [{"system": "http://loinc.org", "code": "64292-6"}]}], "patient": {"reference": "Patient/test-member-002"}, "dateTime": "2026-01-15T10:00:00Z", "performer": [{"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}}], "policyRule": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN"}]}}}
      ]
    },
    {
      "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": "treatment"}]}, "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "IDSCL"}]}, {"coding": [{"system": "http://loinc.org", "code": "64292-6"}]}], "patient": {"reference": "Patient/test-member-001"}, "dateTime": "2026-01-15T10:00:00Z", "performer": [{"identifier": {"system": "http://hl7.org/fhir/sid/us-npi", "value": "1982947230"}}], "policyRule": {"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "OPTIN"}]}}}
      ]
    }
  ]
}

Response: 202 Accepted, Content-Location: [base]/fhir/Group/$provider-member-match-status/<task-id>.

3. Poll

Call the status URL until it returns 200 OK.

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

4. Download

Use the output[0].url from the manifest to fetch the ndjson.

GET /output/<task-id>.ndjson

Expected result distribution:

MemberMatchOpt-outBucket
Johnson, RobertYes (test-member-001)NoMatchedMembers
Williams, SarahYes (test-member-002)YesConsentConstrainedMembers
Unknown, NobodyNoNonMatchedMembers

Limitations

The current implementation is intentionally MVP-scoped. The following items are recognized gaps versus the PDex 2.1 spec / production expectations:

AreaStatus
Matching algorithmDeterministic exact match only (family, given[0], birthDate, gender, optional subscriberId). No fuzzy / probabilistic matching, no confidence scoring, no multi-tier fall-through.
Opt-out scope enforcementAll opt-out scopes (global, provider-specific, purpose-specific, payer-specific, provider-category) are treated identically — any active deny constrains the match. Targeting the requesting provider's NPI for provider-specific opt-outs is not yet enforced.
Authentication hardeningUDAP B2B token validation, mTLS, and dynamic client registration are not implemented. The operation relies on whatever OAuth flow Aidbox is configured for.
Rate limitingNo throttling, no 429 Too Many Requests, no per-client concurrency caps.
Treatment-relationship verificationLimited to Consent.status = "active" and presence of the resource. The attestation claim itself is not cross-checked against external sources.
Sandbox / interactive consoleNone — all examples are run against a real Aidbox instance.

What's next

After receiving a MatchedMembers Group, the provider uses its ID to call $davinci-data-export (FHIR Bulk Data group export) on the same Aidbox instance to retrieve the matched patients' clinical data as ndjson. Documentation for that operation will live alongside this page in the Provider Access API section.