api.video provides you the possibility to get a POST request to your server that contains a JSON payload with event data. Webhooks can push notifications directly to your server, saving you the need to poll api.video for changes.

Webhook events

EventDescription
live-stream.broadcast.startedTriggers to indicate that a live stream broadcast has started.
live-stream.broadcast.endedTriggers to indicate that a live stream broadcast has ended.
video.source.recordedTriggers to indicate that a live stream has been completed and the recording of the live stream (if you set it to record) is ready to be transcoded. NOTE: This means the video has been enqueued for transcoding.
video.encoding.quality.completedTriggers when you upload a video, every time api.video finishes encoding a video in a set quality (up to the same level of quality that you uploaded), you get an announcement about it.

Here’s how the video.encoding webhook’s flow looks like:

Event properties

api.video offers the following webhook events that you can set up webhooks for:

live-stream.broadcast.started

Triggers to indicate that a live stream broadcast has started.

PropertyTypeDescriptionExample value
typestringthe webhook typelive-stream.broadcast.started
emittedAtdatetimetimestamp when the request was emitted from api.video2023-05-23T09:29:02.154104779Z
liveStreamIdstringthe live stream idli3VbBGc4e6njqw7fRrELvKl

live-stream.broadcast.ended

Triggers to indicate that a live stream broadcast has ended.

PropertyTypeDescriptionExample value
typestringthe webhook typelive-stream.broadcast.ended
emittedAtdatetimetimestamp when the request was emitted from api.video2023-05-23T09:29:02.154104779Z
liveStreamIdstringthe live stream idli3VbBGc4e6njqw7fRrELvKl

video.source.recorded

Triggers to indicate that a live stream has completed and the recording of the live stream (if you set it to record) is ready to be transcoded. NOTE: This means the video has been enqueued for transcoding.

PropertyTypeDescriptionExample value
typestringthe webhook typevideo.source.recorded
emittedAtdatetimetimestamp when the request was emitted from api.video2023-05-23T09:29:02.154104779Z
liveStreamIdstringthe live stream idli3VbBGc4e6njqw7fRrELvKl
videoIdstringthe video id of the recorded streamviXXXXXXXX

video.encoding.quality.completed

Triggers when you upload a video, every time api.video finishes encoding a video in a set quality (up to the same level of quality that you uploaded), you get an announcement about it.

PropertyTypeDescriptionExample value
typestringthe webhook typevideo.encoding.quality.completed
emittedAtdatetimetimestamp when the request was emitted from api.video2023-05-23T09:29:02.154104779Z
videoIdstringThe ID of the video that was encoded.viXXXXXXXX
encodingstringThe asset that the encoding was finished for. There are two types of assets that you will receive in the encoding:

- HLS
- MP4
hls
qualitystring- The quality of the video was transcoded to the current encoding.

The MP4 asset will only be transcoded once, hence you will receive a webhook only once for the MP4 asset with the final source quality. While the HLS asset webhook will be emitted multiple times with each quality (from the lowest 240p) to the highest of the source (up to 4k).

For example, if you've uploaded a video where the source quality is 720p. You will receive 5 webhooks in total:

- 1 webhook with 720p quality for the MP4 encoding
- 4 webhooks for 240p, 360p, 480p and 720p for the HLS encoding
1080p

Implementation

Testing

You can test your webhooks with tools like Pipedream. These tools enable you to test that api.video sends the correct webhook events, and ensure that webhooks arrive to your server.

Retry policy

📘

Webhook retry policy

api.video’s webhook service makes 3 notification attempts, with 3 second intervals between each try.

Choose an api.video client

The clients offered by api.video include:

To install your selected client, do the following:

go get github.com/apivideo/api.video-go-client
composer require api-video/php-api-client
npm install @api.video/nodejs-client --save

...or with yarn: 
  
yarn add @api.video/nodejs-client
pip install api.video
Using Nuget
  
Install-Package ApiVideo

Retrieve your API key

You'll need your API key to get started. You can sign up for one here: Get your api.video API key!.

