Create webhooks to monitor streaming events using the Wowza Streaming Engine REST API

Wowza Streaming Engine 4.9.6 adds webhook functionality to provide real-time notifications for key streaming events. Instead of continuously polling the REST API, you can now register webhook endpoints to receive event updates automatically as they happen. These enhancements improve both efficiency and responsiveness, making it easier to monitor, automate, and manage streaming workflows with minimal overhead.

This article explains how to set up the WebhookListener module using the Wowza Streaming Engine REST API. If you prefer a more manual setup using XML and JSON configuration and a text editor, see Create webhooks to monitor streaming events in Wowza Streaming Engine.

Overview


The webhooks feature in Wowza Streaming Engine requires a one-time configuration of Server.xml and Webhooks.json. As this article explains, you can use the Wowza Streaming Engine REST API to complete and manage this configuration.

When you update the Server.xml file, you ensure that the WebhookListener module is loaded when Wowza Streaming Engine starts. The Webhooks.json file defines how webhook events are generated and delivered. This file specifies the source identity, filtering criteria, and delivery endpoints for your webhooks.

The base URL or root endpoint for this workflow is:

http://[your-wowza-server]:8087/v2/servers/{serverName}/webhooks

To better understand the events you can capture, see Supported webhook events.

Before you start


Before you start working with the steps in this guide, we recommend that:

Webhooks REST API endpoint reference


You can use the various API requests in this section to programmatically manage and work with REST API endpoints for your webhooks. For more details, see the Wowza Streaming Engine Webhooks.json configuration reference.

Click each endpoint to see its purpose and to view sample requests and responses. In the examples, all values in curly brackets { } are placeholders and should be replaced with your own values, where appropriate.

GET /v2/servers/{serverName}/webhooks

Purpose: Fetch all webhook configurations to view the current rules and targets defined in the Webhooks.json file.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks"

Sample response:

{
  "serverName": "_defaultServer_",
  "webhooks": {
    "filters": [
      {
        "criteria": "vHost.*.app.myApp.appInstance.*.stream.*.state.*",
        "enabled": false,
        "id": "myAppStreamFilter",
        "targetRef": "myEndpointName"
      },
      {
        "criteria": "vHost.myVhost.>",
        "enabled": false,
        "id": "myServerFilter",
        "targetRef": "myEndpointName2"
      },
      {
        "criteria": "vHost.myVhost2.app.*.appInstance._definst_.>",
        "enabled": false,
        "id": "myAppInstanceFilter",
        "targetRef": "myEndpointName"
      },
    ],
    "source": "myWSEInstanceName",
    "targets": [
      {
        "auth": {
          "secret": "abc123secret",
          "type": "jwt"
        },
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer abc123token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value"
          }
        ],
        "id": "myEndpointName",
        "retryCount": null,
        "retryDelay": null,
        "url": "https://my.site.com/"
      },
      {
        "auth": {
          "secret": "def456secret",
          "type": "jwt"
        },
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer def456token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value2"
          }
        ],
        "id": "myEndpointName2",
        "retryCount": null,
        "retryDelay": null,
        "url": "https://my.site2.com/"
      }
    ]
  }
}
PUT /v2/servers/{serverName}/webhooks

Purpose: Update the current rules and targets defined in the Webhooks.json file. The following sample request sends supported webhook events from the _defaultServer_ virtual host to a URL defined in the targets array.

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks" \
 -d '{
   "serverName": "_defaultServer_",
   "webhooks": {
     "source": "myWSEInstanceName",
     "filters": [
       {
         "id": "myServerFilter",
         "enabled": true,
         "criteria": "vHost._defaultVHost_.>",
         "targetRef": "myEndpointName"
       }
     ],
     "targets": [
       {
         "id": "myEndpointName",
         "url": "https://webhook.site/123e4567-e89b-12d3-a456-426614174000",
         "auth": {
           "secret": "def456secret",
           "type": "jwt"
         },
         "headers": [
           {
             "name": "Authorization",
             "value": "Bearer def456token"
           },
           {
             "name": "X-Custom-Header",
             "value": "my-value"
           }
         ]
       }
     ]
   }
 }'

Sample response:

{
  "webhooks": {
    "source": "myWSEInstanceName",
    "filters": [
      {
        "id": "myServerFilter",
        "enabled": true,
        "criteria": "vHost._defaultVHost_.>",
        "targetRef": "myEndpointName"
      }
    ],
    "targets": [
      {
        "id": "myEndpointName",
        "url": "https://webhook.site/123e4567-e89b-12d3-a456-426614174000",
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer def456token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value"
          }
        ],
        "auth": {
          "type": "jwt",
          "secret": "def456secret"
        },
        "retryCount": null,
        "retryDelay": null
      }
    ]
  }
}
GET /v2/servers/{serverName}/webhooks/filters

