Using the Bundle API
Combine multiple individual operations on Resources and Relationships into a single atomic action.
The Bundle API enables grouping multiple Resource and Relationship operations into a single Bundle Request, ensuring that all operations within the bundle are executed atomically. This makes it particularly well-suited for scenarios requiring transactional integrity across multiple Resources and Relationships.
Unlike the Bulk API, where operations are processed independently for records OR relationships, the Bundle API ensures all-or-nothing behaviour for all the operations within the same Bundle Request. If any operation in the bundle fails, the entire set of operations is cancelled.
Sending a Bundle Request
A Bundle Request comprises a collection of Resource operations and Relationship operations.
{
"resourceOperations": [
{
"action": "CREATE",
"create": {
// Type, ID, Data, Contained and Meta
}
},
{
"action": "UPSERT",
"upsert": {
// ...
}
},
{
"action": "DELETE",
"delete": {
// ...
}
}
],
"relationshipOperations": [
{
"action": "CREATE",
"create": {
// Type, ID, Data, Contained and Meta
}
},
{
"action": "UPSERT",
"upsert": {
// ...
}
},
{
"action": "DELETE",
"delete": {
// ...
}
}
]
}
Notes
- Only one operation per Resource and Relationship ID is allowed to prevent unexpected behavior (e.g., you cannot both
DELETE
andUPSERT
the same resource in the same bundle).- Resource operations are processed before Relationship operations. This enables Relationship operations to reference Resource operations in the same bundle.
- For more information on the specification, refer to the the API specification.
Example Use Case
Suppose you need to create an office
, provider
, and establish Relationships between them based on predefined profiles and relationship definitions. Using the Bundle API, this can be done in a single request:
{
"resourceOperations": [
{
"action": "UPSERT",
"upsert": {
"id": "1",
"type": "office",
"data": {
"name": "Clinic Name"
}
}
},
{
"action": "UPSERT",
"upsert": {
"id": "2",
"type": "provider",
"data": {
"name": "John Doe"
}
}
}
],
"relationshipOperations": [
{
"action": "UPSERT",
"upsert": {
"type": "provider-office",
"from": {
"id": "1",
"type": "office"
},
"to": {
"id": "2",
"type": "provider"
},
"data": {
"description": "Works at"
}
}
}
]
}
Bundle Response
Successful Bundle
When all operations in the bundle are valid, they are executed as a single, atomic transaction. The system ensures all operations are successfully completed and provides operation receipts with a
SUCCESS
status for each operation:{ "resourceOperationReceipts": [ { "id": "1", "receivedAt": "2024-11-27T15:43:09.438665Z", "status": "SUCCESS", "type": "office" }, { "id": "2", "receivedAt": "2024-11-27T15:43:09.438665Z", "status": "SUCCESS", "type": "provider" } ], "relationshipOperationReceipts": [ { "id": "office.1,provider.2", "receivedAt": "2024-11-27T15:43:09.444574Z", "status": "SUCCESS", "type": "provider-office" } ] }
Failed Bundle
If any operation in the bundle results in a
FAILURE
status, all other operations in the bundle are automaticallyCANCELLED
maintaining the atomicity of the bundle. By reviewing the returned operation receipts, you may identify the errors that led to the failure:{ "resourceOperationReceipts": [ { "error": { "code": 400, "details": [ { "code": 400, "message": "additionalProperties 'UNKNOWN' not allowed", "type": "INVALID_ARGUMENT" } ], "message": "invalid schema for office", "type": "FAILED_PRECONDITION" }, "id": "1", "receivedAt": "2024-11-27T15:46:18.022606Z", "status": "FAILURE", "type": "office" }, { "id": "2", "receivedAt": "2024-11-27T15:46:18.022606Z", "status": "CANCELLED", "type": "provider" } ], "relationshipOperationReceipts": [ { "id": "office.1,provider.2", "receivedAt": "2024-11-27T15:46:18.030244Z", "status": "CANCELLED", "type": "provider-office" } ] }
Advanced Feature: Virtual IDs
Virtual IDs act as placeholders, enabling the system to automatically generate actual Resource IDs during the execution of a Bundle Request.
Notes
- Virtual IDs follow the pattern
"@rootId"
followed by an integer (e.g.,"@rootId1"
,"@rootId2"
, etc.).- Virtual IDs can be used for
CREATE
operations only.
Example Request:
{
"resourceOperations": [
{
"action": "CREATE",
"create": {
"id": "@rootId1", // Virtual ID #1
"type": "office",
"data": {
"name": "Clinic Name"
}
}
},
{
"action": "CREATE",
"create": {
"id": "@rootId2", // Virtual ID #2
"type": "provider",
"data": {
"name": "John Doe"
}
}
}
],
"relationshipOperations": [
{
"action": "CREATE",
"create": {
"type": "provider-office",
"from": {
"id": "@rootId1", // Virtual ID #1
"type": "office"
},
"to": {
"id": "@rootId2", // Virtual ID #2
"type": "provider"
},
"data": {
"description": "Works at"
}
}
}
]
}
Example Response:
{
"resourceOperationReceipts": [
{
"id": "2pUv7EdiOrKlphAYBtTKF0TwCM9",
"receivedAt": "2024-11-28T22:34:58.94489Z",
"status": "SUCCESS",
"type": "office"
},
{
"id": "2pUv7AQvsnalGn8I4RsBdKID8OR",
"receivedAt": "2024-11-28T22:34:58.94489Z",
"status": "SUCCESS",
"type": "provider"
}
],
"relationshipOperationReceipts": [
{
"id": "office.2pUv7EdiOrKlphAYBtTKF0TwCM9,provider.2pUv7AQvsnalGn8I4RsBdKID8OR",
"receivedAt": "2024-11-28T22:34:58.948208Z",
"status": "SUCCESS",
"type": "provider-office"
}
]
}
Updated 5 months ago