Create a webhook

To create a webhook, all you have to do is set up your server and provide api.video with the URL you want events sent to and the list of events you wish to be sent to that URL.

curl --request POST \
     --url https://ws.api.video/webhooks \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2NDI4MjQzMTkuMDk2NjY1LCJuYmYiOjE2NDI4MjQzMTkuMDk2NjY1LCJleHAiOjE2NDI4Mjc5MTkuMDk2NjY1LCJwcm9qZWN0SWQiOiJwclJ6SUpKQTdCTHNxSGpTNDVLVnBCMSJ9.rfchf3btbMTzSukcwhUS0u4fNY4Q3g1JpoMeIz_Dls1ADmqDdKw7yBOE893C7cagb0lpuvUJvhuhgusLStsJ4nqzTveDeM2oPBQBNJjzwaJZNrImTPD4mif7Tzgxvn1_jQJA5L4gQhjd7frCIJW1yAwywrtiDPbxiWNp8fVl7r_QILjZZfslxy-kblPrHJ20Zix9VURqkGIORY5G_457nHSV9Atks1sUlt49E8b_g3jORja3MnznXBS0-0dksz2K62-QMe1_dk78V9JwbLeydqcr15M1jDLA3H6qFGI7GTsTDdZ5jKLhg5OR6yeSHFysqr3kOteTqAGdp3JuTrpZIA' \
     --header 'Content-Type: application/json' \
     --data '{"events": [
        "live-stream.broadcast.started", "live-stream.broadcast.ended", "video.encoding.quality.completed"
    ],
     "url": "https://example.com/webhooks"
}'
package main

import (
    "context"
    "fmt"
    "os"
    apivideosdk "github.com/apivideo/api.video-go-client"
)

func main() {
    client := apivideosdk.ClientBuilder("YOUR_API_TOKEN").Build()
    // if you rather like to use the sandbox environment:
    // client := apivideosdk.SandboxClientBuilder("YOU_SANDBOX_API_TOKEN").Build()
        
    webhooksCreationPayload := *apivideosdk.NewWebhooksCreationPayload([]string{"Events_example"}, "https://example.com/webhooks") // WebhooksCreationPayload | 

    
    res, err := client.Webhooks.Create(webhooksCreationPayload)

    if err != nil {
        fmt.Fprintf(os.Stderr, "Error when calling `Webhooks.Create``: %v\n", err)
    }
    // response from `Create`: Webhook
    fmt.Fprintf(os.Stdout, "Response from `Webhooks.Create`: %v\n", res)
}
  
require __DIR__ .'/vendor/autoload.php';

use Symfony\Component\HttpClient\Psr18Client;
use ApiVideo\Client\Client;
use ApiVideo\Client\Model\VideosApi;
use ApiVideo\Client\Model\WebHooksApi;
$apiKey = 'your API key here';
$apiVideoEndpoint = 'https://ws.api.video';

$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$client = new ApiVideo\Client\Client(
    $apiVideoEndpoint,
    $apiKey,
    $httpClient
);

$payload = (new \ApiVideo\Client\Model\WebhooksCreationPayload())->setUrl('http://company.com')->setEvents(['video.encoding.quality.completed']);
$webhooks = $client->webhooks()->create($payload);
print($webhooks);

//get the node-js library
const ApiVideoClient = require('@api.video/nodejs-client');

(async () => {
    try {
      const client = new ApiVideoClient({ apiKey: "YOUR_API_TOKEN" });
      const webhooksCreationPayload = {
            events: ["video.encoding.quality.completed"], 
            url: "https://example.com/webhooks", 
        }; 
        // Webhook
        const result = await client.webhooks.create(webhooksCreationPayload);
        console.log(result);
    } catch (e) {
        console.error(e);
    }
})();
# Create a webhook 
import apivideo
from apivideo.apis import WebhooksApi
from apivideo.exceptions import ApiAuthException

api_key = "your api key here"

client = apivideo.AuthenticatedApiClient(api_key)