Purpose: Fetch a list of all filters defined in the Webhooks.json file.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/filters"

Sample response:

{
  "serverName": "_defaultServer_",
  "filters": [
    {
      "criteria": "vHost._defaultVHost_.>",
      "enabled": true,
      "id": "myServerFilter",
      "targetRef": "myEndpointName"
    }
  ]
}
POST /v2/servers/{serverName}/webhooks/filters

Purpose: Create a filter in the Webhooks.json file. This requires that the targetRef exists. In this case, we're creating a filter with the myAppStartedFilter identifier.

Sample request:

curl -X POST --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/filters" \
 -d '{
   "id": "myAppStartedFilter",
   "enabled": true,
   "criteria": "vHost.*.app.*.appInstance.*.stream.*.state.started",
   "targetRef": "myEndpointName",
   "serverName": "_defaultServer_"
 }'

Sample response:

{
  "id": "myAppStartedFilter",
  "enabled": true,
  "criteria": "vHost.*.app.*.appInstance.*.stream.*.state.started",
  "targetRef": "myEndpointName"
}
GET /v2/servers/{serverName}/webhooks/filters/{id}

Purpose: Fetch a webhook filter based on the filter id path parameter. In this case, we're getting details about the myAppStartedFilter.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/filters/myAppStartedFilter"

Sample response:

{
 "criteria" : "vHost.*.app.*.appInstance.*.stream.*.state.started",
 "enabled" : true,
 "serverName" : "_defaultServer_",
 "targetRef" : "myEndpointName"
}
PUT /v2/servers/{serverName}/webhooks/filters/{id}

Purpose: Update a webhook filter based on the filter id path parameter. In this case, we're modifying the myAppStartedFilter criteria to notify us when any stream on the server has stopped.

Note: The filter id value cannot be updated using this method.

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/filters/myAppStartedFilter" \
 -d '{
   "criteria": "vHost.*.app.*.appInstance.*.stream.*.state.stopped",
   "enabled": true,
   "id": "myAppStartedFilter",
   "serverName": "_defaultServer_",
   "targetRef": "myEndpointName"
 }'

Sample response:

{
  "id": "myAppStartedFilter",
  "enabled": true,
  "criteria": "vHost.*.app.*.appInstance.*.stream.*.state.stopped",
  "targetRef": "myEndpointName"
}
DELETE /v2/servers/{serverName}/webhooks/filters/{id}

Purpose: Delete a webhook filter based on the filter id path parameter. In this case, we're deleting the filter with the myAppStartedFilter identifier.

Sample request:

curl -X DELETE --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/filters/myAppStartedFilter"

Sample response:

{
  "success": true,
  "message": "Deleted",
  "data": null
}
GET /v2/servers/{serverName}/webhooks/source

Purpose: Fetch the source from a Webhooks.json configuration file.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/source"

Sample response:

{
  "serverName": "_defaultServer_",
  "source": "myWSEInstanceName"
}
PUT /v2/servers/{serverName}/webhooks/source

Purpose: Update the source in the Webhooks.json configuration file. In this case, we're updating the source name to myWSEInstanceNameUpdated.

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/source" \
 -d '{
   "source": "myWSEInstanceNameUpdated"
 }'

Sample response:

{
  "source" : "myWSEInstanceNameUpdated"
}
GET /v2/servers/{serverName}/webhooks/targets

Purpose: Fetch a list of all targets in the Webhooks.json configuration file.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/targets"

Sample response:

{
  "serverName": "_defaultServer_",
  "targets": [
    {
      "auth": {
        "secret": "def456secret",
        "type": "jwt"
      },
      "headers": [
        {
          "name": "Authorization",
          "value": "Bearer def456token"
        },
        {
          "name": "X-Custom-Header",
          "value": "my-value"
        }
      ],
      "id": "myEndpointName",
      "retryCount": null,
      "retryDelay": null,
      "url": "https://webhook.site/123e4567-e89b-12d3-a456-426614174000"
    }
  ]
}
POST /v2/servers/{serverName}/webhooks/targets

Purpose: Create a target in the Webhooks.json configuration file. In this case, we're adding a new myEndpointName2 target.

Sample request:

