TT developer guide

TT has a small server side that tracks the active configuration, and synchronises it to all viewers. Third party tools can completely replace the streamer UI by talking to the API.

The API is versioned, and currently at version 1. The base address for API version 1 is: https://tt.stephank.nl/api/v1

Authentication

All update requests need to be authenticated using a key. To create a TT key for your app, launch a browser and navigate it to the oauth2/authorize API resource. The user will be prompted to connect with Twitch.

Eventually, Twitch will redirect the user back to the oauth2/verify API resource, which will finish setting up a TT session and show a simple page displaying the key. You can either have the user manually copy/paste the key, or parse the key from the page.

When the user copy/pastes the code, it'll be in the format channel_id:tt_key, which will allow your app to identify the channel ID to use for calling the remaining API resources.

If you want to automatically parse the page, look for the lines: X-TT-Key: ..., X-TT-User-Id: ... and X-TT-User-Name: .... If you're using a library to parse the document, you may extract them from the <script type="text/x-tt-session"> element.

When making API calls, include a header Authorization: Bearer [TT key]. (just the key itself, without the channel ID prefix.)

Configuration format version 1

Version 1 of the API deals with version 1 of the configuration format.

A configuration is a UTF-8 text file with magic TT1\t, and contains lines separated by \n, made up of values separated by \t. A trailing empty line is optional, but recommended.

The first line is a header starting with the TT1 magic, followed by a configuration name, followed by an optional free-form unique ID.

The second line is variable length containing splits, each value the name of the split.

The remaining lines are the run history, in reverse chronological order. Each value in a run is an action taken. An action starts with a type (single character) followed by a positive integer.

Optionally, empty runs may be present indicated by a line with just a dot (.). Such an empty run will often appear at the start of the list to indicate the timer is in a 'clear' state / paused at zero.

Typically, the timer start and pause events alternate, but sometimes the sequence may be broken. This would indicate a timer was interrupted and later resumed, or multiple clients are sending updates in parallel. These scenarios are considered undefined behavior, and up to the client to resolve.

Sending updates

To fetch the current configuration for a Twitch channel, you may send a GET-request to the resource state/[channel ID], where the channel ID is the numeric ID of the Twitch channel. This resource responds with 404 when there is no active configuration, otherwise with 200 and the configuration in the response body.

A PUT or DELETE-request may be sent to the same resource to activate/replace a new configuration, or deactivate the configuration. The request body of a PUT-request contains the new configuration.

You may also send a PATCH-request to this resource to incrementally change the run history. The body of such a request is a single line of \t separated actions to append to the current / first run. In addition, any of the values may be a dot (.) to indicate a new empty run should be started, and prepended to the list as the new current run. A PATCH-request must include a header X-TT-Config-Id that must match the active configuration ID. If the IDs don't match, or you try to append actions when there are no runs, 409 will be returned.

Tools controlling TT typically act as a master, and should not try to account for multiple tools updating the same resources. If a PATCH-request happens to fail, simply make the next request a full update PUT-request.

Uploading images

Splits can have square icons, displayed before their name. These are uploaded as an image-strip, with a maximum height of 128, and the width a multiple of the height. The entire image can be up to 1 MiB, and must be PNG, GIF or JPG.

The first icon in the strip is used as the icon of the configuration itself. The remaining icons are used for the splits, in order.

To upload such an image, send a PUT-request to state/[channel ID] with a multipart/form-data body. Put the regular config in a field config and attach the image in a field image.

Both the response of the PUT-request, and subsequent GET-requests contain a header X-TT-Image-Id containing the ID of the image (a SHA256). The image is now available at image/[image ID], which is where viewers will download it.

If you need to send a PUT-request, but keep the existing image, send a field imageId instead of image, containing just the image ID. Note that you must not rely on any image ID other than from the previous config, because unused images are periodically purged. 400 is returned for invalid image IDs.

Limits

Only one active configuration is stored on the server per channel, and the configuration may not exceed 512 KiB. In addition, configuration patches sent to the API may not exceed 4 KiB. The server will respond with 413 when these limits are exceeded. Exceeding the configuration size limit while patching will cause the server to try and truncate old runs, or respond with 413 if that fails.

Configurations that have not been updated in 2 weeks are automatically purged. Such a purge is more rigorous than the effect of a DELETE-request, as it doesn't notify viewers.

The server relays updates to viewers using Twitch push messages. These messages are throttled to 1 message every 2 seconds, separate from regular TT API request limits. These delays are rarily noticed by viewers, as the overlay has to compensate for stream delay any way. Typically, messages are relayed immediately if not throttled, and otherwise batched in the next push message.

Request limits on the TT API are set to ample amounts, and should not be an obstacle during normal use.

Time synchronisation

The TT configuration format and API are designed such that the latency of requests, notifications and the video stream should not have great effect on the viewer experience.

The configuration contains Unix timestamps that are expected to be taken from a synchronised clock. To accomplish this, the TT overlay and other stock frontends perform naive synchronisation using the Date response header sent by the API.

The TT server is synchronised with the NTP pool, and composes the Date header as it sends out the response to an API request. Naive synchronisation ignores any processing and network latency, and simply takes remembers the difference, which is then taken into account when reading or building a configuration.

Third party clients may perform similar clock synchronisation. If a client needs a TT server clock sample before any request is sent, it may use the ping API resource, which always responds with 204. This resource may also be polled to retrieve more samples and measure latency, though it is subject to normal rate limiting.

If possible, it is recommended clients use a better clock synchronisation mechanism, such as using NTP and the NTP pool servers.