Sign up for free

Create And Manage Webhooks

api.video provides webhook notifications in the form of POST requests, with a JSON payload that contains detailed event data. Webhooks can push notifications directly to your server, saving you the need to poll api.video for changes.

Hereโ€™s how the webhook flow looks like, using video.encoding as an example:

A diagram that shows the video.encoding webhook flowA diagram that shows the video.encoding webhook flow

Webhook events

These are the available webhook events:

EventTriggers when...
live-stream.broadcast.startedA live stream broadcast has started.
live-stream.broadcast.endedA live stream broadcast has ended.
video.source.recordedA live stream has been completed and the recording of the live stream is ready to be transcoded. This means that the video in queue for transcoding.
video.encoding.quality.completedA set quality version of encoding is complete for a video that you uploaded.

For each video, the MP4 asset is transcoded only once, hence you only receive one webhook notification for the MP4 asset, with the final source quality. The HLS asset's webhook notification triggers multiple times with each quality from the lowest 240p to the highest, up to 4k, based on the source you uploaded.

For example, if you upload a video in 720p quality, you 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.
video.caption.generatedAn automatic caption has been generated.
video.summary.generatedAn automatic summary has been generated.

Check out the API reference for detailed descriptions of each webhook event's request headers and payloads.

Subscribe to webhooks

You can subscribe to webhooks via the Dashboard and the API. To actually receive the webhooks, you need to set up a server that accepts POST requests from api.video. You can use tools like Webhook.site to test the process. Tools like this enable you to preview the webhook events, and test whether webhooks arrive to your server.

Via the dashboard

You can subscribe to webhooks in just a couple of clicks on the Webhooks tab in your Project settings.

Via the API

You can use the Create webhook endpoint to create a webhook subscription. Simply provide your server URL and the list of events you want to subscribe to:

Creating a webhook
curl --request POST \
     --url https://ws.api.video/webhooks \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {your API key}' \
     --header 'Content-Type: application/json' \
     --data '{"events": [
		"live-stream.broadcast.started", "live-stream.broadcast.ended", "video.encoding.quality.completed"
	],
     "url": "https://example.com/webhooks"
}'

Manage webhooks

You can manage the webhooks you subscribed to both via the dashboard and the API.

Via the dashboard

Visit the Webhooks tab in your Project settings. You can:

  • see a list of all webhook subscriptions,
  • filter for specific webhook events,
  • delete webhook subscriptions.

Via the API

The API enables you to List all webhooks, Retrieve webhook details, and to Delete a webhook.

Deleting a webhook is a permanent action. Deleted webhooks cannot be recovered.

Verify webhook origins

api.video provides secure signatures for each webhook you subscribe to. You can use this signature to verify that a webhook is indeed sent by api.video.

Verification process

  1. Subscribe to a webhook

    Use the Create webhook endpoint to subscribe to a webhook. We'll use video.encoding.quality.completed for this example:


      curl --request POST \
       --url https://ws.api.video/webhooks \
       --header 'Accept: application/json' \
       --header 'Authorization: Bearer {your API key}' \
       --header 'Content-Type: application/json' \
       --data '
          {"events": [
    	      "video.encoding.quality.completed"
            ],
            "url": "https://nice.url/webhooks"
          }'

  2. Check the response

    When this webhook subscription is created, api.video returns a signature secret in a 201 response, with a response body similar to this:


    {
      "webhookId": "webhook_XXXXXXXXXXXXXXX",
      "createdAt": "2024-08-08T14:12:18+00:00",
      "events": [
        "video.encoding.quality.completed"
      ],
      "url": "http://nice.url",
      "signatureSecret":"sig_sec_0000000000000000000000"
    }

  3. Trigger an event

    Let's upload a video! When the encoding for that video is completed, you receive a webhook notification in the form a POST request from api.video. This would be the body:

    {
      "type":"video.encoding.quality.completed",
      "emittedAt":"2024-08-08T14:12:18+00:00",
      "videoId":"vi0000000000000000000000",
      "liveStreamId":"li0000000000000000000000",
      "encoding":"hls",
      "quality":"720p"
    }

    This POST request will have 2 headers:

    {
      "X-Api-Video-WebhookID": "webhook_1BWt3JArmQq9sNZzsHStRS",
      "X-Api-Video-Signature": "3b7f8f40a6872cf979631f3bf84e6318ddd5cab8cd9d28f5ea1ea8f8a2ed1b11"
    }

    • X-Api-Video-WebhookID is the unique ID of your webhook subscription.
    • X-Api-Video-Signature is the webhook's body encrypted using the webhook's signature secret, in HMAC SHA256

  4. Retrieve the signature secret

    Grab the webhook ID from the X-Api-Video-WebhookID header in the POST request that you just received. Find the signature secret that belongs to it, using the GET /webhooks/{webhookId} endpoint.


  5. Encrypt the webhook body

    Grab the JSON body of the webhook notification that you received earlier. Use the signature secret you retrieved in the previous step to encrypt the webhook notification's JSON body via HMAC SHA256.


  6. Compare the results

    Compare the resulting hash with the value of the X-Api-Video-Signature header in the webhook notification that api.video sent you. When the results match, you have evidence that api.video is the origin of the webhook.


