Local HTTP server for external applications to communicate with a running MetaScalp instance.
Host: 127.0.0.1 Ports: 17845–17855 CORS enabled for all origins. Full documentation
Getting started: 1. Launch MetaScalp — the API server starts automatically. 2. Discover the port with GET /ping. 3. Send commands to switch tickers or open combos.
Scan ports 17845–17855 to find the running MetaScalp instance. Returns the app name and version.
Changes the current ticker. The active window is always notified. When a named binding is provided, that binding's linked panels are also updated.
Accepts two request formats: a ticker pattern string (e.g. BINANCE:BTCUSDT.p) or explicit fields (exchange + market + ticker).
A binding is a named group of linked panels inside MetaScalp (e.g. a chart, order book, and trade feed showing the same ticker). Bindings are numbered "001"–"500" and configured by the user in the MetaScalp UI.
| Binding value | Active window | Named binding |
|---|---|---|
| omitted / empty | notified | — |
"001" … "500" | notified | notified |
EXCHANGE:SYMBOL.suffix — suffix: .p (futures), .m (margin), .o (options), omitted (spot)_, /, -, $, :.BINANCE:BTCUSDT.p, BYBIT:ETHUSDT, OKX:BTC-USDT.m, HYPERLIQUID:BTCUSDT.p, HYPERLIQUID:cash:HOODUSDT0.p-, _, /) are auto-stripped: btc-usdt, BTC/USDT, BTCUSDT all resolve to the same ticker.
Opens a combo layout for the specified ticker in the MetaScalp UI. The ticker field is a symbol (e.g. BTCUSDT), not a pattern — the combo opens on the currently active exchange and market connection. The symbol is normalized: case-insensitive, separators (-, _, /) are stripped, and the SWAP suffix is removed.
| Value | Exchange |
|---|---|
| 2 | Binance |
| 3 | GateIo |
| 4 | Bybit (classic) |
| 5 | KuCoin |
| 6 | BybitUta (Unified Trading Account) |
| 7 | Bitget |
| 8 | Mexc |
| 10 | Okx |
| 11 | BingX |
| 12 | HTX |
| 13 | BitMart |
| 14 | LBank |
| 15 | HyperLiquid |
| 16 | UpBit |
| 17 | AsterDex |
| 18 | Moex |
| 19 | Lighter |
| Value | Type | Description |
|---|---|---|
| 0 | Spot | Spot trading |
| 1 | Futures | Generic futures |
| 2 | UsdtFutures | USDT-margined futures |
| 3 | CoinFutures | Coin-margined futures |
| 4 | InverseFutures | Inverse futures |
| 5 | UsdtPerpetual | USDT perpetual swaps |
| 6 | UsdcPerpetual | USDC perpetual swaps |
| 7 | Margin | Margin (cross/isolated) |
| 8 | Options | Options contracts |
| 9 | Stock | Stock / equity markets |
.p suffix auto-resolves to the right futures type. For explicit fields, 2 (UsdtFutures) is the most common choice for perpetual futures.All errors return HTTP 400 with a JSON body.
| Endpoint | Condition | Error message |
|---|---|---|
| /api/change-ticker | Missing fields | Invalid request body. Provide 'tickerPattern' or 'exchange'+'market'+'ticker'. |
| /api/change-ticker | Invalid pattern | Invalid ticker pattern: '{pattern}' |
| /api/change-ticker | Binding not found | Binding '{name}' not found. Available: {list} |
| /api/change-ticker | No connection | No connection found for exchange ... and market ... |
| /api/change-ticker | Ticker not on connection | Ticker '{ticker}' not found on connection {id} |
| /api/combo | Missing ticker | Invalid request body. 'ticker' is required. |
| /api/combo | Handler not ready | Combo handler not registered |
| any unknown path | — | Not found |
| wrong HTTP method | — | Method not allowed |
Local HTTP server for external applications to communicate with a running MetaScalp instance.
127.0.0.1 (localhost only)17845–17855 (first available port is used)application/jsonAccess-Control-Allow-Origin: *. OPTIONS preflight is supported on all routes.1. Launch MetaScalp — the local API server starts automatically.
2. Discover the port — scan 17845–17855 with GET /ping to find the running instance.
3. Send commands — use POST /api/change-ticker to switch the active ticker, or POST /api/combo to open a combo layout.
Scan the port range to find the running MetaScalp instance.
GET http://127.0.0.1:{port}/ping
Response 200 OK:
{ "app": "MetaScalp", "version": "0.0.9" }
Switches the active ticker in MetaScalp. The active window is always notified. When a named binding is provided, that binding's linked panels are notified as well.
POST http://127.0.0.1:{port}/api/change-ticker
Content-Type: application/json
The endpoint accepts two request formats. Include either tickerPattern or the exchange + market + ticker fields.
| Field | Type | Required | Description |
|---|---|---|---|
tickerPattern | string | yes | Pattern string (see Ticker pattern format below). |
binding | string | no | Named binding ("001"–"500"). Omit or send empty string to only notify the active window. |
| Field | Type | Required | Description |
|---|---|---|---|
exchange | integer | yes | Exchange identifier (see Exchange values below) |
market | integer | yes | Market type identifier (see MarketType values below) |
ticker | string | yes | Trading pair symbol, e.g. "BTCUSDT" |
binding | string | no | Named binding ("001"–"500"). Omit or send empty string to only notify the active window. |
A binding is a named group of linked panels inside MetaScalp (e.g. a chart, order book, and trade feed that should all show the same ticker). Bindings are numbered "001" through "500" and are configured by the user inside the MetaScalp UI. When you send a binding name with a request, all panels assigned to that binding will switch to the new ticker.
binding value | Active window notified | Named binding notified |
|---|---|---|
| omitted / empty / null | yes | — |
"001" … "500" | yes | yes |
200 OK — ticker changed successfully:
{ "status": "ok" }
400 Bad Request — validation error:
{ "error": "..." }
Possible error messages:
| Condition | Error message |
|---|---|
| Missing fields | Invalid request body. Provide 'tickerPattern' or 'exchange'+'market'+'ticker'. |
| Invalid pattern format | Invalid ticker pattern: '{pattern}' |
| Binding name not found | Binding '{name}' not found. Available: {list} |
| No connection for exchange + market | No connection found for exchange {exchange} and market {market} |
| Ticker not available on connection | Ticker '{ticker}' not found on connection {id} |
Using ticker pattern:
curl -X POST http://127.0.0.1:17845/api/change-ticker \
-H "Content-Type: application/json" \
-d '{"tickerPattern": "BINANCE:BTCUSDT.p", "binding": "001"}'
Using explicit fields:
curl -X POST http://127.0.0.1:17845/api/change-ticker \
-H "Content-Type: application/json" \
-d '{"exchange": 2, "market": 2, "ticker": "BTCUSDT", "binding": "001"}'
Opens a combo layout for the specified ticker. The ticker field is a symbol (e.g. BTCUSDT), not a pattern — the combo opens on the currently active exchange and market connection. The symbol is normalized: case-insensitive, separators (-, _, /) are stripped, and the SWAP suffix is removed.
POST http://127.0.0.1:{port}/api/combo
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
ticker | string | yes | Trading pair symbol, e.g. "BTCUSDT" |
200 OK:
{ "status": "ok" }
400 Bad Request:
| Condition | Error message |
|---|---|
Missing or empty ticker | Invalid request body. 'ticker' is required. |
| Handler not registered | Combo handler not registered |
curl -X POST http://127.0.0.1:17845/api/combo \
-H "Content-Type: application/json" \
-d '{"ticker": "BTCUSDT"}'
The tickerPattern string follows the TradingView-style format:
EXCHANGE:SYMBOL.suffix
| Part | Required | Description |
|---|---|---|
EXCHANGE | no | Exchange name (case-insensitive), e.g. BINANCE, BYBIT, OKX. Separated from the symbol by :. If omitted, the colon is also omitted. |
SYMBOL | yes | Trading pair symbol, e.g. BTCUSDT, ETH-USDT. May contain letters, digits, _, /, -, $, and :. |
.suffix | no | Single-letter market type suffix preceded by a dot. |
| Suffix | Market type |
|---|---|
.p | Futures |
.m | Margin |
.o | Options |
| (none) | Spot |
| Pattern | Exchange | Symbol | Market |
|---|---|---|---|
BINANCE:BTCUSDT.p | Binance | BTCUSDT | Futures |
BYBIT:ETHUSDT | Bybit | ETHUSDT | Spot |
OKX:BTC-USDT.m | OKX | BTC-USDT | Margin |
BINANCE:BTCUSDT.o | Binance | BTCUSDT | Options |
HYPERLIQUID:BTCUSDT.p | HyperLiquid | BTCUSDT | Futures |
HYPERLIQUID:cash:HOODUSDT0.p | HyperLiquid | cash:HOODUSDT0 | Futures |
BTCUSDT.p | (none) | BTCUSDT | Futures |
BTCUSDT | (none) | BTCUSDT | Spot |
Note: The exchange name in the pattern is matched case-insensitively against the exchange names listed in Exchange values below.
The symbol part of the pattern is flexible — MetaScalp automatically tries several normalizations to find a match:
| Step | Transformation | Example |
|---|---|---|
| 1 | As-is (exact match) | cash:HOODUSDT0 → cash:HOODUSDT0 |
| 2 | Uppercase | btcusdt → BTCUSDT |
| 3 | Strip separators (-, _, /) | ETH/USDT → ETHUSDT, SOL_USDT → SOLUSDT |
| 4 | Strip separators + uppercase | eth/usdt → ETHUSDT |
| 5 | Remove SWAP suffix | BTCUSDTSWAP → BTCUSDT |
| 6 | Preserve prefix before :, uppercase the rest | cash:hoodUSDT0 → cash:HOODUSDT0 |
This means you can pass symbols in any case and with or without common separators (-, _, /) — the API will find the correct ticker.
| Value | Exchange | Notes |
|---|---|---|
| 2 | Binance | |
| 3 | GateIo | |
| 4 | Bybit | Classic (non-UTA) accounts |
| 5 | KuCoin | |
| 6 | BybitUta | Bybit Unified Trading Account |
| 7 | Bitget | |
| 8 | Mexc | |
| 10 | Okx | |
| 11 | BingX | |
| 12 | HTX | |
| 13 | BitMart | |
| 14 | LBank | |
| 15 | HyperLiquid | |
| 16 | UpBit | |
| 17 | AsterDex | |
| 18 | Moex | |
| 19 | Lighter |
Note: Values 1 and 9 are unused and reserved. Exchange identifiers are not sequential.
| Value | Type | Description |
|---|---|---|
| 0 | Spot | Spot trading |
| 1 | Futures | Generic futures |
| 2 | UsdtFutures | USDT-margined futures |
| 3 | CoinFutures | Coin-margined futures |
| 4 | InverseFutures | Inverse futures |
| 5 | UsdtPerpetual | USDT perpetual swaps |
| 6 | UsdcPerpetual | USDC perpetual swaps |
| 7 | Margin | Margin (cross/isolated) |
| 8 | Options | Options contracts |
| 9 | Stock | Stock / equity markets |
Tip: Unsure which market type to use? Use the ticker pattern approach instead — the.psuffix auto-resolves to the right futures type. For explicit fields,2(UsdtFutures) is the most common choice for perpetual futures.
Note: When the requested market type is not Spot and no exact connection match is found, MetaScalp falls back to any non-Spot connection on the same exchange.
async function discoverMetaScalp() {
for (let port = 17845; port <= 17855; port++) {
try {
const r = await fetch(`http://127.0.0.1:${port}/ping`);
if (r.ok) {
const data = await r.json();
if (data.app === "MetaScalp") return port;
}
} catch {}
}
return null;
}
async function changeTickerByPattern(port, tickerPattern, binding) {
const body = { tickerPattern };
if (binding) body.binding = binding;
const r = await fetch(`http://127.0.0.1:${port}/api/change-ticker`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
});
return r.json();
}
async function changeTicker(port, exchange, market, ticker, binding) {
const r = await fetch(`http://127.0.0.1:${port}/api/change-ticker`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ exchange, market, ticker, binding })
});
return r.json();
}
// Usage with ticker pattern
const port = await discoverMetaScalp();
if (port) await changeTickerByPattern(port, "BINANCE:BTCUSDT.p", "001");
// Usage with explicit fields
if (port) await changeTicker(port, 2, 2, "BTCUSDT", "001");
// Without binding — only active window is updated
if (port) await changeTickerByPattern(port, "BINANCE:ETHUSDT.p");
import requests
def discover_metascalp():
for port in range(17845, 17856):
try:
r = requests.get(f"http://127.0.0.1:{port}/ping", timeout=0.5)
if r.ok and r.json().get("app") == "MetaScalp":
return port
except requests.ConnectionError:
continue
return None
def change_ticker_by_pattern(port, ticker_pattern, binding=None):
payload = {"tickerPattern": ticker_pattern}
if binding:
payload["binding"] = binding
r = requests.post(f"http://127.0.0.1:{port}/api/change-ticker", json=payload)
return r.json()
def change_ticker(port, exchange, market, ticker, binding=None):
payload = {"exchange": exchange, "market": market, "ticker": ticker}
if binding:
payload["binding"] = binding
r = requests.post(f"http://127.0.0.1:{port}/api/change-ticker", json=payload)
return r.json()
def open_combo(port, ticker):
r = requests.post(f"http://127.0.0.1:{port}/api/combo", json={"ticker": ticker})
return r.json()
# Usage
port = discover_metascalp()
if port:
change_ticker_by_pattern(port, "BINANCE:BTCUSDT.p", binding="001")
change_ticker(port, 2, 2, "BTCUSDT", binding="001")
open_combo(port, "BTCUSDT")