# If you'd rather use the sandbox environment:
# client = apivideo.AuthenticatedApiClient(api_key, production=False)

client.connect()

webhooks_api = WebhooksApi(client)

# Create the webhooks payload
webhooks_creation_payload = {
    "events": ["video.encoding.quality.completed"],
    "url": "https://example.com/webhooks"
}

# Create a webhook
response = webhooks_api.create(webhooks_creation_payload)
print(response)

List all webhooks

After you create webhooks, you can retrieve a complete list of the URLs and associated events going to them with this code sample:

curl --request GET \
     --url 'https://ws.api.video/webhooks?events=video.encoding.quality.completed&currentPage=1&pageSize=25' \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2NDI4MjQzMTkuMDk2NjY1LCJuYmYiOjE2NDI4MjQzMTkuMDk2NjY1LCJleHAiOjE2NDI4Mjc5MTkuMDk2NjY1LCJwcm9qZWN0SWQiOiJwclJ6SUpKQTdCTHNxSGpTNDVLVnBCMSJ9.rfchf3btbMTzSukcwhUS0u4fNY4Q3g1JpoMeIz_Dls1ADmqDdKw7yBOE893C7cagb0lpuvUJvhuhgusLStsJ4nqzTveDeM2oPBQBNJjzwaJZNrImTPD4mif7Tzgxvn1_jQJA5L4gQhjd7frCIJW1yAwywrtiDPbxiWNp8fVl7r_QILjZZfslxy-kblPrHJ20Zix9VURqkGIORY5G_457nHSV9Atks1sUlt49E8b_g3jORja3MnznXBS0-0dksz2K62-QMe1_dk78V9JwbLeydqcr15M1jDLA3H6qFGI7GTsTDdZ5jKLhg5OR6yeSHFysqr3kOteTqAGdp3JuTrpZIA'
package main

import (
    "context"
    "fmt"
    "os"
    apivideosdk "github.com/apivideo/api.video-go-client"
)

func main() {
    client := apivideosdk.ClientBuilder("YOUR_API_TOKEN").Build()
    // if you rather like to use the sandbox environment:
    // client := apivideosdk.SandboxClientBuilder("YOU_SANDBOX_API_TOKEN").Build()
    req := apivideosdk.WebhooksApiListRequest{}
    
    req.Events("video.encoding.quality.completed") // string | The webhook event that you wish to filter on.
    req.CurrentPage(int32(2)) // int32 | Choose the number of search results to return per page. Minimum value: 1 (default to 1)
    req.PageSize(int32(30)) // int32 | Results per page. Allowed values 1-100, default is 25. (default to 25)

    res, err := client.Webhooks.List(req)
    

    if err != nil {
        fmt.Fprintf(os.Stderr, "Error when calling `Webhooks.List``: %v\n", err)
    }
    // response from `List`: WebhooksListResponse
    fmt.Fprintf(os.Stdout, "Response from `Webhooks.List`: %v\n", res)
}
<?php
require __DIR__ .'/vendor/autoload.php';

use Symfony\Component\HttpClient\Psr18Client;
use ApiVideo\Client\Client;
use ApiVideo\Client\Model\VideosApi;
use ApiVideo\Client\Model\WebHooksApi;
$apiKey = 'your API key here';
$apiVideoEndpoint = 'https://ws.api.video';

$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$client = new ApiVideo\Client\Client(
    $apiVideoEndpoint,
    $apiKey,
    $httpClient
);

$webhooks = $client->webhooks()->list();
print($webhooks);
const ApiVideoClient = require('@api.video/nodejs-client');

(async () => {
    try {
        const client = new ApiVideoClient({ apiKey: "YOUR_API_TOKEN" });

        const events = 'video.encoding.quality.completed'; // The webhook event that you wish to filter on.
        const currentPage = '2'; // Choose the number of search results to return per page. Minimum value: 1
        const pageSize = '30'; // Results per page. Allowed values 1-100, default is 25.

        // WebhooksListResponse
        const result = await client.webhooks.list({ events, currentPage, pageSize })
        console.log(result);
    } catch (e) {
        console.error(e);
    }
})();
# List all webhooks
import apivideo
from apivideo.apis import WebhooksApi
from apivideo.exceptions import ApiAuthException

