Skip to main content
FHIR supports sending multiple interactions in a single HTTP request by posting a Bundle to the server base URL. You choose the behavior with Bundle.type:
  • batch: entries are processed independently (partial success is expected)
  • transaction: all-or-nothing (atomic); either everything is applied or nothing is

The shape (what you send)

You POST a Bundle to the base endpoint:
POST /fhir
Content-Type: application/fhir+json
Each entry includes a request describing the interaction:
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:patient-1",
      "resource": { "resourceType": "Patient", "name": [{ "family": "Doe" }] },
      "request": { "method": "POST", "url": "Patient" }
    }
  ]
}
Important fields:
  • entry.request.method: GET, POST, PUT, PATCH, DELETE
  • entry.request.url: relative FHIR URL (e.g. Patient/123, Observation?code=...)
  • entry.resource: required for write interactions (POST, PUT, PATCH)
  • entry.fullUrl: optional, but very useful in transactions for intra-bundle references

Batch vs transaction (how it behaves)

Aspectbatchtransaction
Atomic❌ No✅ Yes
Partial success✅ Normal❌ No
Intra-bundle references (fullUrlReference.reference)⚠️ Not generally meaningful✅ Common pattern
Error reportingPer-entryWhole request fails
If any entry depends on another entry (e.g. create a Patient, then reference it), use a transaction.

The response (what you get back)

On success, servers return a response bundle where each entry.response contains the HTTP status and metadata for the corresponding request:
{
  "resourceType": "Bundle",
  "type": "transaction-response",
  "entry": [
    {
      "response": {
        "status": "201 Created",
        "location": "Patient/123/_history/1",
        "etag": "W/\"1\"",
        "lastModified": "2026-01-14T12:00:00Z"
      }
    }
  ]
}
If the server rejects the request, you typically get an OperationOutcome with a non-2xx HTTP status.

References inside a transaction

Transactions commonly use fullUrl values like urn:uuid:... so resources can reference each other before the server assigns real ids:
{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    {
      "fullUrl": "urn:uuid:patient-1",
      "resource": { "resourceType": "Patient", "name": [{ "family": "Doe" }] },
      "request": { "method": "POST", "url": "Patient" }
    },
    {
      "fullUrl": "urn:uuid:obs-1",
      "resource": {
        "resourceType": "Observation",
        "status": "final",
        "subject": { "reference": "urn:uuid:patient-1" }
      },
      "request": { "method": "POST", "url": "Observation" }
    }
  ]
}
The server resolves these references as part of processing the transaction.

Conditional logic (common patterns)

FHIR also supports conditional create/update/delete inside batch and transaction bundles via request metadata like If-None-Exist and conditional URLs. If you rely on conditional behavior, always verify support in the server’s CapabilityStatement (GET /fhir/metadata).

Next