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-groups to 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:

NameData TypeDescription
nameStringName 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:

VariableDescription
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:

VariableDescription
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):

NameData TypeDescription
auto_failbackBooleanAuto-failback when issue is resolved
channelsListList of channels in the Failover Group
modeStringPrioritized, flat, or custom
nameStringName of the Failover Group
slicersListList of Slicers, each having a dictionary, in the Failover Group
thresholdsListList 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

NameName on Failover Thresholds UIDescription
failover_audio_lossAudio LossSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_blacknessBlack ScreenSpecifies "low" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean
failover_cc_last_seenCC Last SeenSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_droppedDropped FramesSpecifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean
failover_inputInput LossSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_nielsen_last_seenNielsen Last SeenSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_proc_qProcessing QueueSpecifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean
failover_queueUpload QueueSpecifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean
failover_scte_last_seenSCTE Last SeenSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_static_audioStatic AudioSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_static_videoStatic VideoSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_tr_101_290_stats_P1_errorsTR 101 290 P1 ErrorsSpecifies "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_errorsTR 101 290 P2 ErrorsSpecifies "high" level which is an integer, "fault_duration" and "recovery_duration" in seconds, and "enabled" which is a Boolean
failover_video_lossVideo LossSpecifies "fault_duration" and "recovery_duration" in seconds and "enabled" which is a Boolean
failover_involuntary_blackoutInvoluntary BlackoutSpecifies "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
        }

Did this page help you?