FHIR Bulk Data export security: one request, every patient, and where agents fit

Bulk Data export is the FHIR operation built for moving whole populations of records. That makes it the largest blast radius on a FHIR server. Here's how the flow works, what the spec requires, and an agent policy.

The short answer

FHIR Bulk Data $export is an asynchronous operation that exports large sets of FHIR resources as files: for all patients, for a group, or for the whole server.1 The implementation guide requires TLS 1.2 or later for all exchanges, recommends OAuth 2.0 access management under the SMART Backend Services profile, and, when that’s used, says status requests and output-file requests marked requiresAccessToken must be protected like the kick-off, with a token whose scopes cover all resources being exported.1

For AI agents, the policy is simple: an agent shouldn’t be able to start an export. If a workflow needs population data, a person or a scheduled job starts it with its own credentials, and the agent works on a narrow, approved extract.

This is about data access and records security, not clinical use of the data.

A FHIR server can accept a write and quietly drop a field. Deedglass reads the resource back and names what differs. Made-up resource.

The three export endpoints

Endpoint Exports1 Blast radius
[fhir base]/Patient/$export Resources of many types for all patients Every patient on the server
[fhir base]/Group/[id]/$export Resources for all members of a Group Every member of that group
[fhir base]/$export Data from the server whether or not tied to a patient, e.g. for backups or terminology exports via _type The whole server

Parameters narrow it: _type limits resource types, _since returns only resources changed after a time, and _typeFilter applies FHIR search criteria per type.1 Narrowing helps, but the default for a system-level export is everything.

How the flow works

From the implementation guide:1

  1. Kick-off. The client calls an $export endpoint with Prefer: respond-async.
  2. Accepted. The server answers 202 Accepted with a Content-Location header: the polling URL.
  3. Poll. The client polls that URL until the export completes. The server may return a partial manifest with files that are ready, then update it.
  4. Download. The completion manifest lists output file URLs, in NDJSON; the client downloads them.
  5. Delete. The client may send DELETE to the polling URL to cancel, or, after completion, to signal it’s done so the server can remove the files; later polls then return 404.1

Two details matter for security. The output files are separate URLs, which may or may not require an access token. And the guide doesn’t set one approach for how long files stay available: it supports an Expires header and leaves removal to the server implementer, while saying servers shouldn’t delete files a client is actively downloading.1

What the spec requires for security

From the guide’s privacy and security considerations:1

Requirement Strength
TLS 1.2 or later on all exchanges SHALL
Mutual TLS OPTIONAL
OAuth 2.0 access management per SMART Backend Services SHOULD
With Backend Services: status and output-file requests with requiresAccessToken=true protected like the kick-off, with scopes covering all exported resources SHALL
Restricting status and file requests to the client that started the export MAY
Access control through in-band (OAuth scopes) and out-of-band restrictions Described as the way to meet obligations

Read the “MAY” row twice. Unless your server restricts status and file requests to the originating client, another client with a sufficiently scoped token may be able to reach them. Check how your server behaves.

Why agents and bulk export don’t mix

An agent with a Backend Services token that can call $export holds, in one tool call, the ability to copy every patient’s records to files. Three things make that worse than an ordinary read:

  • The scale is the operation’s purpose. A read tool returns one resource; an export returns the population.
  • The data leaves in files. Once downloaded, the files are outside the FHIR server’s access controls and audit trail.
  • It’s asynchronous. A kick-off, a poll and a download can be spread across steps, each looking harmless on its own.

That’s the lethal trifecta with the private-data leg turned up to its maximum. The blast radius of a confused or steered agent is everyone.

Questions to ask your FHIR vendor

Bulk Data behaviour varies by server. Before any agent goes near a server that supports $export, get answers to:

  1. Which clients can call $export, and with which scopes? You want a short, named list.
  2. Do output files require an access token? And is that token checked against the client that started the export?1
  3. How long do files live? Whether the server sets an Expires header, and when it removes files.1
  4. Is every kick-off, poll and file download logged with the client identity?
  5. Can a gateway rule block $export for some clients regardless of their scopes?

Write the answers down next to your agent’s access policy. They decide how bad the worst day could be.

An agent policy for bulk data

  1. No export scopes in agent tokens. Agents get SMART scopes for the resources and patients their task needs; our post on SMART on FHIR v2 scopes covers granular scopes. Export rights live with a separate backend client.
  2. Block the operation at the gateway. A rule that refuses any agent request whose path ends in $export, regardless of scopes, is cheap insurance.
  3. Exports started by people or schedules, with _type and _since set to the minimum, and files deleted after use with the DELETE request.1
  4. Agents work on extracts. If an analysis needs population data, give the agent a de-identified, approved extract, not the export pipeline.
  5. Restrict file access to the originating client, where your server supports it.1
  6. Log every kick-off with the client, parameters and file count.

A checklist

  • TLS 1.2 or later on every Bulk Data exchange.
  • SMART Backend Services for export clients, with scopes limited to what each export needs.
  • Output files require access tokens and expire.
  • File and status requests restricted to the originating client where possible.
  • No agent token can start an export; a gateway rule blocks $export from agents.
  • Exports deleted after download.
  • Every export logged and reviewed.

For agent writes on FHIR servers, see AI agents writing to patient records; for the basics, the FHIR glossary entry. To see what the agents configured on your machine could reach, paste the config into the check page or run npx deedglass scan (how the grade works); to try tool-call rules in your browser, open the playground.

Written with AI assistance and checked against our claims register.

The takeaway

One FHIR $export kick-off can return every patient's resources as files. The spec requires TLS 1.2+ and scoped tokens for files; keep agents off it.

Read nextSMART on FHIR v2 scopes: how to give an AI agent only the access it needs Try it: install in 7 s

Related on this site

More posts

Sources

  1. 1HL7 FHIR Bulk Data Access IG v3.0.0: Export · hl7.org · checked 26 October 2026

Published 26 October 2026, sources last checked 26 October 2026. If something here is out of date, write to hello@deedglass.com.

Try it on your own setup

npx deedglass scan

Grades only your own setup. Nothing is uploaded.

Pricing