TYGER SDK
Documentation updated
Add your game to TYGER
Bringing TYGER's adaptive music engine into your game is a creative partnership, not just an API integration. We work closely with each studio to shape the experience around your title — which game events drive the music, what arrangements fit your tone, and how the SDK plugs into your runtime.
If that sounds like something you'd like to explore, drop us a line at contact@tygermedia.ai with a short note about your studio and the game you're working on. Someone from our partnerships team will be happy to set up a conversation and walk you through what's possible. We evaluate each potential partner carefully so we can deliver something great together.
The TYGER app
The SDK is served by the TYGER desktop app for Windows. It runs a small HTTP server on the player's machine; your integration talks to it over localhost. Errors come back as real HTTP status codes with a JSON body, so you can see exactly what went wrong while you integrate.
The TYGER team provides the app build, your API key and a Postman collection when you are onboarded. Playing music requires a free TYGER account: sign in and start the music before you test — with no session open the app plays 30-second previews, and once your session is open every track plays in full, adaptive mode.
Two kinds of integrator use the same API:
- Game studios — your game reports its own moments. Your studio key identifies the game; you never send a game id.
- Game platforms — your platform detects moments in games it doesn't own and forwards them. Your platform key identifies you; each session names the game it drives.
Developer Reference
Local game events REST API
The TYGER SDK is a fire-and-forget REST contract: your client sends game events to the local HTTP ingress and never waits on the response to keep playing. Success is observable in the app — the music reacts.
Wire contract: a request that succeeds returns an empty HTTP 200. A request that fails returns the real status code (401, 403, 409, 422, 500) with a JSON body { "error": "<tag>", "detail": "..." }. The detail field is optional.
Base URL and port
The server binds to 127.0.0.1 (IPv4 loopback) on the player's machine. At startup it takes the first free port from this list:
- Default:
58931 - Fallbacks:
18081,18082,18083
Try the ports in that order and lock in the first one where GET /tyger/health answers 200. A port that refuses the TCP connection is not TYGER.
Authentication
Every route except GET /tyger/health requires an API key, passed as a query parameter on every request:
- Query parameter:
?api_key=<your-api-key>
The TYGER team generates and shares your key when you are onboarded. The kind of key decides how a session names its game:
| Key kind | Identifies | Game |
|---|---|---|
| Studio | one game | implied by the key — never sent |
| Platform | the integrator | game_id in the connect body, from the games your key is allowed to drive |
No key is 401 unauthorized; a key that matches nothing is 403 forbidden. Requests carrying browser fetch metadata (Origin, Sec-Fetch-Site) are refused with 403 forbidden_origin: the ingress is a localhost server and must not be drivable from a web page. Clients written in C++, C#, Go or any non-browser HTTP stack never send these headers.
Session lifecycle
Call connect when your integration starts, game-events as moments happen, disconnect when it stops. No heartbeat is required. Sessions are per API key: your connect never disturbs another integrator's session, and your disconnect only closes yours.
Ending your session
You own the close. TYGER never ends your session for you: not when the game process exits, not after a period without events, not when your client disappears. There is no heartbeat and no idle timeout. Call disconnect:
- when the game exits or the match tracking stops,
- when your integration shuts down — put the call in your shutdown or exit hook, and fire it before your process ends (a 5-second timeout is plenty, then exit anyway),
- when the player leaves your platform or signs out.
If you skip it, the app stays in game mode with the adaptive music running until the player restarts TYGER. A connect on a session that is already open is harmless, so reconnecting after a crash needs no special handling: call connect again and carry on.
Sessions live in memory. After TYGER restarts, game-events answers 409 no_session: call connect again, then resend.
Session ownership
TYGER also detects supported titles on its own. On a machine where your platform observes a game TYGER already detected, both sources report the same game. TYGER runs one game session and decides who owns it:
- Priority: studio key > platform key > TYGER's own detection. The game itself beats an observer, and an explicit "the match started" beats a process sighting. TYGER's own detection is the fallback.
- Takeover: your connect on a game TYGER already owns takes the session over. The music keeps playing; from that moment only your events reach the game and TYGER's own detection is muted. The app shows the game as driven by you (for example Valorant via <your platform>).
- Fallback: your disconnect hands the session back to TYGER's own detection when the game is still running, instead of ending it. When yours is the last claim, the session ends.
- A successful connect does not guarantee ownership. Behind a higher-priority integrator your session is recorded as a fallback: your events are accepted and dropped until you become the owner.
Connecting and retrying
On startup, find the port with GET /tyger/health, then fire POST /tyger/v1.0/session/connect. If the TCP connection refuses, TYGER is not running. Keep retrying with a backoff. Recommended client contract: 5-second request timeout, 10-second retry interval.
ECONNREFUSED— nothing listening on that port. TYGER not running, or it took a fallback port.- Empty
HTTP 200— the session is open. 409 no_sessionongame-events— TYGER restarted or your session was closed. Callconnectagain, then resend.- Other
4xx/5xx— read theerrortag (per-endpoint lists below), log it, retry later if it is transient. - Timeout — TCP accepted but no reply within the deadline. Treat as transient.
Verifying your integration
The HTTP response only tells you the request was accepted. Verify the effect in the app:
- After
connect, the game bar at the bottom of the app shows your game as connected — for a platform key, with your platform name (Valorant via <your platform>). - The music switches to the game's adaptive mode: the idle mix plays while nothing happens.
- Send a
kill: the arrangement changes (victory) and the kill sound effect plays. Send adeath: failure arrangement. After the moment's duration the music returns to idle on its own. - After
disconnect, the game bar shows no game (or the game TYGER detects on its own).
Nothing audible? Check, in this order: the user is signed in, the music is started (press play), sound effects are enabled for the game in the game card's Audio settings, the event name matches the game's vocabulary.
Endpoints
/tyger/health
Liveness check & port discovery
Purpose
Liveness check — confirms TYGER is up and locks in which port it bound to. No API key. Answers an empty 200.
Example
curl "http://127.0.0.1:58931/tyger/health"
/tyger/v1.0/session/connect
Open your session
Purpose
Open a session for the game. A studio key implies the game; a platform key names it with game_id. Calling connect again on an open session is harmless.
Example — studio key
curl -X POST "http://127.0.0.1:58931/tyger/v1.0/session/connect?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Example — platform key
curl -X POST "http://127.0.0.1:58931/tyger/v1.0/session/connect?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "game_id": 21640 }'
Query parameters
| Field | Required | Type |
|---|---|---|
api_key | Yes | string |
Request fields
| Field | Required | Type |
|---|---|---|
game_id | Platform keys only | number — the game's id, from the list your key is allowed to drive |
Errors
401 unauthorized— API key missing.403 forbidden— unknown API key.422 invalid_payload— platform key withoutgame_id(detail: game_id_required), or the body is not JSON.403 forbidden_game—game_idis not on your key's allowed list.500 server_error— the app is still starting or the game is not loaded. Retry later.
/tyger/v1.0/session/disconnect
Close your session
Purpose
Close your session. Further /tyger/v1.0/game-events calls fail with 409 no_session until you connect again. If TYGER's own detection still sees the game, the session falls back to it instead of ending.
Example
curl -X POST "http://127.0.0.1:58931/tyger/v1.0/session/disconnect?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Query parameters
| Field | Required | Type |
|---|---|---|
api_key | Yes | string |
Request fields
| Field | Required | Type |
|---|---|---|
game_id | No | number — platform keys may repeat the connected game; a different id is 409 no_session |
Errors
401 unauthorized— API key missing.403 forbidden— unknown API key.409 no_session— no open session for this API key.
/tyger/v1.0/game-events
Submit game events
Purpose
Submit one or more game events for your open session. Events are applied in order; a batch is accepted as a whole or rejected as a whole.
Example
curl -X POST "http://127.0.0.1:58931/tyger/v1.0/game-events?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "name": "kill" },
{ "name": "death", "data": { "killer": "player" } }
]
}'
Query parameters
| Field | Required | Type |
|---|---|---|
api_key | Yes | string |
Request fields
| Field | Required | Type |
|---|---|---|
events | Yes | array<object> — at least one |
events[].name | Yes | string — see Event names |
events[].data | No | any — passed through to the game's event handler as-is. No supported game reads it today; leave it out unless agreed at onboarding |
Errors
401 unauthorized— API key missing.403 forbidden— unknown API key.409 no_session— no open session for this API key. Call/tyger/v1.0/session/connectfirst.422 invalid_payload— malformed JSON (detail: invalid_json), no body (missing_body), emptyevents(events_required), an event without a stringname(invalid_event), or a body over 64 KiB (payload_too_large).
Event names
Each game has its own vocabulary of moments, agreed with you during onboarding. Names are case-sensitive; a name the game doesn't know is accepted and ignored. Platform keys drive TYGER's supported titles with their existing vocabulary:
| Game | game_id | Event names |
|---|---|---|
| VALORANT | 21640 | kill, death, assist, headshot — kill streaks (first blood, double kill, triple kill, killing spree) are derived from consecutive kill events |
Global errors
Any endpoint can return the following:
403 forbidden_origin— the request carries browser fetch metadata (Origin/Sec-Fetch-Site).404 not_found— the requested route does not exist.500 server_error— an unexpected server-side error while processing the request.