> For the complete documentation index, see [llms.txt](https://developer.perculus.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.perculus.com/v2-en/misc/webhooks.md).

# Webhooks

## **Introduction**&#x20;

Groups uses webhooks to notify external systems about particular events. To use this functionality, a webhook should be registered to store information, including the webhook endpoint URL (a.k.a listener URL) and the event type. When an event associated with a webhook happens, an HTTP POST payload is sent to the associated URL. Please contact the support team if you want to use this feature and register your webhook URL.

## Events and Messages&#x20;

The following is the list of Groups events and corresponding messages to notify the associated webhooks.

### **SessionReportEvent**

This event is dispatched after a session is packed and report data are available. The status can be *ready* or *failed*. If an error occurred during the preparation of the report, an error text is also included in the message.

#### SessionReportEvent Message (Successful Operation)

```json
{ 
    "request_id": "bd943129-f2eb-4b52-9bf9-784c87d1b80e",
    "type": "SessionReportEvent",
    "session_id": "805368AF-B096-42D4-8233-1B0C0EBF1DB2",
    "token": "63833938902|Uu4T7EFsl6dfBfLjFbVKizWerUJ4q9/pA9UokdW+Vv0=",
    "status": "ready"     
} 
```

#### SessionReportEvent Message (Failed Operation)

```json
{
    "request_id": "bd943129-f2eb-4b52-9bf9-784c87d1b80e",
    "type": "SessionReportEvent",
    "session_id": "805368AF-B096-42D4-8233-1B0C0EBF1DB2",
    "token": "63833938902|Uu4T7EFsl6dfBfLjFbVKizWerUJ4q9/pA9UokdW+Vv0=",     
    "status": "failed",
    "error": "error text comes here" 
} 
```

### **SingleVideoEvent**

This event is dispatched after the video file is ready to be downloaded. If the status is failed, an error text is also included in the message.

#### SingleVideoEvent Message (Successful Operation)

```json
{ 
    "request_id": "0489b550-df7f-4807-a693-22fcd6c9ccf5", 
    "type": "SingleVideoEvent",
    "session_id": "AF7F81CA-167B-43C0-94F7-E6835B30B043",
    "token": "63833938902|Uu4T7EFsl6dfBfLjFbVKizWerUJ4q9/pA9UokdW+Vv0=",
    "status": "ready",
    "video_url": "https://storage-system.constructor.tech/files/0f19be98e5442ec8f9439c7435f5a7f.mp4?token=xhiUZSLoFe4y9VLCYz17TZiKcZk%3D" 
} 
```

#### SingleVideoEvent Message (Failed Operation)

```json
{
    "request_id": "bd943129-f2eb-4b52-9bf9-784c87d1b80e",
    "type": "SingleVideoEvent",
    "session_id": "AF7F81CA-167B-43C0-94F7-E6835B30B043",
    "token": "63833938902|Uu4T7EFsl6dfBfLjFbVKizWerUJ4q9/pA9UokdW+Vv0=",
    "status": "failed",
    "error": "error text comes here" 
} 
```

### **SessionStatusEvent**

This event is dispatched after a session is *started* or *finished*.&#x20;

The event data is encapsulated as a JSON payload and included in an HTTP POST request to the webhook endpoint URL.&#x20;

#### SessionStatusEvent Message&#x20;

```json
{ 
    "request_id": "bd943129-f2eb-4b52-9bf9-784c87d1b80e",
    "type": "SessionStatusEvent",
    "session_id": "805368AF-B096-42D4-8233-1B0C0EBF1DB2",
    "token": "63833938902|Uu4T7EFsl6dfBfLjFbVKizWerUJ4q9/pA9UokdW+Vv0=",
    "status": "started",
    "date": "2024-01-23T17:41:07"
} 
```

## Message Fields

<table><thead><tr><th width="130">Name</th><th width="436">Description</th><th>Types</th></tr></thead><tbody><tr><td><strong>request_id</strong></td><td>This unique identifier identifies the message. It can be used to track messages and troubleshoot problems.</td><td>All</td></tr><tr><td><strong>type</strong></td><td>The type of the message.</td><td>All</td></tr><tr><td><strong>session_id</strong></td><td>This is the unique identifier of the Groups session.</td><td>All</td></tr><tr><td><strong>token</strong></td><td>This is the authentication token used by the webhook endpoint to verify the Groups platform.<br>See <a href="#token-generation-and-verification">"Token Generation and Verification</a>".</td><td>All</td></tr><tr><td><strong>status</strong></td><td>This can have two values for SessionReportEvent and SingleVideoEvent messages, which are <em>ready</em> and <em>failed</em>. The <em>status</em> field in the SessionReportEvent payload indicates whether the session has been correctly packaged. Similarly, the <em>status</em> field in the SingleVideoEvent payload indicates whether the session video has been successfully created. If the status is <em>failed,</em> an error message is transmitted within the error element. <br>It can take <em>started</em> or <em>finished</em> values for SessionStatusEvent.</td><td>All</td></tr><tr><td><strong>video_url</strong></td><td>This element specifies the URL where the video content is located. This URL can be utilized to access the video content and expires after 24 hours. </td><td>SingleVideoEvent</td></tr><tr><td><strong>date</strong></td><td>This element specifies when the session started or finished depending on the value of the status field.</td><td>SessionStatusEvent</td></tr><tr><td><strong>error</strong></td><td>This element contains the error text of the event in case of any errors. It’s an optional element which is omitted if there is no error.</td><td>SessionReportEvent<br>SingleVideoEvent</td></tr></tbody></table>

## Token Generation and Verification&#x20;

The receiver system can authenticate the Groups system by verifying the authentication token sent within the messages. As shown in the sections above, Groups includes a token element in each webhook URL request payload. It is in the following format:&#x20;

`token = <timestamp>|<hmac>`

The **hmac** is a hash-based message authentication code. It’s generated by using a secret and a timestamp.&#x20;

The **timestamp** is the number of seconds passed from 1/1/1970 UTC to the token creation time. It is also known as the [Unix time](https://en.wikipedia.org/wiki/Unix_time).

The **secret** is a private piece of information that is only known by the Groups and the receiver side.&#x20;

The pseudo-code of the token generation is as follows:&#x20;

```csharp
var token_content = utf8_bytes(timestamp);
var hmac_sha256_key = utf8_bytes(secret);
var hmac_sha256_generator = hmac_sha256(hmac_sha256_key);
var hmac = hmac_sha256_generator.compute_hash(token_content);
var token = timestamp + "|" + hmac;
```

Since the secret is also known by the receiver side, the receiver can re-generate the hmac by using the timestamp, which is embedded in the token and the secret by using the above algorithm. Thus, the receiver can verify:

* The validity of the request by checking that the token has not expired if the timestamp is at most N minutes old. Here, deciding the N parameter is up to the receiver side.
* The authenticity of the request (by checking whether the hmacs are equal). The following C# code snippet is a method that generates an authentication token using a secret and a timestamp, as explained above in the document.

### Sample C# Code to Generate an Authentication Token

```csharp
public static string CreateAuthToken(string secret, DateTime httpRequestUTCDate) { 
    if (String.IsNullOrEmpty(secret)) 
        throw new ArgumentException("secret cannot be empty"); 
    // Calculate Unix timestamp which is 
    // the total seconds passed since 1/1/1970 UTC 
    var timestamp = Math.Floor((httpRequestUTCDate - new DateTime(1970, DateTimeKind.Utc)).TotalSeconds).ToString(); 
    // Generate an hmac using HMAC-SHA256 algorithm 
    var keyBytes = System.Text.Encoding.UTF8.GetBytes(secret); 
    var hmacsha256 = new System.Security.Cryptography.HMACSHA256(keyBytes);
    var messageBytes = System.Text.Encoding.UTF8.GetBytes(timestamp);
    var hmac = Convert.ToBase64String(hmacsha256.ComputeHash(messageBytes));
    // Return the token, which combines unix timestamp and hmac 
    return timestamp + "|" + hmac; 
} 
```
