# 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](/captivate-api/javascript-api-reference.md) because this API depends upon that.

### MDNS Discovery (Bonjour) <a href="#mdns-discovery-bonjour" id="mdns-discovery-bonjour"></a>

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:

```javascript
{
  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 <a href="#simple-variable-update-method" id="simple-variable-update-method"></a>

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`](/api-examples/sample-controllers-tour/01-schedule-action.md) 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:**

```sh
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 <a href="#using-the-advanced-api-over-http" id="using-the-advanced-api-over-http"></a>

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](/captivate-api/advanced-api-reference/additional-http-endpoints.md).

### Using the Advanced API over TCP <a href="#using-the-advanced-api-over-tcp" id="using-the-advanced-api-over-tcp"></a>

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\n`)

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

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

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

### Using the Advanced API over UDP <a href="#using-the-advanced-api-over-udp" id="using-the-advanced-api-over-udp"></a>

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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.newbluefx.com/captivate-api/advanced-api-reference/tcp-udp-and-http-connections.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
