Payerbox Docs

$davinci-data-export

Exports clinical, claims, encounter, and prior-authorization data for the members of a Group as ndjson, defined by the Da Vinci ATR IG and referenced by the Da Vinci PDex IG. It is the bulk entry point for both Provider Access (Group produced by $provider-member-match) and Payer-to-Payer (Group produced by $bulk-member-match).

The operation is always asynchronous and follows the FHIR Bulk Data export pattern: kick-off returns 202 Accepted with Content-Location, the client polls the status URL, and downloads each ndjson file referenced in the completed manifest.

exportType selects the PDex scenario the request runs under (see exportType values). Scope follows the Da Vinci Payer-to-Payer Bulk Data Exchange and ATR $davinci-data-export requirements:

  • Opt-in / opt-out consent, per exportType
  • Financial fields excluded from ExplanationOfBenefit and Coverage
  • Drug claims and drug PAs dropped
  • 5-year ExplanationOfBenefit service-date window for payertopayer

The kick-off endpoint is owned by Payerbox's interop app; status polling, output download, and cancellation are served by Aidbox at its standard Bulk Data Export URLs ($export-status, signed output URLs).

Auth

SMART Backend Services and Client Credentials. The caller's OAuth client must be allowed to read the Group and the resource types referenced by _type (and their referenced resources, since Aidbox $export chases references). See Authentication.

payertopayer gates the opt-in export on the UDAP HL7 B2B organization_id claim; the interop app fails closed with 401 when the caller's token carries no such claim.

Kick-off

Endpoint

POST <base>/fhir/Group/<group-id>/$davinci-data-export

<group-id> is the id of a Group resource — typically MatchedMembers from $provider-member-match or $bulk-member-match. Prefer: respond-async is required. Requests without it are rejected with 400.

Parameters

The request body must be a FHIR Parameters resource. Unsupported parameter names are rejected with 400. Aidbox's $export also validates the body against its BulkExportProfile and returns 422 on shape errors (for example, an empty parameter[]).

Dir.ParameterTypeCard.Description
INexportTypecanonical (valueCanonical)0..1Selects the PDex scenario (consent rule + data scope). Supported values: hl7.fhir.us.davinci-pdex#provider-download and hl7.fhir.us.davinci-pdex#payertopayer. See exportType values.
IN_sinceinstant (valueInstant)0..1Only resources updated since this time.
IN_untilinstant (valueInstant)0..1Only resources updated up to this time.
IN_typestring (valueString)0..1Comma-separated FHIR resource types to include (e.g. Patient,Coverage,ExplanationOfBenefit).
IN_typeFilterstring (valueString)0..*Per-type FHIR search expression (e.g. Observation?category=laboratory). A caller clause naming ExplanationOfBenefit is rejected with 400: it would OR-merge with the interop app's injected pharmacy/service-date EOB filter and re-admit excluded data.
IN_outputFormatstring (valueString)0..1Output format. application/fhir+ndjson is the default and only value supported in PDex 2.1.0.
INpatientreference (valueReference)0..*Narrow the export to specific Patients.
OUT202 Accepted with Content-Location pointing at the Aidbox status URL.

exportType values

ValueUsed byConsent ruleData scope
hl7.fhir.us.davinci-pdex#provider-downloadProvider AccessMember opt-out (consentStrategy=opt-out, PDex Provider Consent, provision.type=deny)Full member record, minus drug claims / drug PAs and money fields
hl7.fhir.us.davinci-pdex#payertopayerPayer-to-PayerActive opt-in Consent asserted at $bulk-member-match time (consentStrategy=opt-in, HRex Consent)Same as provider-download, plus ExplanationOfBenefit floored to a 5-year service-date window

Denied PAs are not yet excluded, and a caller _typeFilter naming ExplanationOfBenefit is rejected with 400.

Financial filtering requires Aidbox's fhir.bulk-data.export.nested-elements setting. The Quickstart Docker Compose turns it on via BOX_FHIR_BULK_DATA_EXPORT_NESTED_ELEMENTS; see Aidbox nested _elements.

Example

POST /fhir/Group/<group-id>/$davinci-data-export
Content-Type: application/fhir+json
Prefer: respond-async

{
  "resourceType": "Parameters",
  "parameter": [
    {"name": "exportType", "valueCanonical": "hl7.fhir.us.davinci-pdex#payertopayer"},
    {"name": "_type",      "valueString":    "Patient,Coverage,ExplanationOfBenefit,Condition,Observation,MedicationRequest"},
    {"name": "_since",     "valueInstant":   "2021-01-01T00:00:00Z"}
  ]
}
HTTP/1.1 202 Accepted
Content-Location: <base>/fhir/$export-status/<job-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 400 Bad Request
Content-Type: application/fhir+json

