Vfinity2.0 α
Developers

Local API

Run commands, fire events and follow your stream from your own scripts, over HTTP or a WebSocket

Your script

POST /api/trigger
Host: 127.0.0.1:21424
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "name": "hype",
  "data": {
    "name": "mochi"
  }
}
Sending…

Events

API trigger

hype

VTS Hotkey · Star eyes

POST /api/trigger fires every mapping whose API trigger has that name.

Drive Vfinity from a script, a stream deck plugin or your own app on the same computer. Send a JSON message to run any app command or fire one of your events, and listen on a WebSocket for gifts, chat and results as they happen.

The Local API shares one server with your OBS overlays, on the overlay port. It answers only programs running on this computer, and only when they carry your access token.

21424
the shared overlay and API port
Bearer
token on every request
127.0.0.1
this computer only

Alpha

Vfinity 2.0 is an alpha, and features may change between builds. Test your integration again after each update, before you go live.

Turn on the Local API

Open the Local server card

Go to SettingsConnections and scroll to Advanced. Open the Local server card. Its status line reads Listening on http://127.0.0.1:21424 when the server is up.

Switch it on

Turn on Enable local API. Vfinity makes an API access token for you the first time.

Copy the token and the addresses

Click Copy under the token and paste it into your script. The card also lists the two addresses to use, the state URL and the WebSocket URL; click either one to copy it.

Generate token replaces the token. Every script still using the old one is disconnected at once, while overlays and your live connections carry on. You can also type your own token: 32 to 256 letters, digits, dashes or underscores.

The port lives in the same card as Shared server port. A new port takes effect after you restart Vfinity. If the port is busy at launch, Vfinity picks another one and the card shows the address it really uses.

This PC

VfinityVTube Studio8001

Vfinity connects to the VTube Studio API on port 8001 to press hotkeys and move your model.

VfinityOBS · WebSocket server4455

Vfinity connects to the WebSocket server built into OBS, port 4455, to switch scenes and show sources.

OBS · Browser sourceVfinity · Overlay + Local API21424

An OBS browser source opens Vfinity's own server, port 21424, to draw throws, alerts and widgets.

Your scriptsVfinity · Overlay + Local API21424

Your scripts reach the Local API on that same port, 21424, with a token.

VfinityTikTok LIVE · Twitch · Kick · YouTubeInternet

TikTok LIVE, Twitch, Kick and YouTube are reached over the internet. Vfinity opens each of those connections itself.

Arrow: who opens the connection
Port: who listens for it

The Local API and your overlays share one server on 21424. It listens on this computer only.

How requests are checked

Every HTTP request and every WebSocket connection needs this header:

Authorization: Bearer YOUR_TOKEN

A request is refused when it comes from another computer, when the token is missing or wrong, or when it carries a browser Origin header. That last rule means a web page cannot call the API, even one opened on this computer. Use a desktop script or tool that can set headers.

Turning on overlay access for OBS on another PC does not open the API to the network, and the overlay access key is not an API token.

Vfinity has to be running for the API to answer. Hidden in the tray counts; after you quit, nothing is listening.

Send a request over HTTP

RequestBodyAnswer
GET /api/statenoneThe commands you can run, your events, stream numbers and the TikTok connection
POST /api/trigger{"name":"…","data":{…}}{"ok":true} once the trigger is accepted
POST /api/command{"name":"…","args":…}{"ok":true,"result":…}, or {"ok":false,"error":"…"}

Send Content-Type: application/json with every POST. Bodies can be up to 64 KiB.

# What can I run?
curl -H "Authorization: Bearer YOUR_TOKEN" http://127.0.0.1:21424/api/state

# Add 30 seconds to the subathon timer
curl -X POST http://127.0.0.1:21424/api/command \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"timer.add","args":30}'
$headers = @{ Authorization = "Bearer YOUR_TOKEN" }

# What can I run?
Invoke-RestMethod -Uri http://127.0.0.1:21424/api/state -Headers $headers

# Add 30 seconds to the subathon timer
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:21424/api/command `
  -Headers $headers -ContentType "application/json" `
  -Body '{"name":"timer.add","args":30}'

Fire one of your events

Give an event the API trigger and a Trigger Name, then post that name to /api/trigger. The name matches without regard to case.

curl -X POST http://127.0.0.1:21424/api/trigger \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"raid_alarm","data":{"message":"Raid incoming","level":3}}'

Each field in data becomes a template variable the event's steps can use, so a speech step with {message} reads "Raid incoming". Text, numbers and true or false values pass through; nested objects and lists do not. A field name has to start with a letter, and the first 50 fields count.

The answer {"ok":true} means Vfinity accepted the trigger. An event that is switched off, paused, or held by its cooldown still does nothing, so listen on the WebSocket for actionResult if you need to know what ran.

Run a command

