Developer Reference

Local game-events REST API

Served in-process by the TYGER background window via overwolf.web.createServer (GameEventsOverwolfHttpService). Enable with pmso.gameEventsOverwolfHttpEnabled in pmsettings.json.

Overwolf runtime note: Public Overwolf docs describe each request as a RequestEvent with url, content (string body), and contentType only. There is no documented way to set HTTP status or response body; the app attempts optional response helpers if the runtime provides them. Integrators should not rely on response JSON until verified on a real Overwolf build.

Base URL and port

The server binds to localhost. The first successful port is chosen from this list:

  1. pmso.gameEventsHttpPort (default 58931)
  2. Fallbacks: 18081, 18082, 18083, 58931

When listening succeeds, debug logs may show the URL (e.g. http://127.0.0.1:<port>/). GET /health includes listeningUrl in the intended JSON response when supported.

Request body format

For any route that expects a body, send Content-Type: application/json and a UTF-8 JSON object as the request body. The Overwolf layer passes that payload as the content string on RequestEvent; the app parses it with JSON.parse.

Authentication

If pmso.gameEventsHttpToken is a non-empty string, every route except GET /health requires a matching credential:

  • Query parameter: ?token=<your-token>
  • JSON field on POST bodies: "token": "<your-token>"
  • Header: Authorization: Bearer <your-token> or X-Tyger-Events-Key: <your-token>

If gameEventsHttpToken is empty or whitespace, auth is disabled (localhost trust only).

Session lifecycle

External clients should call connect with the target Overwolf game class ID, then send game-events batches where classId matches that session, then disconnect when finished.

After ingest, GameEventPipeline requires classId to match the currently running game reported by Overwolf (runningGameIndex); otherwise events are dropped.

Endpoints

Purpose

Liveness check; returns service identity and whether a client session is connected.

Auth

None — /health is always allowed even when gameEventsHttpToken is set.

Intended JSON response

{
  "ok": true,
  "service": "tyger-game-events-overwolf",
  "sessionConnected": false,
  "listeningUrl": "http://127.0.0.1:58931/"
}

Purpose

Open an external session for a single classId. Replaces any previous session.

Request fields

FieldRequiredType / format
classIdYesJSON number, finite (Overwolf game class ID, e.g. Fortnite 21216).
tokenConditionalString; required only when gameEventsHttpToken is set and no other auth method is used.

Example body

{
  "classId": 21216,
  "token": "your-shared-secret"
}

Validation

  • Body must parse as JSON; otherwise { "error": "invalid_json" } (intended HTTP 400).
  • classId must be a finite number; otherwise { "error": "classId_required" } (intended 400).

Intended JSON response (success)

{ "ok": true, "classId": 21216 }

Purpose

Clear the external session so further /v1/game-events calls fail until connect again.

Request fields

PartRequiredFormat
BodyNoEmpty body or {} is fine. If present, must be valid JSON.
tokenConditionalSame as connect when token auth is enabled.

Intended JSON response (success)

{ "ok": true }

Purpose

Submit one or more GEP-shaped game events for the active external session.

Request fields

FieldRequiredType / format
classIdYesFinite number; must equal the classId from the current session.
eventsYesNon-empty JSON array of event objects.
events[].nameYesNon-empty string (event name, e.g. "kill").
events[].dataNoAny JSON value; forwarded if present (GEP parity).
tokenConditionalString; for auth when configured.

Example body

{
  "classId": 21216,
  "events": [
    { "name": "kill", "data": "" },
    { "name": "death", "data": { "killer": "player" } }
  ],
  "token": "your-shared-secret"
}

Validation (order matters)

  • Valid JSON body.
  • Session must be connected and body.classId must equal session classId; else intended 409 with { "error": "session_required_or_classId_mismatch" }.
  • classId must be a finite number; else { "error": "classId_invalid" }.
  • events must be a non-empty array; else { "error": "events_required" }.
  • Each element must be an object with non-empty string name; else { "error": "invalid_event", "index": i }.

Pipeline behavior

Events are passed to GameEventPipeline.ingestFromExternalHttp(classId, { events }, …). The pipeline drops the batch unless Overwolf reports a running game whose id equals classId.

Intended JSON response (success)

{ "ok": true, "delivered": 1 }

delivered is a fixed success indicator from the HTTP layer (not a count of downstream consumers).

Other paths

Any path not listed above receives an intended 404 with body { "error": "not_found" } (after auth, when token is required).

Error reference

HTTP (intended)errorWhen
400invalid_jsonBody present but not valid JSON.
400classId_requiredConnect without finite classId.
400classId_invalidGame-events: bad classId after session check.
400events_requiredMissing or empty events array.
400invalid_eventAn element of events is not an object with a non-empty string name.
401unauthorizedToken required but not provided or does not match.
404not_foundRoute does not exist.
409session_required_or_classId_mismatchNo session open, or body classId ≠ session classId.