WINK Streaming

Command API Reference
Version 1.4.9.1
Document Updated: August 2026
WINK Streaming, Inc.

Table of Contents

Overview

This document provides a comprehensive reference for the WINK Streaming Command API, covering WINK Forge, WINK Archive, and WINK Media Router appliances. The API enables programmatic control of video streaming operations, user management, and system administration.

Supported Products

API Architecture

The WINK API uses XML-based messaging over HTTPS, providing:

Note: This document does not cover WINK Crossroad integration APIs or third-party integration commands, which are documented separately.

Getting Started

Authentication

All API calls require authentication using the following XML structure:

<wink_api user='username' pass='password' key='shared_key'>
    <req id='unique_id' command='command_name'>payload</req>
</wink_api>

Authentication Parameters

Parameter Required Description
user Yes API username (must have API access level)
pass Yes User password
key Optional Shared key for enhanced security

SSL Requirements

All API endpoints require SSL/HTTPS connections. Configure SSL certificates through:

  1. Navigate to Settings → System Options → SSL Certificate
  2. Generate self-signed certificate or upload existing certificate
  3. For development, use the --insecure flag with cURL to bypass certificate validation

Example Connection

curl -X POST https://10.130.90.188/api/ \
    --insecure \
    --data-urlencode "<wink_api user='apiuser' pass='apipass'>
        <req id='1' command='version'></req>
    </wink_api>" \
    -H 'Content-Type: application/xml'

API Testing Tool

WINK Forge includes a built-in API testing interface:

API Testing Tool

Access via: Tools → API Tester

  • Test commands without external tools
  • View formatted responses
  • Save command history
  • Export results

Built-in API testing interface

WINK Forge API Commands

1. Version

Command version
Description Returns the API version number
Payload None
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='version'></req>
</wink_api>
Response
<wink_api>
    <resp id="1" command="version" status="ok">1.4</resp>
</wink_api>
Return Value Numeric API version (e.g., "1.4")

2. Input Control - Start, Stop, Restart

Command start | stop | restart
Description Controls transcoding operations for input streams
Payload GUID of the input stream or 'all' for all streams
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='restart'>WF05-2657-1C04-7F1B-5EC0</req>
</wink_api>
Response
<wink_api>
    <resp id="1" command="restart" status="ok">WF05-2657-1C04-7F1B-5EC0</resp>
</wink_api>
Return Value GUID of affected input or error message
Tip: Use 'all' as the payload to control all streams simultaneously. This is useful for system-wide maintenance or emergency stops.

3. IP Based Input Control

Command startip | stopip
Description Controls transcoding based on IP:Port combination
Payload IP address and port (format: IP:PORT)
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='stopip'>10.130.90.68:554</req>
</wink_api>
Response
<wink_api>
    <resp id="1" command="stopip" status="ok">WF05-2657-1C04-7F1B-5EC0</resp>
</wink_api>
Return Value GUID of the affected input

GUID Operations

4. Get GUID

Command getguid
Description Returns GUID for a specific IP:Port combination
Payload IP and Port (e.g., 10.130.90.199:554)
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='getguid'>10.130.90.199:8382</req>
</wink_api>
Response
<wink_api>
    <resp id="1" command="getguid" status="ok">WF05-2657-1C04-7F1B-5EC0</resp>
</wink_api>

5. GUID Status

Command guidstatus
Description Returns the current status of a stream
Payload GUID string
Response Values
  • 0 = Not publishing
  • 1 = Publishing
  • 2 = Blocked
  • 3 = Set as unavailable

6. Block GUID

Command blockguid
Description Blocks video output from viewers
Payload Options
  • GUID - Block stream (default)
  • GUID@0 - Unblock stream
  • GUID@2 - Block stream
  • GUID@3 - Mark as unavailable
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='blockguid'>WF05-2657-1C04-7F1B-5EC0</req>
</wink_api>
Note: Blocked streams display a placeholder image instead of live video. This is useful for privacy compliance or content moderation.

7. Unblock GUID

Command unblockguid
Description Restores video output to viewers
Payload GUID string

IP-Based Operations

8. Block IP

Command blockip
Description Blocks video based on IP:Port without knowing GUID
Payload IP:Port combination (e.g., 10.130.90.199:554)
Response Returns the GUID of the blocked stream

9. Unblock IP

Command unblockip
Description Restores video based on IP:Port
Payload IP:Port combination

Stream Management

10. Input Stream Properties