Commands are the same named actions hotkeys, Quick Deck pads and command steps use. GET /api/state lists the ones this build offers right now, because some only exist while their part of the app is running.

{ "name": "control.panic" }
{ "name": "deck.press", "args": "Applause" }
{ "name": "giveaway.draw" }
{ "name": "sceneCard.showBrb" }
{ "name": "mapping.trigger", "args": "YOUR_EVENT_ID" }

mapping.trigger runs one of your events as if its trigger had fired, and answers with how many runs it started. It takes an event's ID or an API trigger's name. To get an ID, right-click the event on the Events tab and choose Copy event ID.

Try it
Events Right-click a row
Rose
Lion
Chat command
Every 30 min
Follow

Right-click an event and choose Copy event ID to use it with mapping.trigger. Try right-clicking the row.

Every command is listed with its argument in Commands.

Connect TikTok LIVE from a script

CommandArgumentsWhat it does
tiktok.connectoptional {"username","autoRejoin","waitForLive"}Connects with your saved settings, overridden for this session only
tiktok.disconnectnoneLeaves the LIVE and stops reconnecting
tiktok.cancelRejoinnoneStops waiting or rejoining, and leaves a joined LIVE connected
{
  "name": "tiktok.connect",
  "args": { "username": "yourname", "autoRejoin": true, "waitForLive": true }
}

The answer {"ok":true,"result":{"accepted":true}} means the request was queued, not that the LIVE was joined. Watch the tiktok part of /api/state, or tiktokStatus on the WebSocket: room.state reads "connected" once Vfinity is in the LIVE.

Listen on the WebSocket

Connect to ws://127.0.0.1:21424/api/ws with the same Authorization header. You can send the same requests as over HTTP, each with a requestId you choose, and Vfinity streams what happens on your stream back to you.

// npm install ws
const WebSocket = require('ws');

const socket = new WebSocket('ws://127.0.0.1:21424/api/ws', {
  headers: { Authorization: 'Bearer YOUR_TOKEN' },
});

socket.on('open', () => {
  socket.send(JSON.stringify({ type: 'command', name: 'timer.add', args: 30, requestId: '1' }));
});

socket.on('message', (raw) => {
  const message = JSON.parse(raw);
  if (message.type === 'event' && message.event === 'gift') {
    console.log(`${message.data.nickname} sent ${message.data.giftName}`);
  }
  if (message.type === 'response') console.log(message.requestId, message.data);
});

What you send

{ "type": "state", "requestId": "1" }
{ "type": "command", "name": "timer.add", "args": 30, "requestId": "2" }
{ "type": "trigger", "name": "raid_alarm", "data": {}, "requestId": "3" }

Each gets one reply: {"type":"response","requestId":"2","data":{"ok":true}}.

What Vfinity sends

Prop

Type

A gift that is part of a combo (giftType 1) sends updates while the combo runs. Act on it only when repeatEnd is not false, the way Vfinity does. Timestamps are Unix milliseconds.

The stream is live only: nothing is replayed, and a client that reads too slowly can miss messages.

Limits and errors

You getWhy
HTTP 401The token is missing or wrong, or the request had an Origin header
HTTP 403The request came from another computer
HTTP 503Enable local API is off
HTTP 413The body is over 64 KiB
HTTP 42916 WebSocket clients are already connected
"busy"32 requests are already waiting for an answer
"timeout"No answer within 10 seconds. A command that already started keeps running
"unknownCommand"No command by that name is available right now
"failed"The command ran and failed; message says why
"invalidName"name is missing, empty or longer than 200 characters

Ordinary backups leave the token out and restore with the API switched off. Tick Include passwords and tokens when you back up to keep it.

Let Vfinity connect to you instead

The Trigger API card, also under Advanced, turns the connection around: Vfinity connects as a client to a WebSocket server you run. It suits a server that already exists, such as a game or a bot.

Local API

Your script connects to Vfinity on port 21424, with a token. It can run commands, fire events, read state and receive every live event.

Trigger API

Vfinity connects to your server, by default at localhost on port 8080, with no token. Your server sends triggers and commands and can ask for your API events.

Turn on Trigger API, enter the WebSocket Host and WebSocket Port, then click Connect API. Your server can then send:

{ "type": "trigger", "name": "raid_alarm", "data": { "message": "Raid incoming" } }
{ "type": "command", "name": "timer.add", "args": 30, "requestId": "abc-1" }
{ "type": "request", "requestType": "event_list", "requestId": "abc-2" }

A command with a requestId gets an answer such as {"type":"response","requestType":"command","requestId":"abc-1","data":{"name":"timer.add","ok":true}}. event_list answers with every event that has an API trigger, its steps and whether it is on, and stats answers with connection states and event counts.

Anything that can reach your server can run these commands, so keep the server on this computer or put your own authentication in front of it.