# Receive automatic notifications from AXIS Body Worn Live to SOC

With an integration between your AXIS Body Worn Live organization and your security operating center (SOC), you can listen to different types of events from AXIS Body Worn Live.

## Event type schemas

### Stream started

```json
{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "http://bodyworn.axis.com/dash/stream/started/1.0.0.json",
  "title": "Stream started",
  "description": "Properties for a started dash stream",
  "type": "object",
  "required": ["systemId", "playlistId", "bearerId", "videoUrl", "metadata"],
  "properties": {
    "systemId": {
      "type": "string",
      "description": "Id of the body worn system"
    },
    "playlistId": {
      "type": "string",
      "description": "Id of the dash playlist"
    },
    "bearerId": {
      "type": "string",
      "description": "Id of the bearer recording the stream"
    },
    "metadata": {
      "type": "object",
      "description": "Metadata for the stream. Note that these properties may not always be present.",
      "properties": {
        "Tzoffset": {
          "type": "string",
          "description": "BWC local time offset from UTC in seconds"
        },
        "Encrypted": {
          "type": "string",
          "description": "If the stream segments are encrypted, <true|false>"
        },
        "Wearerid": {
          "type": "string",
          "description": "Id of wearer"
        },
        "Wearername": {
          "type": "string",
          "description": "Name of wearer"
        },
        "Triggertime": {
          "type": "string",
          "description": "Time when the stream was triggered, unix timestamp (micro second precision)"
        },
        "Starttime": {
          "type": "string",
          "description": "Time when stream starts, unix timestamp (micro second precision)"
        },
        "Wearershowid": {
          "type": "string",
          "description": "External identifier of wearer as configured in the body worn system"
        }
      }
    },
    "videoUrl": {
      "type": "string",
      "description": "URL to the playlist"
    }
  }
}
```



## Requirements

### Event

The event arrives as an HTTP POST request to the URL specified in the SOC integration. The events returned through Webhook adhere to the [CloudEvents](https://cloudevents.io/) specification. The `data` field is different for the different event types.

### Pre-flight check

To prevent abuse, CloudEvents requires that a validation handshake is made before an event is sent to a consumer. If the consumer doesn’t reply appropriately during the handshake, the subscription won’t be created.

To accept all issuers of Webhook events in your consumer, answer the HTTP OPTIONS request with 200 OK and the following header: `Webhook-Allowed-Origin: '*'`. 

### Payload signature

When you create a Webhook subscription, you can also configure a secret payload signature to sign the event payload. This is used to verify the integrity of the payload.

##### 2. Verify signature

Each request sent to your callback URL can contain a header called `WebHook-Signature-SHA256`.
The value of this header is a HMAC SHA256 digest, encoded as hex, of the event payload signed with the key provided in the `createWebhookEventSubscription` mutation.

To verify the request:

1. Use your key to compute a HMAC SHA256 digest from the event payload, that is, the request body.
2. Compare* the result of your signature with the one received in the header.

\* To compare the values you must encode your signature to hex.

##### Python example

```python
import secrets
import hmac
import hashlib
import json


# Request data
##############

signature_header = "f4b42c9f59441dc31e5218346b1d97c3799f9e7c265e53c8b7415ac3e4c1d761"
event_data = {
    "specversion": "1.0",
    "eventversion": "1",
    "id": "a6214c31-6e16-4e02-a062-d39a4d0201da",
    "eventcorrelationid": "67543333-3653-44e9-ad92-6a9048701e78",
    "type": "com.axis.connect.onboarding.started",
    "arn": "arn:device:ea5a8fec-a42d-41b9-9c97-e49e7eab0b8a/56bfe68d-7df1-4dc9-adfe-e4479217ed19/c46e66e7-c42d-49fc-b008-42085e2e919d",
    "source": "bearer",
    "subject": "06f801f5-0107-4dad-b911-625c7408b00f",
    "time": "2022-02-02T16:07:05Z",
    "datacontenttype": "application/json",
    "dataschema": "com/axis/connect/onboarding/started/@v/1.0.0",
    "data": {
        "serialNumber": "AAABBBBCCC123",
        "deviceArn": "arn:device:ea5a8fec-a42d-41b9-9c97-e49e7eab0b8a/56bfe68d-7df1-4dc9-adfe-e4479217ed19/c46e66e7-c42d-49fc-b008-42085e2e919d",
    },
}

event_data_bytes = json.dumps(event_data).encode("utf-8")
signature_header_bytes = bytes.fromhex(signature_header)

# Generate key
##############

# key = secrest.token_hex().encode("utf-8")
# Use this key for the example to work
key = bytes.fromhex(
    "36393466393337643466343039316663373938376363303261336331643061363061643438343132386461363831646665306239303637343336396537393833"
)

# Validation
############

digest = hmac.digest(key, event_data_bytes, hashlib.sha256)
assert hmac.compare_digest(digest, signature_header_bytes)
```