curl -X POST --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/targets" \
 -d '{
   "serverName": "_defaultServer_",
   "id": "myEndpointName2",
   "url": "https://webhook.site/9f8b7c6d-a12b-34d5-b678-90abcdef1234"
 }'

Sample response:

{
  "id": "myEndpointName2",
  "url": "https://webhook.site/9f8b7c6d-a12b-34d5-b678-90abcdef1234",
  "headers": null,
  "auth": null,
  "retryCount": null,
  "retryDelay": null
}
GET /v2/servers/{serverName}/webhooks/targets/{id}

Purpose: Fetch a target from the Webhooks.json configuration file using the id path parameter. In this case, we're getting details about the myEndpointName2 target.

Sample request:

curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/targets/myEndpointName2"

Sample response:

{
  "serverName": "_defaultServer_",
  "url": "https://webhook.site/9f8b7c6d-a12b-34d5-b678-90abcdef1234"
}
PUT /v2/servers/{serverName}/webhooks/targets/{id}

Purpose: Update a target in the Webhooks.json configuration file based on the id path parameter. In this case, we're updating the myEndpointName2 target.

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/targets/myEndpointName2" \
 -d '{
   "id": "MyEndpointName2",
   "url": "https://webhook.site/4a1b2c3d-e456-78f9-a012-3456789abcde",
   "headers": [
     {
       "name": "Authorization",
       "value": "Bearer abc123token"
     },
     {
       "name": "X-Custom-Header",
       "value": "some-value"
     }
   ],
   "auth": {
     "type": "jwt",
     "secret": "abc123secret"
   }
 }'

Sample response:

{
  "id": "myEndpointName2",
  "url": "https://webhook.site/4a1b2c3d-e456-78f9-a012-3456789abcde",
  "headers": [
    {
      "name": "Authorization",
      "value": "Bearer abc123token"
    },
    {
      "name": "X-Custom-Header",
      "value": "some-value"
    }
  ],
  "auth": {
    "type": "jwt",
    "secret": "abc123secret"
  },
  "retryCount": null,
  "retryDelay": null
}
DELETE /v2/servers/{serverName}/webhooks/targets/{id}

Purpose: Delete a target in the Webhooks.json configuration file based on the target id path parameter. In this case, we're deleting the myEndpointName2 target.

Sample request:

curl -X DELETE --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks/targets/myEndpointName2"

Sample response:

{
  "success": true,
  "message": "Deleted",
  "data": null
}

1. Configure your Server.xml file


The first step is to update the Server.xml configuration file located at  [install-dir]/conf/Server.xml to include:

 <ServerListeners>
    <ServerListener>
      <BaseClass>com.wowza.wms.webhooks.WebhookListener</BaseClass>
    </ServerListener>
  </VHostListeners> 

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_" \
 -d'
 {
  "description": "desc",
  "name": "Wowza Streaming Engine",
  "serverName": "_defaultServer_",
  "defaultStreamPrefix": "mp4",
  "ipAddress": "*",
  "port": 8083,
  "handlerThreadPool": "${com.wowza.wms.TuningAuto}",
  "handlerThreadPoolAutoValue": "120",
  "transportThreadPool": "${com.wowza.wms.TuningAuto}",
  "transportThreadPoolAutoValue": "80",
  "rtpDataPortSharing": false,
  "rtpDataPortSharingPort": 6970,
  "serverListeners": {
   "serverName": "_defaultServer_",
   "serverListeners": [
    {
     "order": 0,
     "baseClass": "com.wowza.wms.mediacache.impl.MediaCacheServerListener"
    },
    {
     "order": 1,
     "baseClass": "com.wowza.wms.webhooks.WebhookListener"
    }
   ]
  },
  "serverTS": 0
 }'

Sample response:

{
  "success": true,
  "message": "Saved",
  "data": null
}

2. Configure your Webhooks.json file


Next, define the rules and targets in the Webhooks.json file. This JSON configuration file defines how webhook events are generated and delivered. For more, see the Wowza Streaming Engine Webhooks.json configuration reference.

Note: In this section, we use Webhook.site to generate a unique URL endpoint to use as a test webhook destination. For more details, see Test your webhook notification.
  1. Go to Webhook.site and create a unique URL for your endpoint.
  2. Run this curl request to fetch the content of the Webhooks.json configuration file located at [install-dir]/conf/Webhooks.json:
curl -X GET --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks"

Sample response:

