TCP, UDP, and HTTP Connections

Our primary API operates over a websocket connection with various JavaScript wrapper libraries. However, websocket communication is not universally supported and can be cumbersome to implement from outside the context of a browser. Therefore, we provide three additional communication methods:

  • TCP socket (persistent communication)

  • UDP socket (one-shot communication)

  • HTTP GET/POST endpoints (two-way communication using chunked responses)

Each of these methods gives you new ways to access the ServiceHandler.scheduler object, and each of these endpoints handles data communication in roughly the same way (although the method of connecting to them is different).

Before reading further, make sure you are familiar with the Controller API because this API depends upon that.

MDNS Discovery (Bonjour)

We broadcast our API using MDNS (bonjour) technology with the following PTR names:

  • _newblue._tcp.local

  • _newblue._udp.local

In the answers, you will see the following service names (IDENTIFIER will be constructed from the computer’s IP address):

  • Captivate-WS-API-[IDENTIFIER]._newblue._tcp.local: WebSocket API service

  • Captivate-HTTP-API-[IDENTIFIER]._newblue._tcp.local: Advanced API over HTTP

  • Captivate-TCP-API-[IDENTIFIER]._newblue._tcp.local: Advanced API over TCP

  • Captivate-UDP-API-[IDENTIFIER]._newblue._udp.local: Advanced API over UDP

  • Captivate-UDP-FinishLynx-[IDENTIFIER]._newblue._udp.local: Experimental FinishLynx support

You may also query for the following deprecated PTR name:

  • _captivate-tcp-api._tcp.local

A PTR query on one of our service names (names must be exact, do not use a trailing dot) will return an answer for each of our services with the following structure:

{
  answers: [
    {
      name: '_newblue._tcp.local',
      type: 'PTR',
      ttl: 120,
      class: 'IN',
      flush: false,
      data: 'Captivate-WS-API-192-168-10-50._newblue._tcp.local'
    }
  ],
  additionals: [
    {
      name: 'Captivate-WS-API-192-168-10-50._newblue._tcp.local',
      type: 'SRV',
      ttl: 120,
      class: 'IN',
      flush: true,
      data: {
        weight: 0,
        priority: 10,
        port: 9023,
        target: 'Captivate-WS-API-192-168-10-50._newblue._tcp.local'
      }
    },
    {
      name: 'Captivate-WS-API-192-168-10-50._newblue._tcp.local',
      type: 'A',
      ttl: 120,
      class: 'IN',
      flush: true,
      data: '192.168.10.50'
    },
    {
      name: 'Captivate-WS-API-192-168-10-50._newblue._tcp.local',
      type: 'TXT',
      ttl: 4500,
      class: 'IN',
      flush: true,
      data: [
        'hlp=default qwebchannel-based api',
        'ip=192.168.10.50',
        'id=3z4jv021t',
        'port=9023'
      ]
    }
  ]
}
  • The PTR record will contain the name of the SRV record which will include a unique identifier for that service.

  • The SRV record will expose the port for that service.

  • The A record that will give the IP address.

Simple Variable Update method

Because the majority of external APIs really only need to update variables, we have implemented a simplified endpoint for doing just that.

Send a POST request with Content-type: application/json to /api/action/ACTION/TARGET/TARGET_NAME with the following:

  • ACTION needs to be one of the scheduleAction actions such as render, update, still, animateIn, animateOut, etc.

  • TARGET can be either input or title.

  • When targeting an input, TARGET_NAME should be the full name of the data controller connected to the title layer.

  • When targeting a title, TARGET_NAME may be either the textual name of the title as it shows up in the project list, or the internal title id for the title.

  • The request body should be a simple mapping of variable names to values encoded as JSON.

Example:

curl -H 'Content-type: application/json' \
     --data '{"Home Score": 13}' \
     'http://localhost:9022/api/action/update/input/Scoreboard%20OCR%3A%20Basketball'

Using the Advanced API over HTTP

The HTTP endpoint is exposed at port 9022 at path /api. This port must not be in use when Captivate launches or the HTTP endpoint will not be able to start.

The HTTP endpoint responds to GET requests at /api with a brief help text similar to the TCP welcome message.

To send an API command, send a POST request to /api with Content-type: application/json and a JSON-encoded string as the request body.

To subscribe to Captivate’s notification stream, send a GET request to /api/subscribe. The server will keep the connection open and reply with a chunked HTTP response. Each notification from Captivate will be served as a JSON-encoded string chunk.

Note: We also support a number of extra methods over HTTP. You can see documentation for them here.

Using the Advanced API over TCP

The TCP endpoint is exposed at port 9025. This port must not be in use when Captivate launches or the TCP endpoint will not be able to start.

When a client connects, a welcome message will be sent from Captivate. The welcome message will be something like this:

CAPTIVATE HELLO
=======================================
We support a subset of Titler's API over direct TCP socket communication using JSON.

All messages are terminated with CRLF. '\r\n'


To call "scheduleCommand", send a JSON-encoded string that will decode with the following fields:

  - command: The name of the command to run
  - parameters: The parameters as an object
  - variables: The variables as an object

  The results of the command will be output as a JSON-encoded string.

To call "scheduleAction", send a JSON-encoded string that will decode with the following fields:

  - action: The name of the action to schedule
  - input: The name of the input / data controller to target
  - title: The id of the title / graphic layer to target
  - variables: The variables as an object

  The results of the command will be output as a JSON-encoded string.

Additionally, as long as you are connected, we will send you Titler's notification stream.
-------------------------------------------------------------------------------------------
BEGIN DATA

The welcome message ends with:

  • The text BEGIN DATA

  • Two sets of CRLF. (\r\n\r)

After the welcome message, all messages sent to or from this socket will be JSON-encoded strings, terminated with one set of CRLF. (\r)

As long as this client is connected to the TCP endpoint, all notification messages and signals will be sent to the client.

Note: If a client connects and immediately sends a message, the server will not send the welcome message and will also not subscribe the client to notification messages and signals. If you connected with an immediate message and want to subscribe to notification messages send the command subscribe with empty parameters and variables.

Example for Mac:

MSG=$'{"command": "subscribe"}\r\n'
( echo $MSG; sleep 10; ) | nc localhost 9025

Using the Advanced API over UDP

The UDP endpoint is exposed at port 9026. This port must not be in use when Captivate launches or the UDP endpoint will not be able to start.

The UDP endpoint expects to receive a JSON-encoded string and will immediately attempt to process the API call.

There is no notion of a “response” in UDP communication, but the server will attempt to send API responses to the same client and port used by the sender.

Last updated