Slicer Failover API
Create, update, and delete failover groups programmatically, including authentication and sample code.
Slicer Failover API Updates
Slicer Failover API documentation is online at https://api-docs.uplynk.com/#Develop/Live-Slicer-Failover-API.htm.
Since the introduction of Slicer Failover, APIs have been added or updated for the creation of Failover Groups, the deletion of Failover Groups, and the ability to update Slicer Failover thresholds.
These APIs are:
- POST -
/failover-groupsto create a Failover Group (New) - DELETE -
/failover-groups/{failover_group_id}to delete a Failover Group (New) - PATCH -
/failover-groups/{failover_group_id}to update a Failover Group (Updated)
The code examples in this section use Uplynk's api_auth module.
Create New Failover Group API
A new API has been created for creating a Failover Group:
POST /failover-groups
Request Body Parameters:
| Name | Data Type | Description |
|---|---|---|
| name | String | Name for the new Failover Group * Note: *If same name already used, another will be created with the same name but different system-defined ID to differentiate |
Request Body Example:
{ "name": "NewGroup" }
Sample Code:
import json
import requests
from api_auth import APICredentials, APIParams
class CreateFailoverGroup:
def __init__(self):
self.host = "https://services.uplynk.com"
def run(self):
self._create_failover_group()
def _create_failover_group(self):
failover_group_name = 'MyFailoverGroup' # Replace with the desired failover group name.
url = "{}{}".format(self.host, "/api/v4/failover-groups/")
payload = {
'name': failover_group_name
}
headers = {'Content-Type': 'application/json'}
response = requests.post(
url, params=APIParams(APICredentials()).get_params({}), data=json.dumps(payload), headers=headers
)
print(response.status_code)
CreateFailoverGroup().run() Delete Failover Group API
A new API has been created for deleting a Failover Group:
DELETE /failover-groups/{failover_group_id}
Request URL variable:
| Variable | Description |
|---|---|
| Failover Group ID (Required) | Replace this variable with the system-defined ID assigned to the desired Failover Group Insight: Use the Get All Failover Groups endpoint to retrieve a list of Failover Groups and their system-defined ID |
Sample Code:
import json
import requests
from api_auth import APICredentials, APIParams
class DeleteFailoverGroup:
def __init__(self):
self.host = "https://services.uplynk.com"
def run(self):
self._delete_failover_group()
def _delete_failover_group(self):
failover_group_id = 'd22a96e815f241319677659316d3fb0f' # Replace with the desired failover group ID.
url = "{}{}{}".format(self.host, "/api/v4/failover-groups/", failover_group_id)
headers = {'Content-Type': 'application/json'}
response = requests.delete(
url, params=APIParams(APICredentials()).get_params({}), headers=headers
)
print(response.status_code)
DeleteFailoverGroup().run()Update Failover Group API
The Update Failover Group API has been updated to set failover thresholds and more fields than previously allowed:
PATCH /failover-groups/{failover_group_id}
Request URL Variable:
| Variable | Description |
|---|---|
| Failover Group ID (Required) | Replace this variable with the system-defined ID assigned to the desired Failover Group Insight: Use the Get Failover Group endpoint to retrieve a list of parameters set for a given Failover Group |
Request Body Parameters (include only those to be updated):
| Name | Data Type | Description |
|---|---|---|
| auto_failback | Boolean | Auto-failback when issue is resolved |
| channels | List | List of channels in the Failover Group |
| mode | String | Prioritized, flat, or custom |
| name | String | Name of the Failover Group |
| slicers | List | List of Slicers, each having a dictionary, in the Failover Group |
| thresholds | List | List of Slicer Failover threshold values, including severities, which are in dictionaries |
Request Body Example:
{
"auto_failback": false,
"channels": [ "99994a11ead446e7b4d7a4c91c679999", "88884a11ead446e7b4d7a4c91c678888" ],
"mode": "prioritized",
"name": "My Failover Group",
"slicers": { "slicer1": { "force_blacklist": false, "priority": 1 },
"slicer2": { "force_blacklist": false, "priority": 2 }
},
"thresholds": {
"failover_audio_loss": { "fault_duration": 90, "recovery_duration": 60, "enabled": false, "severity": 5 },
"failover_blackness": { "low": 1, "fault_duration": 120, "recovery_duration": 60, "enabled": false , "severity": 5 },
"failover_cc_last_seen": { "fault_duration": 60, "recovery_duration": 90, "enabled": false , "severity": 5 },
"failover_dropped": { "high": 0, "fault_duration": 5, "recovery_duration": 6, "enabled": false , "severity": 5 },
"failover_input": { "fault_duration": 0, "recovery_duration": 30, "enabled": false , "severity": 5 },
"failover_nielsen_last_seen": { "fault_duration": 60, "recovery_duration": 90, "enabled": false , "severity": 5 },
"failover_proc_q": { "high": 8, "fault_duration": 10, "recovery_duration": 30, "enabled": false , "severity": 5 },
"failover_queue": { "high": 5, "fault_duration": 5, "recovery_duration": 5, "enabled": false , "severity": 5 },
"failover_scte_last_seen": { "fault_duration": 60, "recovery_duration": 90, "enabled": false , "severity": 5 },
"failover_static_audio": { "fault_duration": 90, "recovery_duration": 60, "enabled": false , "severity": 5 },
"failover_static_video": { "fault_duration": 90, "recovery_duration": 60, "enabled": false , "severity": 5 },
"failover_tr_101_290_stats_P1_errors": { "high": 1, "fault_duration": 0, "recovery_duration": 30, "enabled": false, "severity": 5 },
"failover_tr_101_290_stats_P2_errors": { "high": 1, "fault_duration": 0, "recovery_duration": 30, "enabled": false , "severity": 5 },
"failover_video_loss": { "fault_duration": 90, "recovery_duration": 60, "enabled": false },
"failover_involuntary_blackout": { "enabled": false, "severity":5 }
}
}NOTE 1: When specifying Slicers, please note that force_blacklist (set to false to enable Slicer in Failover Group) and priority are required.
NOTE 2: The Get Failover Group API returns threshold values for failover_audio and failover_video, but those are deprecated.
Dictionary Lists in the Update Failover Group API
The "slicers" list of dictionaries contains the names of the Slicers in the Failover Group as well as the priority of each Slicer and whether the Slicer should be enabled or disabled in the Failover Group.
The "thresholds" list of dictionaries maps to the failover thresholds in the Failover Thresholds UI.
The "thresholds" list also contains a severity value for each threshold with the default value being 5 (highest). If severity is not returned by the Get Failover Group endpoint, the value is assumed to be 5.
Thresholds Dictionary List in Update Failover Group API
| Name | Name on Failover Thresholds UI | Description |
|---|---|---|
| failover_audio_loss | Audio Loss | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_blackness | Black Screen | Specifies "low" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_cc_last_seen | CC Last Seen | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_dropped | Dropped Frames | Specifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_input | Input Loss | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_nielsen_last_seen | Nielsen Last Seen | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_proc_q | Processing Queue | Specifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_queue | Upload Queue | Specifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_scte_last_seen | SCTE Last Seen | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_static_audio | Static Audio | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_static_video | Static Video | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_tr_101_290_stats_P1_errors | TR 101 290 P1 Errors | Specifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_tr_101_290_stats_P2_errors | TR 101 290 P2 Errors | Specifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean |
| failover_video_loss | Video Loss | Specifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean |
| failover_involuntary_blackout | Involuntary Blackout | Specifies "enabled" which is a Boolean |
Update Failover Group Sample Code
The example below shows changing Failover Group name, priority of Slicers, and thresholds, including severities. You only need to include items that are changing (e.g., 'name', 'slicers', or 'thresholds'). You only need to include thresholds that are changing.
When changing Slicers, all Slicers need to be included. The force_blacklist value is the inverse of the enable of the Slicer in the Failover Group (set to false to enable Slicer in the Failover Group).
import json
import requests
from api_auth import APICredentials, APIParams
class UpdateFailoverGroup:
def __init__(self):
self.host = "https://services.uplynk.com"
def run(self):
self._update_failover_group()
def _update_failover_group(self):
failover_group_id = '99f7b514f79440bb940812f2eb8954d7' # Replace with the desired failover group ID.
url = "{}{}{}".format(self.host, "/api/v4/failover-groups/", failover_group_id)
payload = {
# Only include 'name, 'slicers', or 'thresholds' if changing values.
'name': 'MyFailoverGroup (Test)', # Change name of failover group.
'slicers': {
"main_slicer": { "force_blacklist": False , "priority": 2}, # Make priority 2.
"backup_slicer": { "force_blacklist": False , "priority": 1} # Make priority 1.
},
'thresholds': {
'failover_static_audio': {
'enabled': True, # Enable static audio threshold.
'severity': 3 # Lower severity from default
},
'failover_tr_101_290_stats_P1_errors': {
# Enable P1 error threshold.
"high": 3,
"fault_duration": 1,
"recovery_duration": 60,
"enabled": True,
"severity": 4
}
}
}
headers = {'Content-Type': 'application/json'}
response = requests.patch(
url, params=APIParams(APICredentials()).get_params({}), data=json.dumps(payload), headers=headers
)
data=json.dumps(payload)
print(data)
print(response.status_code)
UpdateFailoverGroup().run()API Authentication Module (api_auth.py)
The api_auth.py module is used to authenticate Uplynk v4 APIs.
import base64
import os
import zlib, hmac, hashlib, time, json
class APICredentials:
"""
Stores credentials required to request our API.
"""
@property
def user_id(self):
"""
Set your user ID to the one defined on the User Settings page.
"""
return "1234567890abcdefghijklmnopqrstu"
@property
def secret(self):
"""
Set your API key to a value defined on the Integration Keys page.
"""
return "1234567890abcdefghijklmnopqrstuvwxyz1234"
class APIParams(object):
"""
Provides API authentication. Learn more at:
https://docs.uplynk.com
"""
def __init__(self, credentials):
self.credentials = credentials
def get_params(self, data):
"""
Encodes and signs <data> into the expected format and returns it.
"""
data = self._get_params(**data)
data.update(data)
return data
def _get_msg(self, msg=None):
"""
Encodes and returns the 'msg' parameter.
"""
msg = msg if msg else {}
msg.update({
'_owner': self.credentials.user_id,
'_timestamp': int(time.time())
})
msg = json.dumps(msg)
msg_compressed = zlib.compress(msg.encode(), 9)
return base64.b64encode(msg_compressed).strip()
def _get_params(self, **msg):
"""
Returns the message and its signature.
"""
msg = self._get_msg(msg)
sig = hmac.new(
self.credentials.secret.encode(), msg, hashlib.sha256
).hexdigest()
return {
'msg': msg,
'sig': sig
}Updated about 2 hours ago