{
  "serverName": "_defaultServer_",
  "webhooks": {
    "filters": [
      {
        "criteria": "vHost.*.app.myApp.appInstance.*.stream.*.state.*",
        "enabled": false,
        "id": "myAppStreamFilter",
        "targetRef": "myEndpointName"
      },
      {
        "criteria": "vHost.myVhost.>",
        "enabled": false,
        "id": "myServerFilter",
        "targetRef": "myEndpointName2"
      },
      {
        "criteria": "vHost.myVhost2.app.*.appInstance._definst_.>",
        "enabled": false,
        "id": "myAppInstanceFilter",
        "targetRef": "myEndpointName"
      },
    ],
    "source": "myWSEInstanceName",
    "targets": [
      {
        "auth": {
          "secret": "abc123secret",
          "type": "jwt"
        },
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer abc123token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value"
          }
        ],
        "id": "myEndpointName",
        "retryCount": null,
        "retryDelay": null,
        "url": "https://my.site.com/"
      },
      {
        "auth": {
          "secret": "def456secret",
          "type": "jwt"
        },
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer def456token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value2"
          }
        ],
        "id": "myEndpointName2",
        "retryCount": null,
        "retryDelay": null,
        "url": "https://my.site2.com/"
      }
    ]
  }
}
  1. Run the following curl request to update the Webhooks.json configuration file. The endpoint url in the targets array is a placeholder. Replace it with your own value, or in this case, add the unique URL from the Webhook.site in step 1:
curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept: application/json; charset=utf-8" \
 -H "Content-Type: application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/webhooks" \
 -d '{
   "serverName": "_defaultServer_",
   "webhooks": {
     "source": "myWSEInstanceName",
     "filters": [
       {
         "id": "myServerFilter",
         "enabled": true,
         "criteria": "vHost._defaultVHost_.>",
         "targetRef": "myEndpointName"
       }
     ],
     "targets": [
       {
         "id": "myEndpointName",
         "url": "https://webhook.site/123e4567-e89b-12d3-a456-426614174000",
         "auth": {
           "secret": "def456secret",
           "type": "jwt"
         },
         "headers": [
           {
             "name": "Authorization",
             "value": "Bearer def456token"
           },
           {
             "name": "X-Custom-Header",
             "value": "my-value"
           }
         ]
       }
     ]
   }
 }'

Sample response:

{
  "webhooks": {
    "source": "myWSEInstanceName",
    "filters": [
      {
        "id": "myServerFilter",
        "enabled": true,
        "criteria": "vHost._defaultVHost_.>",
        "targetRef": "myEndpointName"
      }
    ],
    "targets": [
      {
        "id": "myEndpointName",
        "url": "https://webhook.site/123e4567-e89b-12d3-a456-426614174000",
        "headers": [
          {
            "name": "Authorization",
            "value": "Bearer def456token"
          },
          {
            "name": "X-Custom-Header",
            "value": "my-value"
          }
        ],
        "auth": {
          "type": "jwt",
          "secret": "def456secret"
        },
        "retryCount": null,
        "retryDelay": null
      }
    ]
  }
}
Note: In this example, we want to capture supported webhook events only from the _defaultVHost_ virtual host (VHost) and send them to the target endpoint. For information about authenticating the request, see JSON Web Token (JWT) details.

3. Restart your server


After making any configuration changes to your Server.xml and Webhook.json files, ensure that you restart your Wowza Streaming Engine server for the changes to take effect.

Sample request:

curl -X PUT --basic -u "USERNAME:PASSWORD" \
 -H "Accept:application/json; charset=utf-8" \
 -H "Content-Type:application/json; charset=utf-8" \
 "http://localhost:8087/v2/servers/_defaultServer_/actions/restart"

Sample response:

{
  "success": true,
  "message": "Restarting server in 5 seconds",
  "data": null
}

4. Test your webhook notification


In this section, we use Webhook.site to capture and inspect webhook notifications from Wowza Streaming Engine during development. This makes it easy to view raw payloads, confirm request formatting, and debug your setup.

Note: For production environments, you'll want to integrate webhooks in a more secure and scalable manner, for example, by using direct server endpoints to receive and process events in your app, event streaming processors such as Kafka, serverless functions like AWS Lambda, or no-code platforms like Zapier.
  1. Start a stream and send it to your Wowza Streaming Engine server. For more about publishing live streams, see Connect a live source to Wowza Streaming Engine.
  2. Use the unique URL you created in the Webhook.site online tool to verify that webhook notifications from Wowza Streaming Engine are received. For example, you get a notification each time a stream starts or stops, or an application shuts down. A request payload looks similar to the Raw Content in the following screenshot:

More resources