Skip to content
Hoody.com

The Displays Input Actions API provides low-level control over mouse, keyboard, and window operations on a container’s virtual display. Use these endpoints to build automation scripts, capture screenshots after actions, query cursor and window state, and orchestrate multi-step input sequences.

All endpoints are scoped to a single display identified by the *-display-N.* hostname pattern. Override the display with the displayId query parameter when needed.

GET /api/v1/display/input/display-geometry

Section titled “GET /api/v1/display/input/display-geometry”

Returns the current display dimensions and the screen identifier.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"width": 1920,
"height": 1080,
"screen": 0
}
await client.display.input.geometry();
await client.display.input.geometry({ displayId: 2 });
Terminal window
curl -X GET "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/display-geometry?displayId=1"

Executes a single named action and optionally captures a screenshot of the result.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_ActBody schema. An action string is required (e.g. mouse/click, keyboard/type). Pass screenshot: true to capture a frame after the action completes.

{
"success": true,
"action": {
"success": true,
"action": "mouse/click",
"details": {
"button": 1,
"x": 450,
"y": 320
}
},
"screenshot": {
"timestamp": "2025-01-15T10:30:00.000Z",
"image": {
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
"mimeType": "image/png",
"dataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
}
}
}
await client.display.input.act({
action: "mouse/click",
params: { button: 1, x: 450, y: 320 },
screenshot: true,
screenshotDelay: 100
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/act" \
-H "Content-Type: application/json" \
-d '{"action":"mouse/click","params":{"button":1,"x":450,"y":320},"screenshot":true,"screenshotDelay":100}'

Executes a sequence of actions in order. The response reports which actions completed and which failed.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_BatchBody schema. An actions array of 1 to 50 items is required; each item must include an action string.

{
"success": true,
"completed": [
{ "index": 0, "action": "mouse/move", "success": true },
{ "index": 1, "action": "mouse/click", "success": true },
{ "index": 2, "action": "keyboard/type", "success": true }
],
"failed": null,
"skipped": []
}
await client.display.input.batch({
actions: [
{ action: "mouse/move", params: { x: 450, y: 320 } },
{ action: "mouse/click", params: { button: 1 } },
{ action: "keyboard/type", params: { text: "Hello, world!" } }
]
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/batch" \
-H "Content-Type: application/json" \
-d '{"actions":[{"action":"mouse/move","params":{"x":450,"y":320}},{"action":"mouse/click","params":{"button":1}}]}'

Moves the cursor to an absolute position and clicks a mouse button in one operation.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_ClickAtBody schema. x and y coordinates are required; button is optional (default 1).

{
"success": true,
"action": "click-at",
"details": {
"x": 450,
"y": 320,
"button": 1
}
}
await client.display.input.clickAt({ x: 450, y: 320, button: 1 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/click-at" \
-H "Content-Type: application/json" \
-d '{"x":450,"y":320,"button":1}'

Drags from a starting position to an ending position with optional intermediate steps.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_DragBody schema. startX, startY, endX, and endY are required. button defaults to 1; steps controls smoothness.

{
"success": true,
"action": "drag",
"details": {
"startX": 100,
"startY": 100,
"endX": 500,
"endY": 400,
"button": 1,
"steps": 20
}
}
await client.display.input.drag({
startX: 100,
startY: 100,
endX: 500,
endY: 400,
button: 1,
steps: 20
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/drag" \
-H "Content-Type: application/json" \
-d '{"startX":100,"startY":100,"endX":500,"endY":400,"button":1,"steps":20}'

Releases all held inputs as an emergency recovery. Use this when the input state is stuck (for example, after a botched drag or a held modifier key).

This endpoint takes no parameters and no request body.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"action": "reset",
"details": {
"released": ["mouse-button-1", "shift", "ctrl"]
}
}
await client.display.input.reset();
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/reset"

Selects a range by clicking at one position and shift-clicking at another.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_SelectBody schema. x, y, endX, and endY coordinates are required.

{
"success": true,
"action": "select",
"details": {
"x": 200,
"y": 150,
"endX": 600,
"endY": 450
}
}
await client.display.input.select({ x: 200, y: 150, endX: 600, endY: 450 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/select" \
-H "Content-Type: application/json" \
-d '{"x":200,"y":150,"endX":600,"endY":450}'

Moves the cursor, clicks, and types text in a single operation. Useful for filling form fields.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_TypeAtBody schema. x, y, and text are required. delay controls inter-keystroke timing.

{
"success": true,
"action": "type-at",
"details": {
"x": 450,
"y": 320,
"text": "user@example.com",
"delay": 10
}
}
await client.display.input.typeAt({
x: 450,
y: 320,
text: "user@example.com",
delay: 10
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/type-at" \
-H "Content-Type: application/json" \
-d '{"x":450,"y":320,"text":"user@example.com","delay":10}'

Pauses for a duration and optionally captures a screenshot. Useful for waiting for animations or async UI updates.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WaitBody schema. ms (50-30000) is required; screenshot is optional.

{
"success": true,
"action": "wait",
"details": {
"ms": 500
},
"screenshot": {
"timestamp": "2025-01-15T10:30:00.500Z",
"image": {
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
"mimeType": "image/png",
"dataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
}
}
}
await client.display.input.wait({ ms: 500, screenshot: true });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/input/wait" \
-H "Content-Type: application/json" \
-d '{"ms":500,"screenshot":true}'

Presses one or more key combinations in sequence. Each entry may include modifier prefixes like ctrl+ or shift+.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_KeyboardKeyBody schema. keys is an array of 1-20 key strings and is required. window, delay, and clearModifiers are optional.

{
"success": true,
"action": "key",
"details": {
"keys": ["ctrl+c"],
"delay": 0
}
}
await client.display.input.keyboardKey({ keys: ["ctrl+c"] });
await client.display.input.keyboardKey({
keys: ["ctrl+shift+t"],
delay: 50,
clearModifiers: true
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/keyboard/key" \
-H "Content-Type: application/json" \
-d '{"keys":["ctrl+c"]}'

Holds a single key down. Pair with key-up to release, or set holdMs to auto-release.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_KeyboardKeyDownBody schema. key (X11 keysym, e.g. Shift_L, ctrl) is required. window and holdMs (100-60000) are optional.

{
"success": true,
"action": "key-down",
"details": {
"key": "shift"
}
}
await client.display.input.keyboardKeyDown({ key: "shift", holdMs: 2000 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/keyboard/key-down" \
-H "Content-Type: application/json" \
-d '{"key":"shift","holdMs":2000}'

Releases a previously held key.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
NameTypeRequiredDescription
keystringYesKey name (X11 keysym). Maximum length: 100.
windowinteger | stringNoTarget window ID (decimal or hex).
{
"success": true,
"action": "key-up",
"details": {
"key": "shift"
}
}
await client.display.input.keyboardKeyUp({ key: "shift" });
await client.display.input.keyboardKeyUp({ key: "ctrl", window: "0x400001" });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/keyboard/key-up" \
-H "Content-Type: application/json" \
-d '{"key":"shift"}'

Types a literal string of text. Modifier keys are cleared by default before typing.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_KeyboardTypeBody schema. text (max 10000 chars) is required. window, delay, and clearModifiers are optional.

{
"success": true,
"action": "type",
"details": {
"text": "Hello, world!",
"delay": 10
}
}
await client.display.input.keyboardType({ text: "Hello, world!", delay: 10 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/keyboard/type" \
-H "Content-Type: application/json" \
-d '{"text":"Hello, world!","delay":10}'

Returns the current cursor position and the window it is over.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"x": 450,
"y": 320,
"screen": 0,
"window": 12345
}
await client.display.input.mouseLocation();
Terminal window
curl -X GET "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/location"

Sends a mouse click at the current cursor position. Use repeat to click multiple times.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_MouseClickBody schema. All fields (button, repeat, delay, window) are optional; an empty body performs a left click.

{
"success": true,
"action": "click",
"details": {
"button": 1,
"repeat": 1
}
}
await client.display.input.mouseClick({ button: 1, repeat: 2, delay: 50 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/click" \
-H "Content-Type: application/json" \
-d '{"button":1,"repeat":2,"delay":50}'

Sends a double-click at the current cursor position.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
NameTypeRequiredDescription
buttonintegerNoMouse button. Valid range: 1-7. Default: 1.
windowinteger | stringNoTarget window ID (decimal or hex).
{
"success": true,
"action": "double-click",
"details": {
"button": 1
}
}
await client.display.input.mouseDoubleClick({ button: 1 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/double-click" \
-H "Content-Type: application/json" \
-d '{"button":1}'

Presses and holds a mouse button. Pair with mouse/up, or use holdMs to auto-release.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
NameTypeRequiredDescription
buttonintegerNoMouse button. Valid range: 1-7. Default: 1.
windowinteger | stringNoTarget window ID (decimal or hex).
holdMsintegerNoAuto-release after this many milliseconds. Valid range: 100-60000.
{
"success": true,
"action": "mouse-down",
"details": {
"button": 1
}
}
await client.display.input.mouseDown({ button: 1, holdMs: 1500 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/down" \
-H "Content-Type: application/json" \
-d '{"button":1,"holdMs":1500}'

Moves the cursor to an absolute screen position. Coordinates are in display pixels.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_MouseMoveBody schema. x and y (both -65535 to 65535) are required. window, screen (0-15), and sync are optional.

{
"success": true,
"action": "move",
"details": {
"x": 450,
"y": 320
}
}
await client.display.input.mouseMove({ x: 450, y: 320 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/move" \
-H "Content-Type: application/json" \
-d '{"x":450,"y":320}'

Moves the cursor by a relative offset from its current position.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
NameTypeRequiredDescription
xintegerYesHorizontal offset in pixels.
yintegerYesVertical offset in pixels.
syncbooleanNoWait for the move to complete before returning.
{
"success": true,
"action": "move-relative",
"details": {
"x": 25,
"y": -10
}
}
await client.display.input.mouseMoveRelative({ x: 25, y: -10, sync: true });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/move-relative" \
-H "Content-Type: application/json" \
-d '{"x":25,"y":-10,"sync":true}'

Sends a scroll wheel event in a direction. Each click corresponds to one notch of the wheel.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_MouseScrollBody schema. direction (up, down, left, right) is required. clicks (1-100, default 5) is optional.

{
"success": true,
"action": "scroll",
"details": {
"direction": "down",
"clicks": 5
}
}
await client.display.input.mouseScroll({ direction: "down", clicks: 5 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/scroll" \
-H "Content-Type: application/json" \
-d '{"direction":"down","clicks":5}'

Releases a previously held mouse button.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
NameTypeRequiredDescription
buttonintegerNoMouse button. Valid range: 1-7. Default: 1.
windowinteger | stringNoTarget window ID (decimal or hex).
{
"success": true,
"action": "mouse-up",
"details": {
"button": 1
}
}
await client.display.input.mouseUp({ button: 1 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/mouse/up" \
-H "Content-Type: application/json" \
-d '{"button":1}'

Returns the ID of the currently focused window.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"windowId": 12345
}
await client.display.input.windowActive();
Terminal window
curl -X GET "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/active"

GET /api/v1/display/window/{windowId}/geometry

Section titled “GET /api/v1/display/window/{windowId}/geometry”

Returns the position and size of a specific window.

NameInTypeRequiredDescription
windowIdpathstringYesWindow ID (decimal or hex).
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"windowId": 12345,
"x": 100,
"y": 80,
"width": 1024,
"height": 768
}
await client.display.input.windowGeometry("12345");
await client.display.input.windowGeometry("0x400001", { displayId: 2 });
Terminal window
curl -X GET "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/12345/geometry"

GET /api/v1/display/window/{windowId}/name

Section titled “GET /api/v1/display/window/{windowId}/name”

Returns the title of a specific window.

NameInTypeRequiredDescription
windowIdpathstringYesWindow ID (decimal or hex).
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.
{
"success": true,
"windowId": 12345,
"name": "Terminal — bash"
}
await client.display.input.windowName("12345");
Terminal window
curl -X GET "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/12345/name"

Closes a window. The window ID may be passed as a decimal integer or a hex string (0x...).

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowIdBody schema. windowId is required.

{
"success": true,
"action": "close",
"details": {
"windowId": 12345
}
}
await client.display.input.windowClose({ windowId: 12345 });
await client.display.input.windowClose({ windowId: "0x400001" });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/close" \
-H "Content-Type: application/json" \
-d '{"windowId":12345}'

Activates and focuses a window.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowIdBody schema. windowId is required.

{
"success": true,
"action": "focus",
"details": {
"windowId": 12345
}
}
await client.display.input.windowFocus({ windowId: 12345 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/focus" \
-H "Content-Type: application/json" \
-d '{"windowId":12345}'

Minimizes (iconifies) a window.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowIdBody schema. windowId is required.

{
"success": true,
"action": "minimize",
"details": {
"windowId": 12345
}
}
await client.display.input.windowMinimize({ windowId: 12345 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/minimize" \
-H "Content-Type: application/json" \
-d '{"windowId":12345}'

Moves a window to an absolute position. Set relative: true to move by an offset instead.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowMoveBody schema. windowId, x, and y are required. sync and relative are optional.

{
"success": true,
"action": "move",
"details": {
"windowId": 12345,
"x": 200,
"y": 150
}
}
await client.display.input.windowMove({
windowId: 12345,
x: 200,
y: 150,
sync: true
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/move" \
-H "Content-Type: application/json" \
-d '{"windowId":12345,"x":200,"y":150,"sync":true}'

Raises a window to the top of the stacking order without changing focus.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowIdBody schema. windowId is required.

{
"success": true,
"action": "raise",
"details": {
"windowId": 12345
}
}
await client.display.input.windowRaise({ windowId: 12345 });
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/raise" \
-H "Content-Type: application/json" \
-d '{"windowId":12345}'

Resizes a window to a specific width and height. Set useHints: true to use the window manager’s preferred size increments.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowResizeBody schema. windowId, width, and height are required. sync and useHints are optional.

{
"success": true,
"action": "resize",
"details": {
"windowId": 12345,
"width": 1280,
"height": 720
}
}
await client.display.input.windowResize({
windowId: 12345,
width: 1280,
height: 720,
sync: true
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/resize" \
-H "Content-Type: application/json" \
-d '{"windowId":12345,"width":1280,"height":720,"sync":true}'

Searches for windows by name, class, or classname using a regex pattern. Returns matching window IDs.

NameInTypeRequiredDescription
displayIdqueryintegerNoDisplay ID to use (overrides the *-display-N.* hostname pattern). Valid range: 1-999999.

The body follows the display_WindowSearchBody schema. pattern (regex, max 200 chars) is required. name, class, classname, and onlyVisible are optional search filters.

{
"success": true,
"windows": [12345, 67890]
}
await client.display.input.windowSearch({
pattern: "Terminal.*",
name: true,
onlyVisible: true
});
Terminal window
curl -X POST "https://myproj-abc123-display-1.us-east.containers.hoody.icu/api/v1/display/window/search" \
-H "Content-Type: application/json" \
-d '{"pattern":"Terminal.*","name":true,"onlyVisible":true}'