Skip to main content

transaction-bundles

Makes a Bundle of type transaction atomic: every entry is applied, or none is. Without the feature, the same request is accepted but runs as a batch.

TypeProject feature
Value in featurestransaction-bundles
Change withPATCH /v1/projects/me/features (replaces the whole list)
Who can change itProject admin. Any practitioner can read the list.
On for new projectsYes
When offA transaction Bundle runs as a batch: entries succeed or fail independently

What it does​

Send a Bundle whose type is transaction to the FHIR base:

curl --request POST \
--url 'https://api.sandbox.ovok.com/fhir/R4' \
--header "Authorization: Bearer ${OVOK_TOKEN}" \
--header 'Content-Type: application/fhir+json' \
--data @transaction-bundle.json

Example transaction-bundle.json. The Observation refers to the new Patient through a temporary urn:uuid id:

{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "urn:uuid:5b1f0c0e-6f43-4c55-9d1a-0a6c2f6d1a11",
"resource": { "resourceType": "Patient", "name": [{ "family": "Example" }] },
"request": { "method": "POST", "url": "Patient" }
},
{
"resource": {
"resourceType": "Observation",
"status": "final",
"code": { "coding": [{ "system": "http://loinc.org", "code": "8867-4" }] },
"subject": { "reference": "urn:uuid:5b1f0c0e-6f43-4c55-9d1a-0a6c2f6d1a11" },
"valueQuantity": { "value": 72, "unit": "beats/minute" }
},
"request": { "method": "POST", "url": "Observation" }
}
]
}

What you get back​

FeatureOutcome
On, all entries succeed200 with a transaction-response Bundle.
On, one entry failsThe whole request is rejected with an OperationOutcome and nothing is written. The HTTP status is the failing entry's own (for example 404 when an entry reads a resource that does not exist).
Off, all entries succeed200 with a transaction-response Bundle.
Off, one entry fails200 with a transaction-response Bundle. The other entries are still written; read each entry's response.status.

When the feature is on, expect these statuses for a rolled-back transaction: 412 when an entry's If-Match is stale, 409 when the database could not serialise concurrent writes, and 400 with a deadlock message when it detected a deadlock. Retry 409 and a deadlock 400; re-read before retrying 412.

Limits when it is on​

LimitResult
More than 50 update (PUT) entries400 Transaction contains more update operations than allowed
A conditional create (ifNoneExist), conditional update or conditional delete with more than 8 entries in the Bundle400 Transaction requires strict isolation but has too many entries
Prefer: respond-async on a transaction400 Transaction batches cannot be executed asynchronously

Split work that exceeds the limits into several transactions, and keep each one a single logical change.

Turn it on​

curl --request PATCH \
--url 'https://api.sandbox.ovok.com/v1/projects/me/features' \
--header "Authorization: Bearer ${OVOK_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{"features":["bots","cron","email","transaction-bundles","websocket-subscriptions"]}'

Gotchas​

  • Off is silent. With the feature off, a transaction Bundle still returns 200, and the response type is still transaction-response, so nothing in the response tells you it ran as a batch. A client that treats 200 as "everything was saved" can lose writes. Check transaction-bundles in the features list, and check each entry's response.status when you are not sure.
  • The flag is read from the project of the token that sends the Bundle, not from the project that owns the data.
  • Projects created before this was a default can lack it. Call GET /v1/projects/me/features and check.