Sample implementation

Here is a sample implementation to verify webhooks using PHP:

  1. Create the webhook listener
      <?php
    
      require __DIR__ . "/vendor/autoload.php";
    
      /**
       * Set up the api.video client
       */
      $httpClient = new \Symfony\Component\HttpClient\Psr18Client();
      $client = new \ApiVideo\Client\Client(
          "https://sandbox.api.video",
          "YOUR_API_KEY",
          $httpClient
      );
    
      /**
       * Receive the webhook POST call
       */
      assert($_SERVER["REQUEST_METHOD"] === "POST");
    
      /**
       * Parse the data gotten from the webhook request
       */
      // This is the ID you will need to get the signature secret
      $webhookId = $_SERVER["HTTP_X_API_VIDEO_WEBHOOKID"];
      // This is the signature computed by api.video, based on the secret and on the request's content
      $expectedSignature = $_SERVER["HTTP_X_API_VIDEO_SIGNATURE"];
      // This is the content you will need in order to build the signature
      $webhookBody = file_get_contents("php://input");
      assert(is_string($webhookBody));
    
      /**
       * Get your signature secret based on the webhook ID
       */
      $secret = $client
          ->webhooks()
          ->get($webhookId)
          ->getSignatureSecret();
    
      /**
       * Build the signature based on the data you retrieved
       */
      $actualSignature = hash_hmac("sha256", $webhookBody, $secret);
    
      /**
       * Compare the signatures
       */
      if ($actualSignature === $expectedSignature) {
          echo "The webhook is valid." . PHP_EOL;
      } else {
          echo "The webhook is invalid." . PHP_EOL;
      }

  2. Run the webhook listener

    For the sake of this example, we are running the listener in a local environment:


      $ php -S localhost:8181

  3. Simulate a webhook call

    Let's pretend that api.video is sending a webhook notification to your local environment. Use this call:

    $ curl --location 'http://localhost:8181' --header 'x-api-video-webhookid: webhook_XXXXXXXXXXXXXXX' --header 'x-api-video-signature: 27a77d3a7fc626854886b5dbfae4e32c8b0170c1ea1b714c91ba77f1e7774e8c' --header 'Content-Type: application/json' --data '{"type":"video.encoding.quality.completed","emittedAt":"2021-01-29T15:46:25.217Z","videoId":"vi0000000000000000000000","liveStreamId":"li0000000000000000000000","encoding":"hls","quality":"720p"}'

    Note that this example call does not have any whitespaces. Copy and reuse it without modification, otherwise your call will not be successful.


  4. Result

    The implementation should return The webhook is valid..


Retries and failed webhooks

api.video handles failed webhook deliveries using these rules:

  • We accept responses that you send in return to a webhook notification.
  • We check for status codes in your responses above HTTP 299: 3xx redirections, 4xx client errors, and 5xx server errors.
  • In case of an unsuccessful delivery, api.video retries sending the webhook notification 3 times, with 3 second intervals between each try.
  • In case the status code in your response is 1xx or 2xx, api.video assumes that the delivery is successful and does not retry.

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.

Was this page helpful?