$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
ExplanationOfBenefitandCoverage - Drug claims and drug PAs dropped
- 5-year
ExplanationOfBenefitservice-datewindow forpayertopayer
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. | Parameter | Type | Card. | Description |
|---|---|---|---|---|
| IN | exportType | canonical (valueCanonical) | 0..1 | Selects 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 | _since | instant (valueInstant) | 0..1 | Only resources updated since this time. |
| IN | _until | instant (valueInstant) | 0..1 | Only resources updated up to this time. |
| IN | _type | string (valueString) | 0..1 | Comma-separated FHIR resource types to include (e.g. Patient,Coverage,ExplanationOfBenefit). |
| IN | _typeFilter | string (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 | _outputFormat | string (valueString) | 0..1 | Output format. application/fhir+ndjson is the default and only value supported in PDex 2.1.0. |
| IN | patient | reference (valueReference) | 0..* | Narrow the export to specific Patients. |
| OUT | — | — | — | 202 Accepted with Content-Location pointing at the Aidbox status URL. |
exportType values
| Value | Used by | Consent rule | Data scope |
|---|---|---|---|
hl7.fhir.us.davinci-pdex#provider-download | Provider Access | Member 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#payertopayer | Payer-to-Payer | Active 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 resourceUnsupported parameter(s): <name>Parameter exportType is requiredParameter exportType must appear at most onceParameter exportType must use valueCanonicalUnsupported 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 state | HTTP | Headers | Body |
|---|---|---|---|
| in progress | 202 | X-Progress, Retry-After | — |
| completed | 200 | Content-Type: application/json | Bulk Data manifest |
| failed | 500 | — | BulkExportStatus resource carrying status="error" and an extension[BulkExportStatus.internal-error] |
| not found / expired | 404 | — | OperationOutcome |
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
| Status | Where | Cause |
|---|---|---|
| 400 | Kick-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 |
| 401 | Kick-off (interop) | payertopayer export whose access token carries no UDAP HL7 B2B organization_id claim; the opt-in gate fails closed |
| 422 | Kick-off (interop) | exportType is a recognized Da Vinci canonical this server does not yet translate; Group meta.profile incompatible with exportType; inactive Group |
| 404 | Kick-off (Aidbox) | Group/<id> not found |
| 404 | Status / cancel (Aidbox) | Unknown <job-id> or job expired |
| 422 | Kick-off (Aidbox) | Body fails BulkExportProfile validation (for example empty parameter[]) |
| 500 | Status (Aidbox) | Background export failed; see BulkExportStatus.extension[BulkExportStatus.internal-error] |
See the Provider Access and Payer-to-Payer pillars.