api_key = "your api key here"

client = apivideo.AuthenticatedApiClient(api_key)

# If you'd rather use the sandbox environment:
# client = apivideo.AuthenticatedApiClient(api_key, production=False)

client.connect()

webhooks_api = WebhooksApi(client)

# Create a webhook
response = webhooks_api.list()
print(response)

Show a webhook

You can retrieve details about a specific webhook, including the URL and associated events, by sending a request with the unique webhook ID using this code sample:

curl --request GET \
     --url https://ws.api.video/webhooks/webhook_XXXXXXXXXXXXXXX \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2NDI4MjQzMTkuMDk2NjY1LCJuYmYiOjE2NDI4MjQzMTkuMDk2NjY1LCJleHAiOjE2NDI4Mjc5MTkuMDk2NjY1LCJwcm9qZWN0SWQiOiJwclJ6SUpKQTdCTHNxSGpTNDVLVnBCMSJ9.rfchf3btbMTzSukcwhUS0u4fNY4Q3g1JpoMeIz_Dls1ADmqDdKw7yBOE893C7cagb0lpuvUJvhuhgusLStsJ4nqzTveDeM2oPBQBNJjzwaJZNrImTPD4mif7Tzgxvn1_jQJA5L4gQhjd7frCIJW1yAwywrtiDPbxiWNp8fVl7r_QILjZZfslxy-kblPrHJ20Zix9VURqkGIORY5G_457nHSV9Atks1sUlt49E8b_g3jORja3MnznXBS0-0dksz2K62-QMe1_dk78V9JwbLeydqcr15M1jDLA3H6qFGI7GTsTDdZ5jKLhg5OR6yeSHFysqr3kOteTqAGdp3JuTrpZIA'
package main

import (
    "context"
    "fmt"
    "os"
    apivideosdk "github.com/apivideo/api.video-go-client"
)

func main() {
    client := apivideosdk.ClientBuilder("YOUR_API_TOKEN").Build()
    // if you rather like to use the sandbox environment:
    // client := apivideosdk.SandboxClientBuilder("YOU_SANDBOX_API_TOKEN").Build()
        
    webhookId := "webhookId_example" // string | The unique webhook you wish to retreive details on.

    
    res, err := client.Webhooks.Get(webhookId)

    if err != nil {
        fmt.Fprintf(os.Stderr, "Error when calling `Webhooks.Get``: %v\n", err)
    }
    // response from `Get`: Webhook
    fmt.Fprintf(os.Stdout, "Response from `Webhooks.Get`: %v\n", res)
}
<?php
require __DIR__ .'/vendor/autoload.php';

use Symfony\Component\HttpClient\Psr18Client;
use ApiVideo\Client\Client;
use ApiVideo\Client\Model\VideosApi;
use ApiVideo\Client\Model\WebHooksApi;
$apiKey = 'your API key here';
$apiVideoEndpoint = 'https://ws.api.video';

$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$client = new ApiVideo\Client\Client(
    $apiVideoEndpoint,
    $apiKey,
    $httpClient
);

$webhooks = $client->webhooks()->get('webhook ID here');
print($webhooks);
const ApiVideoClient = require('@api.video/nodejs-client');

(async () => {
    try {
        const client = new ApiVideoClient({ apiKey: "YOUR_API_TOKEN" });

        const webhookId = 'webhookId_example'; // The unique webhook you wish to retreive details on.

        // Webhook
        const result = await client.webhooks.get(webhookId);
        console.log(result);
    } catch (e) {
        console.error(e);
    }
})();
# List all webhooks
import apivideo
from apivideo.apis import WebhooksApi
from apivideo.exceptions import ApiAuthException

api_key = "your api key here"

client = apivideo.AuthenticatedApiClient(api_key)

