HTTP API
While running, Stash serves a set of HTTP control endpoints for querying runtime state, switching proxy groups, refreshing remote resources, and diagnosing DNS, proxies, and routing. The endpoints stay compatible with the Clash control API, so existing Clash dashboards can connect to Stash directly; on top of that, Stash adds its own endpoints under /stash and /diagnosis.
Enabling and Authentication
- iOS / tvOS: Turn on external control under Settings - External Access and set an API secret. The page lists the addresses an external controller can connect to.
- macOS: Configure the control port in Settings; the default is
9090.
Every request carries the secret in the Authorization header:
Authorization: Bearer <API secret>When a WebSocket client cannot set custom headers, pass the secret as the token query parameter instead, e.g., /traffic?token=<API secret>.
The endpoints that run scripts or read and write script storage only accept requests from the local loopback address, and only when a secret is set.
Basics
| Method | Path | Description |
|---|---|---|
| GET | / | App version, OS version, device ID, architecture, and platform |
| GET | /version | Version number |
| GET | /configs | Current mode, log-level, and the mixed proxy port |
| PATCH | /configs | Switch the mode; body {"mode": "rule"} with rule, global, or direct |
| GET | /logs | Live log stream; accepts a level parameter |
| GET | /traffic | Current upload and download rates with totals |
| GET | /stash/speed | Current rates and totals |
Connections
| Method | Path | Description |
|---|---|---|
| GET | /connections | Active connections with source, destination, matched rule, and proxy chain |
| GET | /connections/{id} | Details and log of one connection |
| DELETE | /connections/{id} | Close the connection |
| GET | /http | Recent requests captured by the HTTP engine |
| GET | /http/{id} | Full request and response of one captured HTTP request |
Rules
| Method | Path | Description |
|---|---|---|
| GET | /rules | The rules in effect |
| GET | /rules/count | Total rule count, with rule sets counted by their entries |
| GET | /rules/match | Report which rule and outbound a destination would match, without opening a connection |
Query parameters of /rules/match:
target: Required. A domain,domain:port, or IP address.network:tcporudp,tcpby default.port: Destination port, 443 by default; a port insidetargetwins.process,user-agent: A simulated process path and User-Agent forPROCESS-NAME,PROCESS-PATH, andUSER-AGENTrules.src-ip,src-port: A simulated source address and port forSRC-IPandSRC-PORTrules.resolve: Whether DNS resolution may run for the match,trueby default.
The response includes the matched rule (type, payload, and index), the final outbound, the proxy chain, the resolution outcome, and the number of rules evaluated.
Proxies and Groups
| Method | Path | Description |
|---|---|---|
| GET | /proxies | Every proxy and group with latency and current selection |
| PUT | /proxies/{name} | Change a group’s selection; body {"name": "<proxy name>"} |
| GET | /proxies/{name}/delay | Run one latency test on the proxy and return the result |
| GET | /proxies/{name}/info | Details of the proxy |
| GET | /stash/proxies | Proxy names |
| GET | /stash/proxy/count | Proxy count |
| GET | /stash/proxy/display/v2 | The summary the app’s group page uses |
| PUT | /stash/proxy/delay/{name} | Trigger a latency test for the proxy |
Tailscale proxies have their own endpoints: GET /proxies/{name}/tailscale returns the node status, GET /proxies/{name}/tailscale/stream pushes status changes, POST /proxies/{name}/tailscale/login and /logout start login and logout, and PUT or DELETE /proxies/{name}/tailscale/exit-node set or clear the exit node.
Remote Resources
| Method | Path | Description |
|---|---|---|
| GET | /providers/proxies | Remote proxy sets and their nodes |
| PUT | /providers/proxies/{name} | Update the proxy set now |
| GET | /providers/proxies/{name}/healthcheck | Run latency tests on the set’s nodes |
| GET | /providers/rules | Rule sets |
| PUT | /providers/rules/{name} | Update the rule set now |
| GET | /providers/scripts | Scripts |
| PUT | /providers/scripts/{name} | Update the script now |
| GET | /providers/geodb | GeoIP / ASN database information |
| PUT | /providers/geodb/{name} | Update the database now |
| PUT | /stash/provider | Update every remote resource now |
DNS
| Method | Path | Description |
|---|---|---|
| GET | /dns/record | DNS cache contents: question, record type, answers, answering server, and cost |
| GET | /dns/count | Number of cached entries |
| GET | /dns/resolve/{host} | Resolve a domain through the current DNS configuration and return the record |
| POST | /dns/flush | Flush the DNS cache |
Diagnosis
| Method | Path | Description |
|---|---|---|
| GET | /diagnosis/dns | Test each configured DNS server, reporting name, cost, and error |
| GET | /diagnosis/dns/latency | DNS resolution latency |
| GET | /diagnosis/proxies | Test each proxy for HTTP and UDP connectivity |
| GET | /diagnosis/traceroute | Trace the route to a destination |
| GET | /diagnosis/usedMemory | Memory the core currently uses |
| GET | /diagnosis/availableMemory | Available memory |
Query parameters of /diagnosis/traceroute: target (required), proxy (an explicit outbound; the rules decide when omitted), direct (true traces the direct path), and maxHops and probes (maximum hops and probes per hop). The response first reports the routing decision (matched rule, outbound, and chain), then one hop at a time, with each address annotated with its country, ASN, and organization. A destination that goes through a proxy is traced only as far as the proxy server.
Scripts
| Method | Path | Description |
|---|---|---|
| POST | /script/evaluate | Run a script in a mock environment and return its output, logs, notifications, and elapsed time |
| GET / POST | /script/runtime/store/{key} | Read or write script persistent storage |
Request body fields of /script/evaluate: script (required, the script source), engine (webkit or jsc), timeout (seconds), argument, and name.
Live Updates
List endpoints such as /traffic, /connections, /http, /dns/record, /proxies, and /diagnosis/dns/latency can be upgraded to WebSocket connections. After the upgrade, Stash pushes the full data once, then pushes again whenever the data changes, at the interval set by the interval query parameter in milliseconds. /diagnosis/dns and /diagnosis/proxies are WebSocket-only and stream each test result as it completes.
Dashboard
GET /dashboard serves the built-in web dashboard, which can be opened directly in a browser.