Skip to content

Automation API Overview

ZestSSH Squeezed includes an automation API that allows external apps to trigger SSH commands on your saved connections without opening ZestSSH’s UI. This enables integration with Tasker (Android), Shortcuts (iOS), webhooks, and other automation tools.

The automation system has two entry points:

  1. URL Scheme (zestssh://) --- Works on all platforms. External apps open a URL, and ZestSSH intercepts it.
  2. Android Intents --- Android-specific. External apps send a targeted intent to ZestSSH’s service component.

Both entry points feed into the same internal automation engine:

External App
|
v
[URL Scheme / Android Intent]
|
v
[Deep Link Service] --- validates, parses, rate-limits
|
v
[Automation Provider] --- checks Squeezed status, API key, enabled flag
|
v
[Automation Service] --- headless SSH: connect, execute, disconnect
|
v
[Result] --- returned to caller + logged to automation history

Every automation request must include a valid API key. Keys are:

  • 48 characters of alphanumeric characters, generated by a cryptographically secure random number generator (CSPRNG backed by the OS’s /dev/urandom equivalent).
  • Providing approximately 285 bits of entropy.
  • Stored in the platform’s secure keychain (Android Keystore, iOS Keychain, desktop equivalents).
  • Validated using constant-time comparison (SHA-256 hash comparison) to prevent timing attacks.
  • Tracked with last used timestamps and optional expiration dates.
  1. Create: Settings > Automation > Manage API Keys > Create Key. Assign a label and optional expiration.
  2. Use: Pass the key in each automation request.
  3. Rotate: Create a new key, update your automation tasks, then delete the old key.
  4. Revoke: Delete a key to immediately invalidate it.

You can create multiple keys (e.g. one per Tasker profile, one per Shortcuts workflow) and revoke them independently.

To protect against brute-force API key guessing, the lockout escalates with repeated failures rather than staying fixed:

  • After 5 consecutive failed API key validations, ZestSSH locks out all automation requests for 1 minute.
  • After 10 consecutive failures, the lockout extends to 5 minutes; after 15 or more, to 30 minutes (the cap).
  • A request presenting a valid, unexpired key still succeeds even while a lockout from earlier bad attempts is active. The lockout only throttles further guessing, never a legitimate request.
  • The lockout counter and timestamp are persisted to secure storage, so restarting the app does not bypass the lockout.
  • Successful validation resets the failure counter to 0 and clears any active lockout.
  • Expired keys are treated as invalid and contribute to the failure counter.
  • ZestSSH Squeezed entitlement --- Automation is a Squeezed-only feature. Free-tier users receive a clear error message when automation is attempted.
  • Automation enabled --- The user must toggle automation on in Settings > Automation. It can be disabled to block all external command execution.
  • Valid API key --- Every request must include a key that passes validation.

The automation engine uses headless SSH execution:

  1. Connects to the target server using the saved connection’s credentials.
  2. Runs the command via SSHClient.execute() (no PTY allocated).
  3. Captures stdout and stderr.
  4. Returns the exit code, output, elapsed time, and success/failure status.
  5. Disconnects.

This is designed for non-interactive commands. Commands that require a PTY (like top or interactive editors) will not work correctly in automation mode.

Each command has a configurable timeout (default: 30 seconds, maximum: 300 seconds --- larger values are clamped to 300). The timeout covers the entire lifecycle: TCP connect, SSH authentication, command execution, and output collection.

In automation mode, host keys are not trusted on first use. A host that has never been connected to from this device is rejected --- the user must first connect to it interactively (from the hosts grid) so they can verify the fingerprint out-of-band and enroll it in known hosts. After enrollment, automation to that host succeeds. Changed host keys are also rejected to protect against man-in-the-middle attacks. There is no interactive prompt in headless mode.

The connection parameter in automation requests is resolved in two steps:

  1. Exact ID match (UUID) --- highest priority.
  2. Exact label match (case-insensitive).

Automation deliberately does not fall back to partial or substring matching. connection=prod matches only a connection whose ID or label is exactly prod (case-insensitive); it will not match “Production Server”. This exact-or-nothing rule prevents an ambiguous name from silently running a command on the wrong host.

Every automation execution is logged to an on-device database with:

  • Timestamp
  • Action type (execute, snippet, batch, workflow, connect)
  • Connection ID
  • Command
  • stdout, stderr
  • Exit code
  • Success/failure status
  • Elapsed time in milliseconds

The log retains up to 500 entries (oldest are trimmed automatically). View it at Settings > Automation > Log.

ActionDescriptionReference
executeRun a command on a single connectionEndpoints
snippetRun a saved snippet by name with optional variablesEndpoints
batchRun a command across multiple connectionsEndpoints
workflowRun a multi-step workflow by name or IDEndpoints
connectVerify connectivity to a connectionEndpoints