# If you'd rather use the sandbox environment:
# client = apivideo.AuthenticatedApiClient(api_key, production=False)

client.connect()

webhooks_api = WebhooksApi(client)

# Create a webhook
response = webhooks_api.get("your webhook ID here")
print(response)

Delete a webhook

You can delete a webhook using its unique ID with this code sample:

curl --request DELETE \
     --url https://ws.api.video/webhooks/webhook_XXXXXXXXXXXXXXX \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2NDI4MjQzMTkuMDk2NjY1LCJuYmYiOjE2NDI4MjQzMTkuMDk2NjY1LCJleHAiOjE2NDI4Mjc5MTkuMDk2NjY1LCJwcm9qZWN0SWQiOiJwclJ6SUpKQTdCTHNxSGpTNDVLVnBCMSJ9.rfchf3btbMTzSukcwhUS0u4fNY4Q3g1JpoMeIz_Dls1ADmqDdKw7yBOE893C7cagb0lpuvUJvhuhgusLStsJ4nqzTveDeM2oPBQBNJjzwaJZNrImTPD4mif7Tzgxvn1_jQJA5L4gQhjd7frCIJW1yAwywrtiDPbxiWNp8fVl7r_QILjZZfslxy-kblPrHJ20Zix9VURqkGIORY5G_457nHSV9Atks1sUlt49E8b_g3jORja3MnznXBS0-0dksz2K62-QMe1_dk78V9JwbLeydqcr15M1jDLA3H6qFGI7GTsTDdZ5jKLhg5OR6yeSHFysqr3kOteTqAGdp3JuTrpZIA'
package main

import (
    "context"
    "fmt"
    "os"
    apivideosdk "github.com/apivideo/api.video-go-client"
)

func main() {
    client := apivideosdk.ClientBuilder("YOUR_API_TOKEN").Build()
    // if you rather like to use the sandbox environment:
    // client := apivideosdk.SandboxClientBuilder("YOU_SANDBOX_API_TOKEN").Build()
        
    webhookId := "webhookId_example" // string | The webhook you wish to delete.

    
    err := client.Webhooks.Delete(webhookId)

    if err != nil {
        fmt.Fprintf(os.Stderr, "Error when calling `Webhooks.Delete``: %v\n", err)
    }
}
<?php
require __DIR__ .'/vendor/autoload.php';

use Symfony\Component\HttpClient\Psr18Client;
use ApiVideo\Client\Client;
use ApiVideo\Client\Model\VideosApi;
use ApiVideo\Client\Model\WebHooksApi;
$apiKey = 'your API key here';
$apiVideoEndpoint = 'https://ws.api.video';

$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$client = new ApiVideo\Client\Client(
    $apiVideoEndpoint,
    $apiKey,
    $httpClient
);

$webhooks = $client->webhooks()->delete('webhook ID here');
print($webhooks);
const ApiVideoClient = require('@api.video/nodejs-client');

(async () => {
    try {
        const client = new ApiVideoClient({ apiKey: "YOUR_API_TOKEN" });

        const webhookId = 'webhookId_example'; // The webhook you wish to delete.

        // void
        const result = await client.webhooks.delete(webhookId);
        console.log(result);
    } catch (e) {
        console.error(e);
    }
})();
# List all webhooks
import apivideo
from apivideo.apis import WebhooksApi
from apivideo.exceptions import ApiAuthException

api_key = "your api key here"

client = apivideo.AuthenticatedApiClient(api_key)

# If you'd rather use the sandbox environment:
# client = apivideo.AuthenticatedApiClient(api_key, production=False)

client.connect()

webhooks_api = WebhooksApi(client)

# Create a webhook
response = webhooks_api.delete("your webhook ID here")
print(response)

Deleting a webhook is a permanent action and deleted webhooks cannot be recovered. :warning:

Next steps

You can also use the Get video status endpoint operation to check whether a video is uploaded and ready for playback.

Visit the API reference for a complete list of webhook endpoint operations.


What’s Next

You can also collect this information by doing polling.