# Batch.Execute D2C Operations
The batch.execute operation feature of the Device API allows a user to send one or more actions (combined in a single list), which are processed by the DCS in the supplied order.
# Idempotency
The batch.execute action is idempotent. Idempotency of the whole batch depends on idempotency of individual actions.
Sending several identical requests will result in the same individual actions (requested in the batch.execute body) being processed.
# Message Format
The batch.execute action provides a way to process existing D2C actions in a batch. All actions must be provided in the message body as an array and will be executed one-by-one in the same order as provided.
# Message Properties
Following are the application properties of the batch.execute action:
Property | Mandatory | Description |
---|---|---|
action | Yes | 'batch.execute' indicates that this is a batch action containing other actions to be processed |
timeout | No | If not provided, defaults to a 300 integer. Represents the parameter that will be used to indicate the maximum number of seconds available for processing of the D2C message until the timeout occurs. This excludes sending back response C2D messages. |
version | Yes | Integer. Must be equal to 2. |
failOnError | No | Boolean. Determines whether the entire batch will fail on an error. Defaults to 'false'. |
Properties common to each batch.execute message can be elevated using an "e_" prefix. The following properties can be elevated:
Property | Mandatory | Data Type | Description |
---|---|---|---|
e_timeout | No | String | The timeout is applied to individual batch.execute entries. |
e_action | No | String | If the batch contains only model.create, this can be elevated. |
e_correlationId | No | String | Either an elevated correlationId is used or individual correlationIds can be used. |
e_context | No | String | Either elevated context is used or inidividual action-level contexts can be used. |
Note that any action specific properties can be elevated with the "e" prefix, e.g. e_objectId, e_model, etc.
# Properties Handling in Spite of Elevation and Propagation
Header properties common to each individual action message may be elevated to the header properties of the batch.execute message by adding the e_ prefix to the actual property name. While processing, these properties should be copied to individual actions. Individual action payloads are always request-specific and cannot be elevated. Payload properties cannot be elevated.
Property destination
"Elevation name" in the table below refers to the destination in which the properties will appear, either on the batch level or on the action level inside the batch body, or both.
Elevation name | Can be elevated | Can be propagated to actions level | Description |
---|---|---|---|
BATCH_SCOPE | NO | YES - from batch level property itself | Property can only be defined on a batch level and must not be provided on a specific action level. Once provided, it will be copied to the individual action level. |
INDIVIDUAL_ACTION_SCOPE | YES - from actions level to e_<property_name> | YES - from e_<property_name> | Property can be defined on batch level and specific action level. Property defined on specific action level can be elevated to batch level. On batch level elevated property will use naming convention: e_<property_name>. Property on batch level (the non-elevated one) will never be copied to action level. It means that scope of batch level property is only on batch level and scope of specific action level property (elevated or not) is only on actions level. |
Property | Elevation |
---|---|
iothub-connection-device-id | BATCH_SCOPE |
msgType | BATCH_SCOPE |
version | BATCH_SCOPE |
ack | BATCH_SCOPE |
target | BATCH_SCOPE |
failOnError | BATCH_SCOPE |
action | INDIVIDUAL_ACTION_SCOPE |
correlationId | INDIVIDUAL_ACTION_SCOPE |
timeout | INDIVIDUAL_ACTION_SCOPE |
context | INDIVIDUAL_ACTION_SCOPE |
any other | INDIVIDUAL_ACTION_SCOPE |
# Examples of Using Properties
# BATCH_SCOPE
Here is a valid example:
{
"properties":
{
"iothub-connection-device-id": "<authenticated device id>", //BATCH_SCOPE property
"msgType": "action", //BATCH_SCOPE property
"version": 2, //BATCH_SCOPE property
"ack": "<ack>", //BATCH_SCOPE property
"failOnError": "<true/false>", //BATCH_SCOPE property
"target": "<connectivity path>", //BATCH_SCOPE property
"timeout": "<timeout in seconds>",
"action": "batch.execute",
"correlationId": "<correlation id>"
},
"body":
[
{
"action": "model.delete",
"model": "model"
}
{
"action": "model.delete",
"model": "abb.ability.device"
}
]
}
Invalid example:
The following example is invalid because "msgType" is of type BATCH_SCOPE which means it can only be specified on the batch level (in batch action header properties). It must not be specified on the action level.
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>'",
"msgType": "action",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"ack": "<ack>",
"failOnError": "<true/false>",
"timeout": "<timeout in seconds>",
"target": "<connectivity path>"
},
"body":
[
{
"action": "model.delete",
"msgType": "action", //BATCH_SCOPE property on the action level
"model": "model"
}
{
"action": "model.delete",
"model": "abb.ability.device"
},
]
}
# INDIVIDUAL_ACTION_SCOPE
Valid example 1:
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>",
"msgType": "action",
"action": "batch.execute", //action for batch
"correlationId": "<correlation id>", //correlationId for batch
"timeout": "<timeout in seconds>", //timeout for batch
"version": 2,
"ack": "<ack>",
"failOnError": "<true/false>",
"target": "<connectivity path>"
},
"body":
[
{
"action": "model.delete", //individual action
"correlationId": "<correlation id>", //correlationId for action
"timeout": "<timeout in seconds>", //timeout for action
"model": "model"
},
{
"action": "model.delete", //individual action
"correlationId": "<correlation id>", //correlationId for action
"timeout": "<timeout in seconds>", //timeout for action
"model": "abb.ability.device"
},
]
}
Valid example 2:
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>",
"msgType": "action",
"action": "batch.execute", //action for batch
"correlationId": "<correlation id>", //correlationId for batch
"timeout": "<timeout in seconds>", //timeout for batch
"version": 2,
"ack": "<ack>",
"failOnError": "<true/false>",
"target": "<connectivity path>",
"e_action": "model.delete", // elevated action for all actions
"e_correlationId": "<correlation id>", // elevated correlationId for all actions
"e_timeout": "<timeout in seconds>", // elevated timeout for all actions
},
"body":
[
{
"model": "model"
},
{
"model": "abb.ability.device"
},
]
}
Invalid example 1:
The following example is invalid because the prefix "e_" should not be used on the action level. It can be used only on the batch level (in header properties).
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>",
"msgType": "action",
"action": "batch.execute",
"correlationId": "<correlation id>",
"timeout": "<timeout in seconds>",
"version": 2,
"ack": "<ack>",
"failOnError": "<true/false>",
"target": "<connectivity path>"
},
"body":
[
{
"action": "model.delete",
"correlationId": "<correlation id>",
"timeout": "<timeout in seconds>",
"model": "model"
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"e_timeout": "<timeout in seconds>", //elevated property with prefix 'e_' on action level
"model": "abb.ability.device"
},
]
}
Invalid example 2:
The following example is invalid because you cannot have an "e_timeout" header property on a batch level and "timeout" properties on the action level simultaneously. They are mutually exclusive.
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>",
"msgType": "action",
"action": "batch.execute",
"correlationId": "<correlation id>",
"timeout": "<timeout in seconds>",
"version": 2,
"ack": "<ack>",
"failOnError": "<true/false>",
"target": "<connectivity path>",
"e_timeout": "<timeout in seconds>", //timeout property exists on action level
},
"body":
[
{
"action": "model.delete",
"correlationId": "<correlation id>",
"timeout": "<timeout in seconds>",
"model": "model"
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"timeout": "<timeout in seconds>", //timeout property exists on action level
"model": "abb.ability.device"
},
]
}
# Message Body
The message should be composed of a well-formed JSON array. Each item must be compliant to the request body format of the specific message type.
Here is a general example message:
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>",
"msgType": "action",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"ack": "<ack>",
"failOnError": "<true/false>",
"timeout": "<timeout in seconds>",
"target": "<connectivity path>",
"e_timeout": "<timeout in seconds>", //example elevated property
"e_objectId": "<object ID>" //example elevated property
},
"body":
[
{
"action": "model.delete", //required, action for this request
"model": "model" //request specific property
},
{
"action": "model.create", //required, action for this request
"model": "custom", //request specific property
"body": { //request specific body
"type": "myType@1",
"properties": {
"property": "value"
}
}
},
{
"action": "model.delete", //required, action for this request
"model": "abb.ability.device" //request specific property
},
]
}
Example of a batch.execute action as received by the batch.execute Device API endpoint:
{
"properties": {
"iothub-connection-device-id": "<authenticated device id>", //'BATCH_SCOPE' property
"msgType": "action", //'BATCH_SCOPE' property
"version": 2, //'BATCH_SCOPE' property
"ack": "<ack>", //'BATCH_SCOPE' property
"failOnError": "<true/false>", //'BATCH_SCOPE' property
"target": "<connectivity path>", //'BATCH_SCOPE' property
"timeout": "<timeout in seconds>",
"action": "batch.execute",
"correlationId": "<correlation id>",
"e_timeout": "<timeout in seconds>", //elevated property 'INDIVIDUAL_ACTION_SCOPE'
"e_objectId": "<object ID>" //elevated property 'INDIVIDUAL_ACTION_SCOPE '
},
"body":
[
{
"action": "model.delete",
"model": "model"
},
{
"action": "model.create",
"model": "custom",
"body": {
"type": "myType@1",
"properties": {
"property": "value"
}
}
}
]
}
The following two actions will be generated from the batch:
{
"iothub-connection-device-id": "<authenticated device id>", //'BATCH_SCOPE' property copied from batch header
"msgType": "action", //'BATCH_SCOPE' property copied from batch header
"version": 2, //'BATCH_SCOPE' property copied from batch header
"ack": "<ack>", //'BATCH_SCOPE' property copied from batch header
"failOnError": "<true/false>", //'BATCH_SCOPE' property copied from batch header
"target": "<connectivity path>", //'BATCH_SCOPE' property copied from batch header
"action": "model.delete",
"model": "model",
"timeout": "<timeout in seconds>", //elevated property copied from batch header and from e_timeout
"objectId": "<object ID>" //elevated property copied from batch header and from e_objectId
}
{
"iothub-connection-device-id": "<authenticated device id>", //'BATCH_SCOPE' property copied from batch header
"msgTyp": "action", //'BATCH_SCOPE' property copied from batch header
"version": 2, //'BATCH_SCOPE' property copied from batch header
"ack": "<ack>", //'BATCH_SCOPE' property copied from batch header
"failOnError": "<true/false>", //'BATCH_SCOPE' property copied from batch header
"target": "<connectivity path>", //'BATCH_SCOPE' property copied from batch header
"action": "model.create",
"model": "custom",
"timeout": "<timeout in seconds>", //elevated property copied from batch header and from e_timeout
"objectId": "<object ID>", //elevated property copied from batch header and from e_objectId
"body": {
"type": "myType@1",
"properties": {
"property": "value"
}
}
}
# Validation Rules
The Validation rules applies to the batch.execute action itself. Validation rules for individual actions inside the batch are executed one-by-one afterwards.
# Functionality
Actions that can be batched are all Device API v2 actions except:
- type.query
- extension.get
- batch.execute
If any prohibited action is detected in the body array or in the header as an elevated property, an platform_event_validation_error code is returned with a detailed description.
Validate message properties according to the rules described in Properties Handling in Spite of Elevation and Propagation. If validation fails, a platform_event_validation_error is returned with a detailed description.
If validation fails, (platform_event_validation_error on the batch level), the acks property will not be included in the acknowledgement.
# Processing Rules
The following processing rules apply:
As authorization is only applicable to individual actions, there is no authorization for the batch.execute action.
Elevated properties are copied to individual actions according to the following rules:
Elevated properties are copied into action properties only if the elevated property is specifically defined in action properties.
Elevated properties are not copied into a specific action body (e.g. objectId in model.create is in the action body not in action properties so it shouldn't be copied).
For each message in the batch, action type specific processing is performed:
- If message processing is a success, continue to the next message.
If a message fails, and failOnError is set to 'true', remaining requests are discarded and the batch.execute action is rejected. Remaining requests are marked as failed with a skipped error code in the 'ack' message. A failure acknowledgment is sent back to the device (if requested) with the new batch_operation_error error code with the details "One of the batch actions failed to process. Following actions were skipped." The success payload property of the overall batch acknowledgement is set to 'false' as soon as at least one batch request results in "success":false.
If failOnError is omitted or set to 'false', remaining requests will be processed. C2D messages generated by each action are sent immediately. Upon completion, a success acknowledgment is sent back to the device (if requested). The success payload property of the overall batch.execute acknowledgement is set to 'true' unless there is an error with the batch.execute message itself (e.g., validation error). An individual unsuccessful request will not cause the overall batch.execute to fail.
# Acknowledgement C2D Message
An acknowledgement in Device API v2 format will be sent as follows, depending on the requested ack value:
for ack:all - successful acknowledgement will contain individual actions acknowledgements
for ack:none - nothing is sent back
for ack:positive - nothing is sent back, and processing of the batch.execute action stops
for ack:negative - unsuccessful acknowledgement with error code platform_event_validation_error will be sent back, along with the following description:
"To send back result in an acknowledgement, ack: all needs to be used. To not send back an acknowledgement, ack: none needs to be used. Other values are not supported."
The general format of a Device API v2 acknowledgement message is described in the Device API input document.
CorrelationId and target are reused from the input action.
# Description of Body Properties
Property | Mandatory | Data Type | Description |
---|---|---|---|
number | Mandatory | Integer | Acknowledgement message number, starting with 1. Each batch.execute results in one or more acknowledgements (depending on the number of individual actions inside the batch.execute request), each with an incremental number used to deduplicate and order. |
total | Mandatory | Integer | Total number of acknowledgements for the batch.execute operation, cannot exceed 10. Requests resulting in more than 10 events will fail with a response_too_large error response. |
acks | Mandatory | Array | Actual acknowledgments for each action inside the batch.execute operation. Each of the objects in the array contains a correlationId, action, and the body of the acknowledgment for a given action. |
# Fragmentation of Acknowledgements
A First Fit Algorithm is used to fragment acknowledgements.
The size of the single 'ack' cannot exceed 64800 bytes, otherwise the request will fail with a response_too_large error response.
The total number of acknowledgements for the batch.execute operation cannot exceed 10. Requests resulting in more than 10 events will fail with a response_too_large error response.
# Format of Acknowledgements
# Format of Successful Acknowledgement (ack:all, failOnError:false)
In the following example, there were three actions sent in the batch. The first was successful, the second failed, and the third was successful.
{
"properties": {
"msgType": "ack",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"target": "<target matches the target in the corresponding action>",
"timestamp": "<YYYY-MM-DDTHH:mm:ss.sssZ>"
},
"body": {
"success": true,
"code": "ok",
"details": "''",
"number": "<number>",
"total": "<total>",
"acks": [
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>"
}
},
{
"action": "model.create",
"correlationId": "<correlation id>",
"body": {
"success": false,
"code": "error code",
"details": "error details",
"relatedModels": [ //for each related model
{
"model": "<model definition>",
"success": "true/false",
"code": "<error code>",
"details": "<error detail>"
}
]
}
},
{
"action": "model.update",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>",
"version": "<version>"
}
}
]
}
}
# Format of Successful Acknowledgement (ack:all, failOnError:true/false)
In the following example, there were three actions sent in the batch.execute action. All were successfully executed.
{
"properties": {
"msgType": "ack",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"target": "<target matches the target in the corresponding action>",
"timestamp": "<YYYY-MM-DDTHH:mm:ss.sssZ>"
},
"body": {
"success": true
"code": "ok",
"details": "''",
"number": "<number>",
"total": "<total>",
"acks":
[
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>"
}
},
{
"action": "model.create",
"correlationId": "<correlation id>",
"body": {
"success":true
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"relatedModels": [ //for each related model
{
"model": "<model definition>",
"success": true,
"code": "batch_operation_error",
"details": "<error detail>"
}
]
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>"
}
}
]
}
}
# Format of Failing Acknowledgement (ack:all, failOnError:true/false)
In the following example, there were three actions sent in the batch.execute action. None of them were processed due to a validation error on the batch level. In this case, a simple acknowledgement was sent back (consistent with all other Device API v2 acknowledgements).
{
"properties": {
"msgType": "ack",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"target": "<target matches the target in the corresponding action>",
"timestamp": "<YYYY-MM-DDTHH:mm:ss.sssZ>"
},
"body": {
"success": false
"code": "platform_event_validation_error",
"details": "error details"
}
}
# Format of Failing Acknowledgement
Example 1: (ack:all, failOnError:true)
In the following example, there were three actions sent in the batch.execute action. The first was successful, the second failed, and the third was skipped due to the failOnError value.
{
"properties": {
"msgType": "ack",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"target": "<target matches the target in the corresponding action>",
"timestamp": "<YYYY-MM-DDTHH:mm:ss.sssZ>"
},
"body": {
"success": false,
"code": "batch_operation_error",
"details": "error details",
"number": "<number>",
"total": "<total>",
"acks": [
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>"
}
},
{
"action": "model.create",
"correlationId": "<correlation id>",
"body": {
"success": false,
"code": "error code",
"details": "error details",
"relatedModels": [ //for each related model
{
"model": "<model definition>",
"success": "true/false",
"code": "<error code>",
"details": "<error detail>"
}
]
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": false,
"code": "skipped",
"details": "<error details>"
}
}
]
}
}
Example 2: (ack:all, failOnError:false)
In the following example, as in Example 1, there were three actions sent in the batch.execute action. Here however, the failOnError value is set to false. As a result, the first was successful, the second failed, and the third was successful (with success property = true). Note also that the success property on the whole batch.execute is set to true.
{
"properties": {
"msgType": "ack",
"action": "batch.execute",
"version": 2,
"correlationId": "<correlation id>",
"target": "<target matches the target in the corresponding action>",
"timestamp": "<YYYY-MM-DDTHH:mm:ss.sssZ>"
},
"body": {
"success": true,
"code": "ok",
"details": "''",
"number": "<number>",
"total": "<total>",
"acks": [
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''",
"objectId": "<objectId>",
"model": "<model>"
}
},
{
"action": "model.create",
"correlationId": "<correlation id>",
"body": {
"success": false,
"code": "error code",
"details": "error details",
"relatedModels": [ //for each related model
{
"model": "<model definition>",
"success": "true/false",
"code": "<error code>",
"details": "<error detail>"
}
]
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"body": {
"success": true,
"code": "ok",
"details": "''"
}
}
]
}
}
# Context header in Batch messages
Batch, like any other message, may use context property. Below, you can find examples of using context on batch level and individual actions level (elevated and not elevated)
# Context usage on batch level and individual actions level (not elevated)
In this example there is one context
property for the whole batch action and
separate context
properties for individual batched actions. Both will be
preserved in the acknowledgement from the cloud. Notice that the second "child"
action does not specify any context. The functionality is optional, and context
should be used only when your device implementation requires that.
Example Message
Message properties (batch-level context
is present):
|-------------------------------|----------------------------------------|
| Key | Value |
|-------------------------------|----------------------------------------|
| "iothub-connection-device-id" | "0d4e1778-ff46-4880-b540-0124141b32da" |
| "msgType" | "action" |
| "action" | "batch" |
| "version" | 2 |
| "correlationId" | "5e9d709b-440d-4296-8902-b81bfae3dd3b" |
| "failOnError" | "true/false" |
| "ack" | "all" |
| "context" | "user data 123" |
|-------------------------------|----------------------------------------|
Body (two of the messages have their own context
):
[
{
"action": "model.delete",
"model": "model",
"context": "user data 456"
},
{
"action": "model.delete",
"model": "abb.ability.device"
},
{
"action": "model.delete",
"model": "abb.ability.device",
"context": "user data 789"
},
...
]
Example Successful Acknowledgement
Message properties (batch-level context
is returned):
|-------------------------------|----------------------------------------|
| Key | Value |
|-------------------------------|----------------------------------------|
| "msgType" | "ack" |
| "action" | "batch" |
| "version" | 2 |
| "correlationId" | "5e9d709b-440d-4296-8902-b81bfae3dd3b" |
| "timestamp" | "<YYYY-MM-DDTHH:mm:ss.sssZ>" |
| "target" | "" |
| "context" | "user data 123" |
|-------------------------------|----------------------------------------|
Body (messages that had context
included in the request, also have it in their responses):
{
"success": true,
"code": "ok",
"details": "",
"number": 1,
"total": 1,
"acks": [
{
"action": "model.delete",
"correlationId": "<correlation id>",
"context": "user data 456"
"body": {
"success": true,
"code": "ok",
"details": "",
"objectId": "<objectId>",
"model": "model"
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>"
"body": {
"success": true,
"code": "ok",
"details": "",
"objectId": "<objectId>",
"model": "abb.ability.device"
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"context": "user data 789"
"body": {
"success": true,
"code": "ok",
"details": "",
"objectId": "<objectId>",
"model": "abb.ability.device"
}
}
]
}
# Context usage on batch level and individual actions level (elevated)
In cases where you want all "child" actions to have the same context in a batch,
you may use the e_context
property. It should be specified on the batch action
level. Responses for all of the batched actions will include the context with
the value taken from e_context
that you set in your request.
Example Message
Message properties:
|-------------------------------|----------------------------------------|
| Key | Value |
|-------------------------------|----------------------------------------|
| "iothub-connection-device-id" | "0d4e1778-ff46-4880-b540-0124141b32da" |
| "msgType" | "action" |
| "action" | "batch.execute" |
| "version" | 2 |
| "correlationId" | "5e9d709b-440d-4296-8902-b81bfae3dd3b" |
| "failOnError" | "true/false" |
| "ack" | "all" |
| "context" | "user data 123" |
| "e_context" | "user data 456" |
|-------------------------------|----------------------------------------|
Body - since e_context
is set, individual contexts are not specified (and
shouldn't be, or an error -
platform_event_validation_error - will be returned):
[
{
"action": "model.delete",
"model": "model"
}
{
"action": "model.delete",
"model": "abb.ability.device"
},
...
]
Example Successful Acknowledgement
Message properties (the context
that we sent in the request is also returned):
|-------------------------------|----------------------------------------|
| Key | Value |
|-------------------------------|----------------------------------------|
| "msgType" | "ack" |
| "action" | "batch.execute" |
| "version" | 2 |
| "correlationId" | "5e9d709b-440d-4296-8902-b81bfae3dd3b" |
| "timestamp" | "<YYYY-MM-DDTHH:mm:ss.sssZ>" |
| "target" | "" |
| "context" | "user data 123" |
|-------------------------------|----------------------------------------|
Body (the e_context
value is available at each individual response message):
{
"success": true,
"code": "ok",
"details": "",
"number": 1,
"total": 1,
"acks": [
{
"action": "model.delete",
"correlationId": "<correlation id>",
"context": "user data 456",
"body": {
"success": true,
"code": "ok",
"details": "",
"objectId": "<objectId>",
"model": "model"
}
},
{
"action": "model.delete",
"correlationId": "<correlation id>",
"context": "user data 456",
"body": {
"success": true,
"code": "ok",
"details": "",
"objectId": "<objectId>",
"model": "abb.ability.device"
}
}
]
}
# Error Handling
When an error occurs:
Error information is logged inside platform (in Application Insights).
If a response can be delivered to a device, an acknowledgment will be sent, if requested. For more, see Acknowledgement Handling.
If a response cannot be sent back to a device, the message will be completed and only the error logged.