Using OData transactional $batch requests

APPLIES TO: Business Central 2020 release wave 2 (version 17.1) and later

It's possible to specify that all inner requests in a certain OData $batch request are processed in a transactional way. Unless it's invoked commit, if an inner request fails after another request(s) has committed changes, all changes within a batch will be reverted as if the batch request never happened. Transactional $batch requests are useful in scenarios where a single business operation spans multiple requests, because they prevent adverse effects if parts of the operation fail. Also, they can improve performance by reducing the number of requests the client needs to do when errors occur.

Enable OData transactional batch behavior

To enable transactional batch behavior, include the Isolation: snapshot header with the $batch request. The Isolation: snapshot header makes the entire batch to run within the same session. If the AL code doesn't invoke COMMIT, then the entire batch runs in the same transaction. Otherwise, for each commit, the transaction is committed, and a new one is started.

The CommitBehavior attribute can be used to override the COMMIT behavior of the invoked method.

Example

POST businesscentralPrefix/api/v2.0/$batch HTTP/1.1

Request headers

Header Value
Authorization Bearer {token}. Required.
Content-Type application/json. Required for JSON Batch content.
Accept application/json
Isolation snapshot

Request body

The following request body contains three inner requests. The first two requests should execute successfully. The last request includes content that triggers a validation failure, so the request fails.

{
       "requests": [
              {
                     "method": "PATCH",
                     "url": "items(7ce0af2e-0963-460f-9b1f-0014aea3e117)",
                     "headers": {
                           "Company": "CRONUS International Ltd.",
                           "Content-Type": "application/json",
                           "If-Match": "*"
                     },
                     "body": {
                           "displayName": "Touring Bicycle v2"
                     }
              },
              {
                     "method": "PATCH",
                     "url": "items(7ce0af2e-0963-460f-9b1f-0014aea3e117)/picture(7ce0af2e-0963-460f-9b1f-0014aea3e117)/contentValue",
                     "headers": {
                           "Company": "CRONUS International Ltd.",
                           "Content-Type": "application/json",
                           "If-Match": "*"
                     },
                     "body": {
                           "value": "Picture Blob"
                     }
              },      
              {
                     "method": "PATCH",
                     "url": "items(7ce0af2e-0963-460f-9b1f-0014aea3e117)",
                     "headers": {
                           "Company": "CRONUS International Ltd.",
                           "Content-Type": "application/json",
                           "If-Match": "*"
                     },
                     "body": {
                           "type": "Invalid Type"
                     }
              }
       ]
}

Response

The following response includes successful responses for the first two inner requests, and an error for the last inner request. Because the Isolation: snapshot header was present in the batch request, none of the changes made by either of the successful inner requests are applied after completion of the batch request.

{
       "responses": [
              {
                     "id": null,
                     "status": 200,
                     "headers": {
                           "content-type": "application/json; odata.metadata=minimal",
                           "odata-version": "4.0"
                     },
                     "body": {
                           "displayName": "Touring Bicycle v2",
                           // ...
                     }
              },
              {
                     "id": null,
                     "status": 204,
                     "headers": {}
              },
              {
                     "id": null,
                     "status": 400,
                     "headers": {
                           "content-type": "application/json; odata.metadata=minimal",
                           "odata-version": "4.0"
                     },
                     "body": {
                           "error": {
                                  "code": "Unknown",
                                  "message": "'Invalid Type' is not an option. The existing options are: Inventory,Service,Non-Inventory  CorrelationId:  x."
                           }
                     }
              }
       ]
}

See Also

OData Web Services
Using OData to Return-Obtain a JSON Document