Command input_source
Description Creates or updates video input configuration
Required (New)
  • title - Stream title
  • desc - Stream description
  • path - Input URI
  • type - Protocol (RTSP, MJPEG, HTTP, UDP, TCP, etc.)
Required (Update) guid - Existing stream GUID
Optional Parameters
fpsFrame rate (decimal)
widthVideo width in pixels
heightVideo height in pixels
croptopPixels to crop from top
croprightPixels to crop from right
cropbottomPixels to crop from bottom
cropleftPixels to crop from left
rotateRotation (90, 180, 270, 0)
deinterlace1=on, 0=off
ptz_avail1=PTZ available, 0=none
enabled1=enabled, 0=disabled
usrlogic_idLogical ID number
usrgroupGroup assignment
usrlatLatitude coordinate
usrlongLongitude coordinate
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='input_source'>
        <input title='Test Camera' 
               desc='Testing stream' 
               type='RTSP' 
               path='rtsp://192.168.1.100:554/stream1'
               fps='30'
               width='1920'
               height='1080'
               enabled='1' />
    </req>
</wink_api>

11. Input Stream Delete

Command input_delete
Description Removes video input and associated outputs
Payload GUID string
Warning: Deleting an input stream permanently removes all associated output streams. This action cannot be undone.

User Management

12. Create User

Command createuser
Description Creates a local user account
Parameters
  • name - Full name
  • username - Login username
  • password - User password
  • md5 - true/false (password hashing)
  • access - Access level:
    • 1 = Admin
    • 2 = Operator
    • 3 = Viewer
    • 4 = API Only
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='createuser'>
        <name>Billy Armstrong</name>
        <username>billy</username>
        <password>SecurePass123!</password>
        <access>2</access>
    </req>
</wink_api>

13. Delete User

Command deleteuser
Description Removes a user account
Payload XML with username

14. Change Password

Command changepassword
Description Updates user password
Parameters
  • username - Target user
  • password - New password
  • md5 - true if pre-hashed

System Operations

15. Event Logger

Command log
Description Adds entry to system event log
Payload Log message string
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='log'>API integration test successful</req>
</wink_api>

16. Flush Logs

Command flushlogs
Description Clears the event log
Payload None

17. Reboot Server

Command reboot
Description Initiates system reboot
Payload None
Response Error message or immediate reboot
Warning: This command immediately reboots the system. Ensure all critical operations are complete before executing.

WINK Archive API Commands

Firmware Requirements: Version 1.1 or greater

Archive File Naming: Files are automatically named using the pattern:
TITLE_[YYYY-MM-DD_HH.MM.SS]_GUID.mp4
Example: EastSideSony_[2015-04-03_13.06.18]_WMA5-6E0F-1C04-86F2-E5C4.mp4

1. Version

Same as WINK Forge version command - returns API version number.

2. Archive Control

Commands archiver_start | archiver_stop
Description Controls video archiving operations
Payload GUID or blank (blank = all archivers)
Behavior If already recording, creates overlapping instance to ensure no content loss
Example
<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='archiver_start'>WMA5-6E0F-1C04-86F2-E5C4</req>
</wink_api>
Storage Management: Archives automatically maintain 85% disk capacity by removing oldest files when threshold is reached.

3. Archiver Status

Command archiver_status
Description Returns archiver configuration and status
Payload GUID or blank (blank = all archivers)
Response
<wink_api>
    <resp id="11" command="archiver_status" status="ok">
        <archiver guid="WMA5-6E0F-1C04-86F2-E5C4" 
                  title="TV2" 
                  desc="Conference Room Feed" 
                  type="RTMP" 
                  path="rtmp://10.130.90.10/public/stream_high" 
                  segmenttime="5" 
                  meta1="Building A" 
                  meta2="Floor 2" 
                  meta3="Room 201" 
                  meta4="PTZ Camera" 
                  enabled="1" />
    </resp>
</wink_api>

4. Archiver Source

Command archiver_source
Description Create or modify archiver configuration
Parameters
  • guid - Required for updates
  • title - Archiver name
  • desc - Description
  • type - Input type (RTMP, RTSP, HTTP)
  • path - Source URI
  • segmenttime - Recording duration (5-60 minutes)
  • meta1-4 - Metadata tags
  • enabled - 1=enabled, 0=disabled

5. Archive Delete

Command archiver_delete
Description Stop and remove archiver
Payload GUID

WINK Media Router API