Interop returns one of these diagnostics:

  • Request body must be a FHIR Parameters resource
  • Unsupported parameter(s): <name>
  • Parameter exportType is required
  • Parameter exportType must appear at most once
  • Parameter exportType must use valueCanonical
  • Unsupported exportType: <value>
  • _outputFormat must be application/fhir+ndjson, got: <value>
  • Caller-supplied _typeFilter on ExplanationOfBenefit is not supported
HTTP/1.1 401 Unauthorized
Content-Type: application/fhir+json

{
  "resourceType": "OperationOutcome",
  "issue": [{
    "severity": "error",
    "code": "login",
    "diagnostics": "payertopayer export requires the caller UDAP hl7-b2b organization_id claim; it is missing"
  }]
}
HTTP/1.1 404 Not Found
Content-Type: application/fhir+json

{
  "resourceType": "OperationOutcome",
  "id": "not-found",
  "issue": [{
    "severity": "fatal",
    "code": "not-found",
    "diagnostics": "Resource Group/<id> not found"
  }]
}

Status polling

Endpoint

GET <base>/fhir/$export-status/<job-id>

Served by Aidbox per the FHIR Bulk Data status spec. <job-id> is the id at the end of the Content-Location from kick-off.

Parameters

Job stateHTTPHeadersBody
in progress202X-Progress, Retry-After
completed200Content-Type: application/jsonBulk Data manifest
failed500BulkExportStatus resource carrying status="error" and an extension[BulkExportStatus.internal-error]
not found / expired404OperationOutcome

Example

GET /fhir/$export-status/<job-id>
HTTP/1.1 202 Accepted
X-Progress: in-progress
Retry-After: 30
HTTP/1.1 200 OK
Content-Type: application/json

{
  "transactionTime": "2026-05-15T13:40:00Z",
  "request": "<base>/fhir/Group/<group-id>/$export",
  "requiresAccessToken": true,
  "output": [
    {"type": "Patient",              "url": "<signed-url>/patient.ndjson"},
    {"type": "Coverage",             "url": "<signed-url>/coverage.ndjson"},
    {"type": "ExplanationOfBenefit", "url": "<signed-url>/eob.ndjson"}
  ],
  "error": [],
  "deleted": []
}
HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
  "resourceType": "BulkExportStatus",
  "id": "<job-id>",
  "status": "error",
  "request": "<base>/fhir/Group/<group-id>/$export",
  "extension": [{
    "url": "urn:url:extension:BulkExportStatus.internal-error",
    "valueString": "<reason>"
  }]
}

Output download

Endpoint

Each entry in the completed manifest's output[].url is a pre-signed URL pointing at the object-store bucket Aidbox is configured to use (S3, MinIO, etc.). Fetch them directly:

GET <output-url>
Authorization: Bearer <token>      # only if `requiresAccessToken: true`
Accept: application/fhir+ndjson

Each file is newline-delimited JSON — one FHIR resource per line. Stream-parse line by line.

Example

GET <signed-url>/patient.ndjson
Accept: application/fhir+ndjson
HTTP/1.1 200 OK
Content-Type: application/fhir+ndjson

Body (one resource per line):

{"resourceType":"Patient","id":"patient-1","name":[{"family":"Smith","given":["John"]}],"gender":"male","birthDate":"1970-05-15"}
{"resourceType":"Patient","id":"patient-2","name":[{"family":"Doe","given":["Jane"]}],"gender":"female","birthDate":"1985-03-12"}

Cancellation

Endpoint

DELETE <base>/fhir/$export-status/<job-id>

Served by Aidbox per the FHIR Bulk Data cancel spec. Returns 202 Accepted for a known job (running or terminal) and 404 for an unknown id.

Example

DELETE /fhir/$export-status/<job-id>
HTTP/1.1 202 Accepted

Errors

StatusWhereCause
400Kick-off (interop)Prefer: respond-async missing; body not Parameters; unsupported parameter; exportType missing, repeated, not valueCanonical, or unknown; _outputFormat not application/fhir+ndjson; caller _typeFilter naming ExplanationOfBenefit
401Kick-off (interop)payertopayer export whose access token carries no UDAP HL7 B2B organization_id claim; the opt-in gate fails closed
422Kick-off (interop)exportType is a recognized Da Vinci canonical this server does not yet translate; Group meta.profile incompatible with exportType; inactive Group
404Kick-off (Aidbox)Group/<id> not found
404Status / cancel (Aidbox)Unknown <job-id> or job expired
422Kick-off (Aidbox)Body fails BulkExportProfile validation (for example empty parameter[])
500Status (Aidbox)Background export failed; see BulkExportStatus.extension[BulkExportStatus.internal-error]

See the Provider Access and Payer-to-Payer pillars.

Last updated: