FHIR Bulk Data export produces large files of patient data on request. Protect every step with the same access token rules, set an expiry on files, and plan deletion yourself, because the specification leaves removal to the implementer. Here is how the flow works and what to lock down.
How the flow works
The consumer sends a kick-off request. The spec says it should include a Prefer header with the value respond-async, so processing is asynchronous. The provider replies with a Content-Location header holding a status URL. The consumer polls that URL. When the job completes, the response lists files to download, and the provider should return an Expires header saying when they will stop being available.
Export can be system level, covering all data, or patient level, and filters such as the _type and _since parameters narrow what comes back. The spec notes that a system level export supports uses like backing up a server.
One quirk: an export can partly succeed. Resources that fail are described in OperationOutcome files, and the provider uses a 200 status for partial success. Consumers must read those outcome files and not assume completeness.
This post uses the HL7 bulk data project source text, which is the working draft, so check the published version for your server. The published guide at the time of writing is version 3.0.0.
Authorization
The spec says the provider should implement OAuth 2.0 using the SMART Backend Services profile. When it does, status requests and file download requests that require a token must be protected the same way as the kick-off request, with a token whose scopes cover all resources being exported. A provider may also limit status and download requests to the consumer that started the export. Other schemes, such as mutual TLS or signed URLs, are permitted.
See SMART Backend Services for how the token is obtained.
Files at rest are the risk
The spec says healthcare organizations must protect PHI stored in file servers, in cloud and in data centers, and that the specification does not dictate how. It supports the Expires header to limit the download window. Removal of the file is left to the implementer. A provider should not delete files a consumer is actively downloading, whatever the expiry.
That gap is where incidents happen. A bucket of NDJSON exports that nobody deletes is a standing breach waiting for a misconfiguration.
Provider checklist
- Require a token with scopes for every resource in the export, on all three request types.
- Bind status and download access to the originating client where you can.
- Set a short Expires value and enforce deletion with a scheduled job.
- Encrypt storage and restrict who can list the export location.
- Log kick-off, status and download events, and review them. See AuditEvent vs Provenance.
- Publish an accurate CapabilityStatement so consumers know what you support.
- Test with a partial failure so you know consumers read the outcome files.
Consumer checklist
- Keep the signing key out of source control.
- Delete downloaded files once loaded, and track the transaction time you received.
- Do not send tokens to download hosts you were not told to use.
Quick check
Who deletes the export files?
The spec leaves removal to the data provider. It supports an Expires header to signal availability, but you must build the deletion.
Sources
- HL7 Bulk Data Access source: export specification text
- HL7 FHIR Bulk Data Access implementation guide
Last reviewed: 19 October 2026.