One-Time Password (OTP) Authentication

The OTP system provides secure, time-limited access to video streams. Key features:

OTP Workflow Diagram

  1. Application requests OTP token from Media Router
  2. Media Router generates unique token with expiration
  3. Application provides token to client
  4. Client uses token to access video stream
  5. Token expires after set duration or use

OTP authentication flow

Default Settings: OTP tokens expire after 60 minutes by default. All tokens can be cleared via the Web Administration OTP section.

OTP Endpoints & Token Usage

The OTP actions live on two different paths. Token creation and token management are handled separately:

Action Endpoint
create http://router.example.com/otp/api/
extend | query | destroy http://router.example.com/api/v1/otp/

Both endpoints accept form-encoded HTTP POST data and require apiuser and apipass on every request.

Passing the Token in a Stream URL

The token is appended to the playlist request as an otp query parameter, alongside an expires timestamp:

http://router.example.com/200/public/hls/<stream>.m3u8?otp=a1b2c3d4e5f6&expires=1691234567

Only the .m3u8 request needs the token. Segment requests inherit the authenticated session, so there is no need to rewrite individual .ts URLs.

Token Scope Across Multiple Routers

Tokens are cluster-wide across a deployment. A token created on one Media Router is valid on every Media Router in that deployment, so a five-router deployment still requires only one token per viewer session. For this to work, the API credentials must be defined identically on each Media Router.

One Token Per Session: A single token must not be shared by all visitors to a site. Issue a token per viewer session so that expiry, extension, and revocation apply to one viewer at a time and the audit trail stays meaningful.

1. Create OTP Token

Command create
Method HTTP POST
Endpoint /otp/api/
Parameters
apiuser / apipass API credentials Required
action create Required
duration Minutes, 1 to 900 (default: 60) Optional
hash_type alpha | numeric | alphanumeric Default: alphanumeric
hash_length Max 128 (default: 32) Optional
expiry_url Redirect URL on expiry Optional
expiry_message Custom expiry message Optional
Example
curl -d "apiuser=apiuser&apipass=apipass&action=create&duration=15&hash_type=numeric&hash_length=20" \
     -X POST http://router.example.com/otp/api/
Response 24814928371014572819
Notes The create call returns the raw token string on its own, with no wrapper or formatting. Errors are returned as 0: followed by a description (for example 0:Invalid Login).

2. Destroy/Extend OTP

Commands destroy | extend
Description Manage existing OTP tokens
Endpoint /api/v1/otp/
Parameters
  • apiuser / apipass - API credentials
  • action - destroy or extend
  • token - Existing token string
  • duration - Minutes, 1 to 900 (for extend only)
Example
curl -d "apiuser=apiuser&apipass=apipass&action=extend&token=24814928371014572819&duration=900" \
     -X POST http://router.example.com/api/v1/otp/
Response Success | Failed

3. Query Token

Command query
Description Returns token expiration time
Endpoint /api/v1/otp/
Parameters
  • apiuser / apipass - API credentials
  • action - query
  • token - Token to query
Example
curl -d "apiuser=apiuser&apipass=apipass&action=query&token=24814928371014572819" \
     -X POST http://router.example.com/api/v1/otp/
Response Format YYYY-MM-DD HH:MM:SS

OTP Integration FAQ

The questions below come up regularly during web portal and partner integrations.

How is the token passed in the video URL?

As an otp query parameter on the playlist request, alongside an expires timestamp:

http://router.example.com/200/public/hls/<stream>.m3u8?otp=a1b2c3d4e5f6&expires=1691234567

Only the .m3u8 request needs it. Segment requests inherit the authenticated session, so individual .ts URLs do not need to be rewritten.

Can one token be shared by all visitors?

No. Issue a token per viewer session. Sharing a single token across every visitor removes the ability to expire, extend, or revoke access for one viewer, and it makes the access log useless for audit purposes.

Do we need one token per Media Router, or one for the whole deployment?

One. Tokens are cluster-wide, so a token created for a session spans every Media Router in the deployment. Define the API credentials the same way on each Media Router.

Which endpoint handles which action?

Both paths are in use, and the actions live on different ones:

Create parameters are action=create, duration=<minutes>, hash_type=<alpha|numeric|alphanumeric>, and hash_length=<max 128, default 32>, plus apiuser and apipass. The create call returns the raw token string on its own. action=query returns the expiration as YYYY-MM-DD HH:MM:SS.

What duration should we set, and how should expiry be handled?

