Skip to content

Command reference

Send commands as JSON objects with a top-level type. See Getting started for connection and authentication, or download the AsyncAPI specification for every message schema.

Keep one command awaiting a response at a time: replies do not echo a client request ID. Check their type, because output events can arrive between responses. An expired client timeout does not cancel the operation.

RequestParametersResponse
AUTHkey: authentication keyAUTH_OK; otherwise AUTH_ERROR and disconnection
events arrayInput events, without a command typeNo acknowledgement
getStateNonestate broadcast; see decoding

The server sends CONNECT with info and authRequired on connection. Send AUTH first when required. Place commands at the root of the message, never inside events.

RequestParametersResponse and data
GET_CURRENT_MAPPINGSNoneCURRENT_MAPPINGS: {profile, profiles, mappings}
GET_PROFILE_MAPPINGSRequired profile: namePROFILE_MAPPINGS: {profile, mappings, requestId}; ignore requestId
GET_TEMPLATE_PROFILESNoneTEMPLATE_PROFILES: array of {name, mappings, outputTypes}
MCP_SWITCH_PROFILERequired profile: nameMCP_PROFILE_SWITCHED: {profile, mappings}
MCP_IMPORT_MAPPINGSmode, mappings, and name for a new profileMAPPINGS_IMPORTED: {profile, mappings, mode}
{"type":"GET_PROFILE_MAPPINGS","profile":"Twitchat"}

Names are matched without case sensitivity after trimming spaces. An unknown profile returns an empty mapping array when read; switching to it returns ERROR. Switching profiles follows the application’s subscription rules. The MCP_ commands are also available to ordinary WebSocket clients.

Use mode: "new" with a non-empty name to create and activate a profile, or mode: "append" to add to the active profile. mappings is required; only the first 500 entries are retained. Appending replaces existing mappings with the same output.type and output.code. Save a copy before changing a profile.

A mapping contains input: {type, code, settings?} and output: {type, code, value}. It can also contain id, description, groupId, groupOperator, groupSettings, position, targetProfile and mute. Use an existing mapping or template as your starting point; the specification provides the supported fields and codes.

Descriptions are limited to 200 characters. New profile names are cleaned and limited to 50 characters; a duplicate name is an error. Invalid mappings return ERROR. Without a subscription, an in-app dialog asks how to import. Complete it promptly: a response can time out after 15 seconds while the import remains pending. Check the app before retrying.

RequestParametersResponse and data
GET_SETTINGSNoneSETTINGS_STATE: {settings, hints}
SET_SETTINGRequired key; either boolean value or toggle: trueSETTING_APPLIED: {key, value}

settings contains the available boolean settings; hints explains selected keys. Use exactly one of value and toggle.

{"type":"SET_SETTING","key":"toggleOutput","value":false}

Common keys are toggleOutput (live main output), toggleGamepad, toggleKeyboard, toggleMouseOutput, allowWebsocketOutput, websocketFullSpeed, toggleOverlay and autoStartMainOutput (startup behavior). releaseAll releases active controls: send value: true; the returned value is false because this is a one-shot action.

SET_SETTING cannot change allowSerialOutput, allowHIDOutput, unlockInputMute, toggleInputBlocking, requireWebsocketAuth, enableAnalytics, enablePostHog or enableCrisp. Change these in the application. Unknown or read-only keys return ERROR.

Enabling WebSocket, MCP or external AI disables automatic WebSocket output; enable output afterwards if needed. Disabling the last setting keeping the server active can close the connection before a reply arrives.

RequestParametersResponse and data
NAVIGATE_TORequired page; optional tab, editMappingId, profileNAVIGATED: {page, tab}
GET_CURRENT_PAGENoneCURRENT_PAGE: {page, tab, pathname}, values can be null

Use a real application path, such as /dashboard, /discover, /mapping, /mapping-v2, /overlay, /inputs, /outputs, /facetester, /settings, /changelog, /premium, /gameDiscovery or /helpdesk. A missing leading slash is added. /agent opens a separate window; /gamepads and /connections are legacy redirects.

Tabs include gamepads, mobile, websocket-mcp for inputs; receiver, 8bitdo, opentrack for outputs; and options, design, advanced, whats-new, debug, account for settings. Some tabs depend on application settings.

On a mapping page, numeric editMappingId opens that mapping for editing; profile can select its profile. These fields take precedence over tab. NAVIGATED acknowledges the navigation request, not completion of the page. CURRENT_PAGE.page normally omits the leading slash; pathname includes it. /gameDiscovery is reported as game-discovery.

These commands need the application’s native desktop controls and the relevant operating-system permissions. Keep PlayAbility running.

RequestParametersResponse and data
LIST_WINDOWSNoneWINDOWS_LIST: {windows: [{id, name}]}
GET_DISPLAYSNoneDISPLAYS_LIST: {displays: [...]}
WINDOW_GET_PROPERTIESWindow selection belowWINDOW_PROPERTIES: {title, region: {left, top, width, height}}
WINDOW_MOVEWindow selection; x, y (default 0, 0)WINDOW_MOVED: {success: true}
WINDOW_RESIZEWindow selection; width, height (default 800, 600)WINDOW_RESIZED: {success: true}
WINDOW_FOCUSWindow selectionWINDOW_FOCUSED: {success: true}
GET_MOUSE_CURSOR_POSITIONNoneMOUSE_POSITION: {x, y}

To select a window, use windowTitle and optional windowTitleMatch: contains (default), exact or startsWith. Matching ignores case and selects the first result. Alternatively, use activeWindowOnly: true, which takes precedence over a title. With neither field, the active window is the default; activeWindowOnly: false then requires a title.

Window-list IDs are temporary enumeration indices, not selectors. Use finite coordinates and positive sizes. A missing matching window returns ERROR.

Each display has id, bounds, workArea, scaleFactor, scalePercent, rotation, isPrimary and label. Bounds and work areas contain {x, y, width, height} and can have negative coordinates. Cursor results are native coordinates; cursor input uses logical coordinates, so account for display scaling.

Send TAKE_SCREENSHOT with these optional fields:

ParameterValues and defaults
formatfile (default), base64, both, dataUrl
qualityJPEG quality, integer 1–100; default 80
maxWidth, maxHeightPositive integers. maxWidth, otherwise maxHeight, otherwise 1024 sets a single maximum dimension for both sides.
activeWindowOnlyCapture the active window
windowTitle, windowTitleMatchCapture a matching window; matching rules as above
region{x, y, width, height} within the screen; omitted fields use screen defaults

Selection priority is active window → title → region → full screen. There is no displayId selector. Window capture reads a screen region, so obscured or minimized content may not be captured as expected.

SCREENSHOT_DATA.data contains width, height (capture dimensions before resizing) and timestamp (Unix milliseconds), plus:

FormatReturned fields
filefilePath: local temporary-directory path, not a URL
base64buffer: raw Base64 string
bothfilePath and buffer
dataUrldataUrl: string prefixed data:image/jpeg;base64,

Saved files persist; manage their retention. Some installations can return PNG bytes despite JPEG metadata, so inspect the bytes if your client requires a guaranteed format.

Errors have {type, error}, with a human-readable message. Most failures use ERROR; screenshot failures can use SCREENSHOT_ERROR, cursor lookup failures MOUSE_POSITION_ERROR, and invalid credentials AUTH_ERROR. There is no stable numeric error code or public request ID.

Unknown command types may receive no reply. Invalid input events may also receive no error. Add a timeout and handle disconnection; use the client examples as a starting point.