# Webhook Types


Kinescope supports outgoing webhooks — notifications about events that occur with your videos or streams. When an event occurs (e.g., a video is processed or a stream ends), Kinescope sends an HTTP request to the URL you specified.

## Who this article is for

* **Developers** — need to automate processes in their system when Kinescope events occur
* **Platform administrators** — need to receive notifications about video processing status
* **DevOps engineers** — need to integrate Kinescope with monitoring systems

## What problems webhooks solve

Webhooks let you automate processes in your system:

- **Tracking video processing** — know when a video is ready to watch or an error occurred
- **Stream monitoring** — receive notifications about streamer connections, stream ends, and other events
- **Integration with your system** — automatically update statuses in your database or send notifications to users

## **How it works**

1. **You configure a URL** for receiving webhooks (via API or the Kinescope interface)
2. **When an event occurs**, Kinescope sends an HTTP POST request to your URL with JSON data
3. **Your server handles the request** and performs the needed actions (status updates, sending notifications, etc.)

## **Video webhooks**

### **`media.update.status`**

Sent when the video status is updated. Used to track video processing, errors, or publication completion.

**Example 1: Successful status update**

```json
{
  "event": "media.update.status",
  "data": {
    "id": "7127f2d7-0e96-40d0-9a03-2e987c096466",
    "status": "done"
  }
}
```

**Example 2: Processing error**

```json
{
  "event": "media.update.status",
  "data": {
    "id": "12706830-0e96-40d0-9a03-2e987c096466",
    "status": "error",
    "message": "import error: code=610100, message=cannot download link: https://example.ru/test.mp4, http_code=404"
  }
}
```

**Possible statuses:**
- `pending` — video is waiting for processing
- `uploading` — video is uploading
- `pre-processing` — video pre-processing
- `processing` — video is being processed
- `aborted` — processing was aborted
- `done` — video is ready to watch
- `error` — an error occurred during processing
- `suspended` — processing/uploading is paused

## **Stream webhooks**

### **`live.created`**

Notification about the creation of a new stream event (via API or interface).

```json
{
  "event": "live.created",
  "data": {
    "event_id": "abc123-def456-ghi789"
  }
}
```

### **`live.connected`**

Streamer connected — RTMP stream started arriving at the server.

```json
{
  "event": "live.connected",
  "data": {
    "event_id": "abc123-def456-ghi789"
  }
}
```

### **`live.disconnected`**

Streamer disconnected — RTMP stream stopped.

```json
{
  "event": "live.disconnected",
  "data": {
    "event_id": "abc123-def456-ghi789"
  }
}
```

### **`live.finished`**

Stream ended. The response also includes `video_id` — the ID of the stream recording video (if recording was enabled).

```json
{
  "event": "live.finished",
  "data": {
    "event_id": "abc123-def456-ghi789",
    "video_id": "7127f2d7-0e96-40d0-9a03-2e987c096466"
  }
}
```

### **`live.cancelled`**

Stream was cancelled.

```json
{
  "event": "live.cancelled",
  "data": {
    "event_id": "abc123-def456-ghi789"
  }
}
```

### **`live.enabled`**

Stream is available for viewing by clients.

```json
{
  "event": "live.enabled",
  "data": {
    "event_id": "abc123-def456-ghi789"
  }
}
```

## **Webhook handling examples**

### **Example 1: Updating video status in the database**

Here is how to handle the `media.update.status` webhook and update the status in your database:

```go
package main

import (
    "encoding/json"
    "log"
)

type MediaStatusEvent struct {
    Event string `json:"event"`
    Data  struct {
        ID      string `json:"id"`
        Status  string `json:"status"`
        Message string `json:"message,omitempty"`
    } `json:"data"`
}

func handleMediaStatusUpdate(event MediaStatusEvent) error {
    videoID := event.Data.ID
    status := event.Data.Status
    
    // Update status in the database
    // db.Exec("UPDATE videos SET status = ?, error_message = ?, updated_at = ? WHERE kinescope_id = ?",
    //     status, event.Data.Message, time.Now(), videoID)
    
    if status == "done" {
        notifyUser(videoID, "Your video is ready to watch!")
    }
    
    if status == "error" {
        log.Printf("Video processing error %s: %s", videoID, event.Data.Message)
    }
    
    if status == "aborted" {
        notifyUser(videoID, "Video processing was aborted")
    }
    
    return nil
}
```

### **Example 2: Handling stream end**

When a stream ends, you can automatically process the recording:

```go
package main

type LiveFinishedEvent struct {
    Event string `json:"event"`
    Data  struct {
        EventID string `json:"event_id"`
        VideoID string `json:"video_id,omitempty"`
    } `json:"data"`
}

func handleLiveFinished(event LiveFinishedEvent) error {
    eventID := event.Data.EventID
    videoID := event.Data.VideoID
    
    // Update stream status
    // db.Exec("UPDATE live_events SET status = ?, recording_video_id = ?, finished_at = ? WHERE kinescope_event_id = ?",
    //     "finished", videoID, time.Now(), eventID)
    
    if videoID != "" {
        notifyViewers(eventID, "Stream recording is available: "+videoID)
    }
    
    return nil
}
```

### **Example 3: Universal webhook handler**

Here is an example of a universal handler that can process different webhook types:

```go
package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type WebhookEvent struct {
    Event string          `json:"event"`
    Data  json.RawMessage `json:"data"`
}

func handleWebhook(event WebhookEvent) error {
    switch event.Event {
    case "media.update.status":
        var e MediaStatusEvent
        json.Unmarshal(event.Data, &e.Data)
        e.Event = event.Event
        return handleMediaStatusUpdate(e)
        
    case "live.finished":
        var e LiveFinishedEvent
        json.Unmarshal(event.Data, &e.Data)
        e.Event = event.Event
        return handleLiveFinished(e)
        
    default:
        log.Printf("Unknown event type: %s", event.Event)
    }
    
    return nil
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    var event WebhookEvent
    if err := json.NewDecoder(r.Body).Decode(&event); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    if err := handleWebhook(event); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(map[string]bool{"success": true})
}
```

## **Setting up webhooks**

Webhooks are configured via the Kinescope API. Specify the URL of your endpoint that will receive notifications.

> **Important:** Your endpoint must return HTTP 200 in response to successful webhook handling. If Kinescope receives an error (4xx, 5xx), it may retry the request.

## **Security**

It is recommended to verify webhook authenticity:

- **Check the request source** — make sure the request comes from Kinescope
- **Use HTTPS** — webhooks should be sent to secure URLs
- **Validate data** — check the format and required fields in the request

Done! You can now set up webhooks and automate processes in your system.

## What's next?

1. **[General API guidelines](https://docs.kinescope.com/developer-guides/api-general-rules/)** — authorization and request format
2. **[Kinescope API](https://docs.kinescope.com/developer-guides/kinescope-api/)** — full API documentation for webhook configuration
3. **[File upload via API](https://docs.kinescope.com/developer-guides/file-upload-via-api/)** — automated video upload

Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!