duration is in minutes and accepts 1 through 900. With per-session tokens, start short - on the order of the length of a typical visit - and call extend for sessions that are still watching, rather than issuing long-lived tokens up front.

On expiry_url versus expiry_message: for a public website, neither should be the primary mechanism. Have the page request a fresh token when one lapses; that is a cleaner experience than a redirect mid-stream. Setting expiry_message is worth doing as a fallback, so anything that does slip through shows a sensible message in the player instead of a bare failure.

Are there rate limits on the OTP API?

The limit is high enough that per-session token creation is not a concern - hundreds of requests per second are permitted. Contact support if a deployment is expected to exceed that.

Do existing stream URLs survive a firmware upgrade?

Yes. Stream URLs are unchanged by the upgrade; the paths documented for a deployment stay the same.

OTP Code Examples

The cURL calls above show the raw requests. The examples below show the same calls in context, issuing and maintaining one token per viewer session.

Keep Credentials Server-Side: apiuser and apipass must never be exposed to a browser. Tokens are created by your backend, and only the resulting token reaches the client.

PHP: Per-Session Token

Creates a token on the visitor's first request, reuses it for the rest of the session, and extends it when it is close to lapsing:

<?php
session_start();

// Create and manage live on different paths
$otp_create = 'https://router.example.com/otp/api/';
$otp_manage = 'https://router.example.com/api/v1/otp/';
$api_user   = 'apiuser';
$api_pass   = 'apipass';
$playlist   = 'https://router.example.com/200/public/hls/WF05-333F-4D5C-E636-2937.m3u8';
$duration   = 15;   // minutes, 1-900

function otp_post($url, $fields) {
    $options = array(
        'http' => array(
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'method'  => 'POST',
            'content' => http_build_query($fields),
            ),
        );

    $result = @file_get_contents($url, false, stream_context_create($options));
    return ($result === false) ? '' : trim($result);
}

// Still watching and the token is nearly up - extend rather than issue a second one
if (!empty($_SESSION['otp_token']) && ($_SESSION['otp_expires'] - time()) < 60) {

    $resp = otp_post($otp_manage, array(
        'apiuser'  => $api_user,
        'apipass'  => $api_pass,
        'action'   => 'extend',
        'token'    => $_SESSION['otp_token'],
        'duration' => $duration
        ));

    if ($resp === 'Success') {
        $_SESSION['otp_expires'] = time() + ($duration * 60);
    } else {
        unset($_SESSION['otp_token']);   // extend failed - fall through and create
    }
}

// No token yet (or the extend failed) - create one for this session
if (empty($_SESSION['otp_token'])) {

    $token = otp_post($otp_create, array(
        'apiuser'     => $api_user,
        'apipass'     => $api_pass,
        'action'      => 'create',
        'duration'    => $duration,
        'hash_type'   => 'alphanumeric',
        'hash_length' => 32
        ));

    // Errors are returned as "0:" followed by a description
    if ($token === '' || substr($token, 0, 2) === '0:') {
        die('OTP API error: ' . htmlspecialchars($token));
    }

    $_SESSION['otp_token']   = $token;
    $_SESSION['otp_expires'] = time() + ($duration * 60);
}

// Only the .m3u8 carries the token - segment requests inherit the session
$video_url = $playlist
           . '?otp=' . urlencode($_SESSION['otp_token'])
           . '&expires=' . $_SESSION['otp_expires'];

// Serving the same values as JSON is all the JavaScript example below needs:
// header('Content-Type: application/json');
// echo json_encode(array('token' => $_SESSION['otp_token'], 'expires' => $_SESSION['otp_expires']));
?>

JavaScript: Player Integration

The page asks its own backend for the session's token, builds the playlist URL, and requests a fresh token shortly before the current one lapses:

let session = null;   // { token: "a1b2c3d4e5f6", expires: 1691234567 }

async function getSessionToken() {
    const res = await fetch('/otp-token.php', { credentials: 'same-origin' });
    if (!res.ok) {
        throw new Error('Token request failed: ' + res.status);
    }
    return res.json();
}

function playlistUrl(playlist) {
    return playlist
        + '?otp=' + encodeURIComponent(session.token)
        + '&expires=' + session.expires;
}

async function startStream(playlist) {
    session = await getSessionToken();

    const video = document.getElementById('player');
    const url = playlistUrl(playlist);

    if (video.canPlayType('application/vnd.apple.mpegurl')) {
        video.src = url;           // Safari and other native HLS players
    } else {
        hls.loadSource(url);       // hls.js or the player of your choice
    }

    scheduleRefresh(playlist);
}

