Alarm and Event Monitoring with Webhooks
Use the ACS webhook interface to set up webhooks to receive alarms and events from the Avigilon Cloud Services.
This document includes:
Creating Central Station and Site Monitoring
Retry Logic
Verifying Event Messages
Event Message Format
Cloud API Endpoints
Unless otherwise specified, all examples are in JSON. For more information about Central Station Monitoring, see Avigilon Online Product Documentation here.
Creating Central Station and Site Monitoring using Webhooks
Central Station is the way that the ACS platform provides for Remote Monitoring Providers to gain access to Customer Sites for purposes of monitoring. An Agent user account is defined for each Central Station.
Note: In order to create a Central Station follow the manual Create a Central Station
Retry Logic
The ACS service acknowledges successful HTTP responses:
200 OK
201 Created
202 Accepted
For connection errors or HTTP request timeouts, the ACS service resend the event with an increasing wait time, up to a maximum of 24 hours after the event has occurred.
After 24 hours, the ACS service will stop sending the event.
Verifying Event Messages
With the Shared Secret Phrase field, you can verify that event messages came from the Avigilon Cloud Services and not a third party.
For security, each Shared Secret Phrase must be unique for each central station configuration. If you support multiple central station configurations or multiple Avigilon dealers, each should have a different Shared Secret Phrase.
For webhooks directed to HTTPS endpoints, each event message contains the Shared Secret Phrase as an authenticationToken
.
For webhooks directed to HTTP endpoints, each event message contains a hash-based message authentication code (HMAC)-encrypted authorization header. The entire message payload plus the Shared Secret Phrase are encrypted. Your endpoint can use the authorization header value to verify the authenticity of the message content by recalculating the hash using the Shared Secret Phrase. In this case, the authenticationToken
value will be null in the message to avoid man-in-the-middle attacks.
Verifying event messages sent over HTTP
For HTTP endpoints, the HMAC-encrypted authorization header is calculated using a SHA-256 cryptographic hash function, and a secret cryptographic key which is the Shared Secret Phrase.
The HTTP request authorization header is formatted as follows:
Authorization: HMAC-SHA256 t/LN4FhGBhqIRt6dpD6BufeTMKSSjVMRkuLEl6BF6w4=
To verify the message content:
Convert the message payload to UTF8-encoded byte array.
Convert the Shared Secret Phrase to UTF8-encoded byte array.
Compute the SHA-256 hash of the encoded message using the encoded Shared Secret Phrase.
Convert the hash value to a Base-64 string.
Compare the computed Base-64 string with the authorization header value.
The following code demonstrates how to implement message validation:
using Nito.AsyncEx;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
string computeMessageSignature(string messagePayload, string authenticationToken)
{
var content = System.Text.Encoding.UTF8.GetBytes(messagePayload);
var token = System.Text.Encoding.UTF8.GetBytes(authenticationToken);
using (HMACSHA256 hmacSha256 = new HMACSHA256(token))
{
return Convert.ToBase64String(hmacSha256.ComputeHash(content));
}
}
async Task<bool> validateMessageRequest(HttpRequestMessage request, string authenticationToken)
{
var authHeader = request.Headers.GetValues("Authorization").First();
if (authHeader != null && authHeader.StartsWith("HMAC-SHA256"))
{
var headerHmac = authHeader.Substring("HMAC-SHA256 ".Length).Trim();
var rawMessage = await request.Content.ReadAsStringAsync();
var computedHmac = computeMessageSignature(rawMessage, authenticationToken);
return headerHmac.Equals(computedHmac);
}
return false;
}
[HttpPost]
[Route("IntegrationEvent/Webhook")]
public IHttpActionResult IntegrationWebhook([FromBody] IntegrationEvent integEvent)
{
var result = AsyncContext.Run(() => validateMessageRequest(Request, "authentication token"));
if (!result)
{
throw new Exception("Corrupt Integration Event Message!!!");
}
}
Event Message Format
An Avigilon event message consists of an Envelope and a Payload.
The event message format is as follows:
{
"payloadType":"BlueEvent",
"version":"1.0.0",
"messageId":"ebb7bd2c-4f2d-4116-8f59-b671110c9ae1",
"transmitTime":"2019-07-17T21:41:27.7959817Z",
"logCorrelationId":"90c3f1972cd44556abd0628c75d25da5",
"authenticationToken":null,
"payload":{
"Version":"1.0.0",
“agentUserId”:"400107a8-193d-4f03-b669-838bd15d31a4",
“agentUserTenantId”:"400107a8-193d-4f03-b669-838bd15d31a4",
"alarmId":"400107a8-193d-4f03-b669-838bd15d31a4",
"alarmTenantId":"400107a8-193d-4f03-b669-838bd15d31a4",
“eventClass”:”security”,
"eventName":"Person in Area",
"eventType":"TooMany",
"eventRuleName":"Person in Area",
"eventStartTime":"2019-07-17T21:41:20.57",
"eventEndTime":null,
"entityTenantId":"400107a8-193d-4f03-b669-838bd15d31a4",
"locationId":"400107a8-193d-4f03-b669-838bd15d31a4",
"locationName":"Assembly Row",
"serverId":"400107a8-193d-4f03-b669-838bd15d31a4",
"serverName":"VMA-BLU-8P8-211712250387",
"cameraId":"400107a8-193d-4f03-b669-838bd15d31a4",
"cameraName":"3.0C-H3A-BO1-IR (1167038) - Assembly Solid Cam",
"cameraRemoteId": "4321HJghayMNBTE5NStVLTsw1MBASuGH8bWKFnY_VrlmPK2KDWx4AAA",
"clipId":"400107a8-193d-4f03-b669-838bd15d31a4",
"clipUri": "https://blue.avigilon.com/some/path",
"gatewayId":"400107a8-193d-4f03-b669-838bd15d31a4"
}
}
Envelope Object
The message envelope identifies the payload type, the version number, and additional information about the signaling system.
Parameter
Type
Required
Description
payloadType
string
required
The payload type. For central station webhooks, the value is always “BlueEvent”.
Informs the client how to decode the Payload which can then be specified as a polymorphic Object.
version
string
required
The version number of the envelope.
messageId
string
required
The message ID.
transmitTime
string
required
The time the message was sent in ISO 8601 format in UTC.
logCorrelationId
string
required
A correlation ID that can be used to track the message in the Avigilon Cloud Services.
authenticationToken
object
required
If HTTPS is used, the value is the Shared Secret Phrase.
If HTTP is used, the value is “null”.
payload
object
required
The message payload. See Payload Object below.
Payload Object
The payload object contains the event details.
Parameter
Type
Required
Description
version
string
required
The message envelope version number.
agentUserId
string
required
The user ID based on the username and password created to configure the webhook central station.
agentUserTenantId
string
required
The tenant ID based on the username and password created to configure the webhook central station.
alarmId
string
required
The Avigilon Cloud Services alarm ID.
alarmTenantId
string
required
The tenant ID of the organization in which the alarm occurred.
eventClass
string
required
The type of event. Values can be “health” or “security”. Health events refer to device events. Security events refer to video analytics events.
eventName
string
required
The name of the event. This is the same name as the analytic rule that triggered the event.
eventType
string
required
The analytic rule activity that signalled the event.
eventRuleName
string
optional
The name of the analytic rule that triggered the event. This is typically the same value as the eventName.
eventStartTime
string
required
The time the event started in ISO 8601 format in UTC.
eventEndTime
string
optional
The time the event ended in ISO 8601 format in UTC. If the event is ongoing, the value is “null”.
entityTenantId
string
required
The tenant ID of the organization in which the event occurred.
locationId
string
required
The site ID of the server associated with the event.
locationName
string
required
The name of the site associated with the event.
serverId
string
required
The ID of the server associated with the event.
serverName
string
optional
The name of the server associated with the event.
cameraId
string
optional
The ID of the camera associated with the event.
cameraName
string
optional
The name of the camera associated with the event.
cameraRemoteId
optional
The ID of a camera from a connected ACC site.
clipId
string
optional
The ID of the event video clip.
clipUri
string
optional
The URI of the event video clip.
gatewayId
string
optional
The Gateway servicing the associated Event Entities.
Cloud API Endpoints
An integrator can respond to an event using the Cloud API. An integration solution can automatically play video related to an alarm.
Using the Cloud API Gateway to Show Alarm-related Video
Note: The procedure below refers to a body of an ACS event received through a webhook connection, using {{Event}} notation.
GET /system
- to get ACS system capabilities - see API detailsNote: Subsequent requests refer to the response of the previous request using
{{response}}
notation.
For example, if the request response is:{
"id": "00000000-0000-0000-0000-000000000000",
"name": "SystemName",
"_links": {
"rel/self": "SystemUrl",
"rel/login": "LoginUrl",
"rel/devices": "DevicesUrl"
},
"_system_id": "00000000-0000-0000-0000-000000000000",
"_type": "System"
}Then the value of
{{response._links.”rel/devices”}}
is"DevicesUrl"
.
GET {{response._links.”rel/devices”}}
Note: If
{{response._links.”rel/devices”}}
doesn’t exist, perform the login operation using thePOST
method to{{response._links.”rel/login”}}
and issueGET /system
again. See Overview - Authentication for details.In the returned collection of devices, identify the following camera
Device
where:Device.id == Event.payload.cameraId
Device.status == "online"Note: The next request refers to the identified device using the
Device
variable.
GET {{Device._links."rel/data_sources"}}
POST {{response._links."rel/rtsp"}}
request body:
{
"cameraId": "{{Event.payload.cameraRemoteId}}",
"quality":"high",
"t":"{{Event.payload.eventStartTime}}",,
"search":"true"
}Use
{{response.rtspRelayURL}}
to get the recorded RTSP video stream associated with the event using the RTSP video player of your choice.
Optimization Hints
An integration should perform login and get system capabilities only once - during initialization
A list of camera devices and
{{Device._links."rel/data_sources"}}
can be cached and/or refreshed in the background.