// Refresh before expiry rather than letting playback fail. This is cleaner than
// redirecting mid-stream with expiry_url; keep expiry_message set as a fallback.
function scheduleRefresh(playlist) {
    const msRemaining = (session.expires * 1000) - Date.now() - 60000;   // 60s headroom

    setTimeout(async function () {
        session = await getSessionToken();   // backend extends, or creates a new token

        const video = document.getElementById('player');
        if (video.canPlayType('application/vnd.apple.mpegurl')) {
            video.src = playlistUrl(playlist);
        } else {
            hls.loadSource(playlistUrl(playlist));
        }

        scheduleRefresh(playlist);
    }, Math.max(msRemaining, 5000));
}

startStream('https://router.example.com/200/public/hls/WF05-333F-4D5C-E636-2937.m3u8');

C#: OTP Client

A small client wrapping the three actions, suitable for an ASP.NET application holding one token per user session:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Threading.Tasks;

public class WinkOtpClient
{
    private static readonly HttpClient Http = new HttpClient();

    private readonly string _createUrl;   // https://router.example.com/otp/api/
    private readonly string _manageUrl;   // https://router.example.com/api/v1/otp/
    private readonly string _user;
    private readonly string _pass;

    public WinkOtpClient(string createUrl, string manageUrl, string user, string pass)
    {
        _createUrl = createUrl;
        _manageUrl = manageUrl;
        _user = user;
        _pass = pass;
    }

    private async Task<string> PostAsync(string url, Dictionary<string, string> fields)
    {
        fields["apiuser"] = _user;
        fields["apipass"] = _pass;

        using (var content = new FormUrlEncodedContent(fields))
        {
            var response = await Http.PostAsync(url, content);
            response.EnsureSuccessStatusCode();
            return (await response.Content.ReadAsStringAsync()).Trim();
        }
    }

    // Returns the raw token string. Errors arrive as "0:Invalid Login"
    public async Task<string> CreateAsync(int durationMinutes = 15)
    {
        var token = await PostAsync(_createUrl, new Dictionary<string, string>
        {
            { "action", "create" },
            { "duration", durationMinutes.ToString() },   // 1-900
            { "hash_type", "alphanumeric" },
            { "hash_length", "32" }
        });

        if (token.StartsWith("0:"))
        {
            throw new InvalidOperationException("OTP API error: " + token);
        }

        return token;
    }

    public async Task<bool> ExtendAsync(string token, int durationMinutes = 15)
    {
        var result = await PostAsync(_manageUrl, new Dictionary<string, string>
        {
            { "action", "extend" },
            { "token", token },
            { "duration", durationMinutes.ToString() }
        });

        return result == "Success";
    }

    public async Task<DateTime> QueryAsync(string token)
    {
        var expires = await PostAsync(_manageUrl, new Dictionary<string, string>
        {
            { "action", "query" },
            { "token", token }
        });

        return DateTime.ParseExact(expires, "yyyy-MM-dd HH:mm:ss",
                                   CultureInfo.InvariantCulture);
    }

    public async Task<bool> DestroyAsync(string token)
    {
        var result = await PostAsync(_manageUrl, new Dictionary<string, string>
        {
            { "action", "destroy" },
            { "token", token }
        });

        return result == "Success";
    }

    // Only the .m3u8 carries the token - segments inherit the session
    public static string BuildPlaylistUrl(string playlist, string token, DateTimeOffset expires)
    {
        return string.Format("{0}?otp={1}&expires={2}",
                             playlist,
                             Uri.EscapeDataString(token),
                             expires.ToUnixTimeSeconds());
    }
}

Usage, holding one token per session:

var otp = new WinkOtpClient("https://router.example.com/otp/api/",
                            "https://router.example.com/api/v1/otp/",
                            "apiuser", "apipass");

var token   = await otp.CreateAsync(15);
var expires = new DateTimeOffset(await otp.QueryAsync(token), TimeSpan.Zero);

var videoUrl = WinkOtpClient.BuildPlaylistUrl(
    "https://router.example.com/200/public/hls/WF05-333F-4D5C-E636-2937.m3u8",
    token, expires);

// Later, while the session is still watching:
await otp.ExtendAsync(token, 15);

// When the session ends:
await otp.DestroyAsync(token);

Code Examples

JavaScript Integration

Complete JavaScript function for API communication:

function exec_api_command() {
    // Update UI
    document.getElementById("resp_payload").value = "Sending API Command";
    
    // Get connection details
    var api_host = document.getElementById("req_ipaddr").value;
    var payload = document.getElementById("req_payload").value;
    
    // Create request
    var xhttp = new XMLHttpRequest();
    
    // Handle response
    xhttp.onreadystatechange = function() {
        if (xhttp.readyState == 4 && xhttp.status == 200) {
            document.getElementById("resp_payload").value = xhttp.responseText.trim();
        }
    };
    
    // Send request
    xhttp.open("POST", "https://" + api_host.trim() + "/api/", true);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(payload);
}

// Example usage
var xmlPayload = `<wink_api user='apiuser' pass='apipass'>
    <req id='1' command='guidstatus'>WF05-1EDA-1C04-6E33-ABF9</req>
</wink_api>`;

// Call function with payload
document.getElementById("req_payload").value = xmlPayload;
exec_api_command();

Python Integration

import requests
import xml.etree.ElementTree as ET

class WinkAPI:
    def __init__(self, host, username, password, verify_ssl=True):
        self.host = host
        self.username = username
        self.password = password
        self.verify_ssl = verify_ssl
        self.api_url = f"https://{host}/api/"
    
    def execute_command(self, command, payload="", req_id="1"):
        # Build XML request
        xml_request = f"""<wink_api user='{self.username}' pass='{self.password}'>
            <req id='{req_id}' command='{command}'>{payload}</req>
        </wink_api>"""
        
        # Send request
        response = requests.post(
            self.api_url,
            data=xml_request,
            headers={'Content-Type': 'application/xml'},
            verify=self.verify_ssl
        )
        
        # Parse response
        root = ET.fromstring(response.text)
        resp = root.find('resp')
        
        return {
            'status': resp.get('status'),
            'command': resp.get('command'),
            'data': resp.text
        }

# Example usage
api = WinkAPI('10.130.90.188', 'apiuser', 'apipass', verify_ssl=False)

# Get version
version = api.execute_command('version')
print(f"API Version: {version['data']}")

# Check stream status
status = api.execute_command('guidstatus', 'WF05-1EDA-1C04-6E33-ABF9')
print(f"Stream Status: {status['data']}")

cURL Examples

Basic Commands

# Get API version
curl -X POST https://forge.example.com/api/ \
    --insecure \
    --data-urlencode "<wink_api user='apiuser' pass='apipass'><req id='1' command='version'></req></wink_api>" \
    -H 'Content-Type: application/xml'

# Start all streams
curl -X POST https://forge.example.com/api/ \
    --insecure \
    --data-urlencode "<wink_api user='apiuser' pass='apipass'><req id='1' command='start'>all</req></wink_api>" \
    -H 'Content-Type: application/xml'

# Create OTP token
curl -d "apiuser=apiuser&apipass=apipass&action=create&duration=60" \
     -X POST https://router.example.com/otp/api/

Advanced Examples

# Create new input with full configuration
curl -X POST https://forge.example.com/api/ \
    --insecure \
    --data-urlencode "<wink_api user='apiuser' pass='apipass'>
        <req id='1' command='input_source'>
            <input title='Conference Room' 
                   desc='Main conference room HD camera' 
                   type='RTSP' 
                   path='rtsp://admin:password@192.168.1.100:554/stream1'
                   fps='30'
                   width='1920'
                   height='1080'
                   ptz_avail='1'
                   usrlat='41.8781'
                   usrlong='-87.6298'
                   enabled='1' />
        </req>
    </wink_api>" \
    -H 'Content-Type: application/xml'

Notes & Best Practices

API Versioning

Performance Considerations

Security Best Practices

Integration Tips

Development Tip: The API Testing tool in WINK Forge (Tools → API Tester) can export command templates in various programming languages.

Customer Support

Contact Information

Email Support support@wink.co
Phone Support +1-312-281-5433
Corporate Website https://www.wink.co

Support Requirements

When contacting support, please provide:

Additional Resources

Programming Language Examples: Contact WINK Support for examples in your preferred programming language. While availability isn't guaranteed, we maintain samples for Python, PHP, Java, C#, and Node.js.

© 2025 WINK Streaming, Inc. All rights reserved.

Document Version: 1.4.9.1 - Updated August 2026

Original Issue: August 2022