TypeScript SDK
The client, the stream, discovery and errors of the @spectre-trade/terminal package.
Install
npm install @spectre-trade/terminalTerminal
A client of one running terminal.
Construct it with a token, or let Terminal.discover find the port
and the token and verify the API version. All methods are async and
throw ApiError for a non-2xx answer and
TerminalUnreachableError when there is no answer.
| Field | Type | Description |
|---|---|---|
host | string | |
port | number | |
timeoutMs | number | |
baseUrl | string | http://127.0.0.1:48180/v1/ — the token is not part of it. |
Terminal()
new Terminal(options: TerminalOptions)discover()
static discover(options: DiscoverOptions = {}): Promise<Terminal>Find the terminal and check it: the token from options.token or
SPECTRE_LOCAL_API_TOKEN (else TokenMissingError), the port from
options.port or instance.json (else 48180; LocalApiDisabledError
when the file says the API is off), then one GET /v1/meta. An
api_version other than "1" is IncompatibleTerminalError; an
unauthorized answer is an ApiError whose message says the token
may be stale or the API switched off.
| Options | Type | Description |
|---|---|---|
tokenoptional | string | Overrides SPECTRE_LOCAL_API_TOKEN. |
portoptional | number | Overrides instance.json. |
hostoptional | string | |
timeoutMsoptional | number | |
instancePathoptional | string | Read this file instead of the OS-specific instance.json path (tests). |
meta()
meta(): Promise<Meta>GET /v1/meta: API version, build, token scopes, limits, stream topics.
HTTP operation: GET /v1/meta
health()
health(): Promise<Health>GET /v1/health.
HTTP operation: GET /v1/health
connections()
connections(): Promise<List<Connection>>GET /v1/connections (connections:read).
HTTP operation: GET /v1/connections
connection()
connection(id: number): Promise<Connection>GET /v1/connections/{id} (connections:read); not_found for an unknown id.
HTTP operation: GET /v1/connections/{id}
instruments()
instruments(options: InstrumentsOptions): Promise<InstrumentsPage>GET /v1/instruments (market:read): one page of the catalogue of an
exchange and market, by connectionId or exchange + market. Follow
next_cursor by hand or use iterInstruments.
HTTP operation: GET /v1/instruments
| Options | Type | Description |
|---|---|---|
connectionIdoptional | number | |
exchangeoptional | string | |
marketoptional | string | |
qoptional | string | Substring of the symbol or the base coin, case-insensitive. |
limitoptional | number | 1–2000, default 500. |
cursoroptional | string | next_cursor of the previous page. |
iterInstruments()
iterInstruments(options: InstrumentsOptions): AsyncGenerator<Instrument, void, undefined>Every instrument matching the options, page after page.
| Options | Type | Description |
|---|---|---|
connectionIdoptional | number | |
exchangeoptional | string | |
marketoptional | string | |
qoptional | string | Substring of the symbol or the base coin, case-insensitive. |
limitoptional | number | 1–2000, default 500. |
cursoroptional | string | next_cursor of the previous page. |
intervals()
intervals(): Promise<Intervals>GET /v1/market/intervals (market:read): candle and cluster intervals.
HTTP operation: GET /v1/market/intervals
candles()
candles(instrument: InstrumentAddress, options: CandlesOptions): Promise<Candles>GET /v1/market/candles (market:read): candle history, oldest first.
HTTP operation: GET /v1/market/candles
| Options | Type | Description |
|---|---|---|
interval | string | A code from /v1/market/intervals: 1m, 5m, … |
limitoptional | number | Up to 2000, default 500. |
endoptional | number | Right boundary, UTC milliseconds; default now. |
connectionIdoptional | number |
trades()
trades(instrument: InstrumentAddress, options: TradesOptions = {}): Promise<Trades>GET /v1/market/trades (market:read): the latest trades of the pair,
oldest to newest. A pair without a subscription is opened on demand and
the call may take up to 3 s.
HTTP operation: GET /v1/market/trades
| Options | Type | Description |
|---|---|---|
limitoptional | number | 1–1000 latest, default 100. |
sinceTsoptional | number | Not earlier than this receive time, UTC milliseconds. |
connectionIdoptional | number |
snapshot()
snapshot(instrument: InstrumentAddress, options: ConnectionOptions = {}): Promise<Snapshot>GET /v1/market/snapshot (market:read): best bid/ask, last trade, mark, ticker.
HTTP operation: GET /v1/market/snapshot
| Options | Type | Description |
|---|---|---|
connectionIdoptional | number |
orderbook()
orderbook(instrument: InstrumentAddress, options: OrderbookOptions = {}): Promise<Orderbook>GET /v1/market/orderbook (market:read); unavailable without a full book within 3 s.
HTTP operation: GET /v1/market/orderbook
| Options | Type | Description |
|---|---|---|
depthoptional | number | 1–200, default 50. |
connectionIdoptional | number |
clusters()
clusters(instrument: InstrumentAddress, options: ConnectionOptions = {}): Promise<Clusters>GET /v1/market/clusters (market:read): up to ten buckets at the
interval selected in the terminal. The first call for an instrument not
open in the window may answer not_active (409); a retry a few seconds
later finds the clusters.
HTTP operation: GET /v1/market/clusters
| Options | Type | Description |
|---|---|---|
connectionIdoptional | number |
accountOrders()
accountOrders(connectionId: number): Promise<AccountOrders>GET /v1/account/orders (account:read): open orders and trigger
orders of one connection, the same cut the terminal window sees.
not_found for an unknown connection.
HTTP operation: GET /v1/account/orders
accountPositions()
accountPositions(connectionId: number): Promise<AccountPositions>GET /v1/account/positions (account:read): open positions of one connection.
HTTP operation: GET /v1/account/positions
accountBalances()
accountBalances(connectionId: number): Promise<AccountBalances>GET /v1/account/balances (account:read): per currency, the latest
value the exchange sent since the API was switched on. A currency
nothing happened to since then is absent.
HTTP operation: GET /v1/account/balances
accountFills()
accountFills(connectionId: number, options: AccountFillsOptions = {}): Promise<AccountFills>GET /v1/account/fills (account:read): the connection's fills since
the API was switched on (the last thousand), oldest to newest.
HTTP operation: GET /v1/account/fills
| Options | Type | Description |
|---|---|---|
limitoptional | number | 1–1000 latest, default 100. |
sinceTsoptional | number | Not earlier than this exchange time, UTC milliseconds. |
placeOrder()
placeOrder(options: PlaceOrderOptions): Promise<Accepted>POST /v1/orders (trading:write): place a limit or market order with
the same command the window uses. The answer means accepted by the
terminal, not by the exchange: watch account.orders in the stream, or
accountOrders, for the order under key. not_tradable (409)
for a disabled, read-only or credential-less connection,
invalid_request (400) for a foreign instrument or a refused size or
price, rate_limited (429) above limits.commands_per_second.
HTTP operation: POST /v1/orders
| Options | Type | Description |
|---|---|---|
connectionId | number | The trading connection; there is no default. |
instrument | InstrumentAddress | |
side | Side | |
type | OrderType | limit needs price, market takes none. |
priceoptional | Decimal | |
sizeoptional | Decimal | Amount in the base coin; exactly one of size and notional. |
notionaloptional | Decimal | The quote amount; exactly one of size and notional. |
reduceOnlyoptional | boolean | Default false. |
postOnlyoptional | boolean | Default false. |
timeInForceoptional | TimeInForce | Absent — the venue's default. |
clientKeyoptional | string | Idempotency key: a repeat with the same key returns the previous answer and does not duplicate the order (the terminal remembers the last thousand). |
cancelOrder()
cancelOrder(options: CancelOrderOptions): Promise<Accepted>DELETE /v1/orders/{id} (trading:write): cancel one order by the
terminal key (t-…) or the exchange's id. The cancellation goes to the
exchange directly; the confirmation arrives through the stream.
HTTP operation: DELETE /v1/orders/{id}
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
orderId | string | The terminal key (t-…) or the exchange's order id. |
cancelAll()
cancelAll(options: InstrumentCommandOptions): Promise<Accepted>POST /v1/orders/cancel-all (trading:write): cancel every order of the instrument, as the space bar does.
HTTP operation: POST /v1/orders/cancel-all
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress |
closePosition()
closePosition(options: InstrumentCommandOptions): Promise<Accepted>POST /v1/positions/close (trading:write): close the instrument's
position the way the window does — a market order for the position size
on futures, "cancel all and close" as one atomic command on spot.
invalid_request without an open position.
HTTP operation: POST /v1/positions/close
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress |
placeTrigger()
placeTrigger(options: PlaceTriggerOptions): Promise<Accepted>POST /v1/orders/trigger (trading:write): a stop loss, take profit or
stop, placed by the same services the window uses. stop_loss and
take_profit go on the open position (side, size and rule come from
it; invalid_request without one); a stop needs side and
notional. key in the answer is the trigger's key (sl_…, tp_…,
stop_…), which shows up as client_id of the trigger in
accountOrders; cancelling and amending use the numeric id from
there. unsupported (501) on a venue without trigger orders in the terminal.
HTTP operation: POST /v1/orders/trigger
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
kind | TriggerType | stop_loss and take_profit go on the open position; stop is its own order. |
triggerPrice | Decimal | |
sideoptional | Side | stop only. |
notionaloptional | Decimal | stop only: the quote amount. |
ruleoptional | TriggerRule | stop only; absent means above the market for a buy, below for a sell. |
clientKeyoptional | string | Idempotency key, as for Terminal.placeOrder. |
cancelTrigger()
cancelTrigger(options: CancelTriggerOptions): Promise<Accepted>DELETE /v1/orders/trigger/{id} (trading:write): cancel one trigger by its numeric id.
HTTP operation: DELETE /v1/orders/trigger/{id}
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
triggerId | string | number | The numeric id of the trigger from accountOrders().triggers. |
cancelAllTriggers()
cancelAllTriggers(options: InstrumentCommandOptions): Promise<Accepted>POST /v1/orders/trigger/cancel-all (trading:write): cancel every trigger of the instrument; plain orders stay.
HTTP operation: POST /v1/orders/trigger/cancel-all
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress |
amendTrigger()
amendTrigger(options: AmendTriggerOptions): Promise<Accepted>PATCH /v1/orders/trigger/{id} (trading:write): move a trigger to a
new price — the window's sequential replacement, cancel then place.
kind is required; a stop also needs its side. key is null.
HTTP operation: PATCH /v1/orders/trigger/{id}
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
triggerId | string | number | The numeric id of the trigger from accountOrders().triggers. |
kind | TriggerType | |
triggerPrice | Decimal | |
sideoptional | Side | stop only. |
ruleoptional | TriggerRule | stop only. |
leverage()
leverage(options: InstrumentCommandOptions): Promise<Leverage>GET /v1/account/leverage (account:read): leverage and margin mode of
a futures instrument, from the terminal's cache. An instrument the
terminal has not touched yet is not_active (409): open it in the window
or call setLeverage, which is how it enters the cache.
HTTP operation: GET /v1/account/leverage
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress |
setLeverage()
setLeverage(options: SetLeverageOptions): Promise<Accepted>POST /v1/account/leverage (trading:write): set the leverage the way
the window does — exactly one of leverage (an integer ≥ 1) and mode
(max, smart). The applied value shows in leverage after the
exchange answered.
HTTP operation: POST /v1/account/leverage
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
leverageoptional | number | An integer of at least 1. |
modeoptional | "max" | "smart" |
setMarginMode()
setMarginMode(options: SetMarginModeOptions): Promise<Accepted>POST /v1/account/margin-mode (trading:write): cross or isolated.
Changing it with an open position is refused by the exchange, as in the
window; the accepted answer does not know that yet.
HTTP operation: POST /v1/account/margin-mode
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress | |
marginMode | MarginMode |
workspace()
workspace(): Promise<Workspace>GET /v1/workspace (workspace:read): every window with its tabs,
stacks and charts, from the snapshot the window publishes at every
structural change. The ids are internal to this run of the terminal.
HTTP operation: GET /v1/workspace
workspaceWindow()
workspaceWindow(options: WindowOptions): Promise<WorkspaceWindow>GET /v1/workspace/windows/{id} (workspace:read): one window; an unknown id is not_found.
HTTP operation: GET /v1/workspace/windows/{id}
| Options | Type | Description |
|---|---|---|
windowId | number |
openStack()
openStack(options: OpenStackOptions): Promise<WorkspaceOutcome>POST /v1/workspace/stacks (workspace:write): a stack of the instrument
in a new tab or a new window, with a chart over it when chart is set.
The answer names the window, the tab and the new widgets. An instrument
the terminal's catalogue does not know is invalid_request.
HTTP operation: POST /v1/workspace/stacks
| Options | Type | Description |
|---|---|---|
instrument | InstrumentAddress | |
connectionIdoptional | number | Chosen by the general rule when omitted. |
chartoptional | boolean | A chart of the same instrument over the stack. |
targetoptional | OpenTarget | new_tab (default) or new_window. |
windowIdoptional | number | The window for a new tab; the focused window when omitted. |
activateoptional | boolean | false opens the tab in the background; a new window always takes focus. |
openTab()
openTab(options: OpenTabOptions): Promise<WorkspaceOutcome>POST /v1/workspace/tabs (workspace:write): a tab with a column per
item — a stack and, with chart, a chart over it — in a new tab or a new
window. Omitted, name is the only instrument or the first one plus a
count. A refusal names the item (items[1]: …) and nothing reaches the
window.
HTTP operation: POST /v1/workspace/tabs
| Options | Type | Description |
|---|---|---|
items | Array<TabItemOptions | InstrumentAddress> | Columns in order, one to fifty; a bare address is a stack without a chart. |
nameoptional | string | Up to 64 characters; omitted, the terminal names the tab after the instruments. |
targetoptional | OpenTarget | new_tab (default) or new_window. |
windowIdoptional | number | The window for a new tab; the focused window when omitted. |
activateoptional | boolean | false opens the tab in the background; a new window always takes focus. |
addStacks()
addStacks(options: AddStacksOptions): Promise<WorkspaceOutcome>POST /v1/workspace/windows/{id}/tabs/{tab}/stacks (workspace:write):
the same columns after the tab's last one; the tab keeps its name and its
column widths. The answer lists only the added widgets.
HTTP operation: POST /v1/workspace/windows/{id}/tabs/{tab}/stacks
| Options | Type | Description |
|---|---|---|
windowId | number | |
tabId | number | |
items | Array<TabItemOptions | InstrumentAddress> | Columns in order, one to fifty; a bare address is a stack without a chart. |
openMultiview()
openMultiview(options: OpenMultiviewOptions): Promise<WorkspaceOutcome>POST /v1/workspace/multiview (workspace:write): a coin on every venue
of «Exchange layout», the same plan as the window's Multiview button. No
cell for the coin is not_found.
HTTP operation: POST /v1/workspace/multiview
| Options | Type | Description |
|---|---|---|
base | string | A coin (BTC) or a pair (BTC/USDT). |
targetoptional | OpenTarget | Omitted: the Multiview «open as» setting decides. |
windowIdoptional | number | |
activateoptional | boolean |
setStackInstrument()
setStackInstrument(options: StackInstrumentOptions): Promise<WorkspaceOutcome>PATCH /v1/workspace/stacks/{widget_id} (workspace:write): another instrument in the stack and its charts.
HTTP operation: PATCH /v1/workspace/stacks/{widget_id}
| Options | Type | Description |
|---|---|---|
widgetId | number | |
instrument | InstrumentAddress | |
connectionIdoptional | number |
closeStack()
closeStack(options: StackOptions): Promise<WorkspaceOutcome>DELETE /v1/workspace/stacks/{widget_id} (workspace:write): close one stack, as its close button does.
HTTP operation: DELETE /v1/workspace/stacks/{widget_id}
| Options | Type | Description |
|---|---|---|
widgetId | number |
closeTab()
closeTab(options: TabOptions): Promise<WorkspaceOutcome>DELETE /v1/workspace/windows/{id}/tabs/{tab} (workspace:write): the only tab of a window is invalid_request.
HTTP operation: DELETE /v1/workspace/windows/{id}/tabs/{tab}
| Options | Type | Description |
|---|---|---|
windowId | number | |
tabId | number |
activateTab()
activateTab(options: TabOptions): Promise<WorkspaceOutcome>POST /v1/workspace/windows/{id}/tabs/{tab}/activate (workspace:write): select the tab; the window's focus is untouched.
HTTP operation: POST /v1/workspace/windows/{id}/tabs/{tab}/activate
| Options | Type | Description |
|---|---|---|
windowId | number | |
tabId | number |
closeWindow()
closeWindow(options: WindowOptions): Promise<WorkspaceOutcome>DELETE /v1/workspace/windows/{id} (workspace:write): the main window is invalid_request.
HTTP operation: DELETE /v1/workspace/windows/{id}
| Options | Type | Description |
|---|---|---|
windowId | number |
activateWindow()
activateWindow(options: WindowOptions): Promise<WorkspaceOutcome>POST /v1/workspace/windows/{id}/activate (workspace:write): restore if minimised and bring to the front.
HTTP operation: POST /v1/workspace/windows/{id}/activate
| Options | Type | Description |
|---|---|---|
windowId | number |
settings()
settings(options: SettingsOptions = {}): Promise<Settings>GET /v1/settings (settings:read): rows as stored, without the default
ladder. Without options: the global rows without a connection. Each row
says whether it is writable through updateSettings.
HTTP operation: GET /v1/settings
| Options | Type | Description |
|---|---|---|
scopeoptional | "global" | "order_book" | global (default) or order_book. |
categoryoptional | string | |
keyoptional | string | |
connectionIdoptional | number | The connection's rows; without it the rows without a connection. |
instrumentoptional | InstrumentAddress | The pair's rows (scope order_book). |
orderbookSettings()
orderbookSettings(options: InstrumentCommandOptions): Promise<OrderbookSettings>GET /v1/settings/orderbook (settings:read): the stack settings of an
instrument as its stack on the connection sees them — the pair's row, the
connection's default, the pair's row without a connection, the global
default — with resolved_from on every key.
HTTP operation: GET /v1/settings/orderbook
| Options | Type | Description |
|---|---|---|
connectionId | number | |
instrument | InstrumentAddress |
updateSettings()
updateSettings(changes: SettingChange[]): Promise<SettingsApplied>PATCH /v1/settings (settings:write): write settings the way the
Settings App does. Every change is checked against the terminal's
catalogue first (invalid_request naming changes[i], nothing written;
leverage is unsupported here — use setLeverage), then applied in
order: the same row, window event and service caches as the Settings App.
The first failed change rejects the call; earlier ones stay applied.
HTTP operation: PATCH /v1/settings
stream()
stream(options: StreamOptions = {}): Promise<Stream>Open /v1/stream. Node only: the token goes in the handshake header.
| Options | Type | Description |
|---|---|---|
timeoutMsoptional | number | Handshake timeout; defaults to the client's timeoutMs. |
StreamProtocol
The socket-free half of the stream protocol: hands out request ids, keeps
the requests waiting for a reply, settles them from subscribed /
unsubscribed / error frames and turns everything else into the frames
a consumer iterates. Pure, so it is unit-testable without a server.
nextRequestId()
nextRequestId(): stringA fresh request_id, unique within this stream.
expect()
expect(requestId: string): Promise<ReplyFrame>Register a request and get the promise its reply will settle.
pendingCount
pendingCount: numberRequests still waiting for a reply.
route()
route(raw: unknown): StreamFrame | undefinedClassify a decoded frame. Replies to our requests settle the matching
promise and return undefined; event, gap and subscription errors
are returned for the consumer; anything unknown or malformed is dropped.
abortAll()
abortAll(error: Error): voidReject every waiting request, e.g. when the socket closes.
Stream
class Stream extends AsyncIterable<StreamFrame>A live /v1/stream connection.
Obtain one with terminal.stream(). Subscribe with subscribe, then
iterate: for await (const frame of stream) yields events, gaps and
subscription errors in arrival order, buffered without limit while the
consumer is busy (the server protects itself: a client that lags for more
than 5 s is closed with 4008). One consumer iterates at a time; a second
concurrent next() simply waits its turn.
When the server closes the connection, iteration ends; for 1001, 4008,
4029 and a lost connection (1006) it ends by throwing
StreamClosedError. closeCode and closeReason are
set either way. Closing from the client (close, or break out of
the loop) ends iteration normally.
connect()
static connect(options: StreamConnectOptions): Promise<Stream>Open the WebSocket and complete the handshake. Rejects with
TerminalUnreachableError when the terminal does not accept it:
Node's WebSocket reports a refused handshake (terminal down, API off,
token rejected) as one generic failure, so the three are not told apart.
| Options | Type | Description |
|---|---|---|
url | string | ws://127.0.0.1:48180/v1/stream. |
token | string | |
timeoutMsoptional | number | Handshake timeout; default 10 000. |
url
url: stringThe stream URL (never carries the token).
closed
closed: booleantrue once the socket is closed, whoever closed it.
closeCode
closeCode: number | undefinedWebSocket close code, once closed.
closeReason
closeReason: string | undefinedWebSocket close reason, once closed.
subscribe()
subscribe(options: SubscribeOptions): Promise<Subscribed>Subscribe to a topic of an instrument, or to an account topic of a
connection. Resolves with the server's subscribed frame (plus the
requested topic and, for market topics, instrument) and rejects with
StreamRequestError on the server's error reply; events of other
subscriptions keep flowing meanwhile. Note the terminal's limit on new
exchange subscriptions per second (/v1/meta); account topics do not
touch the exchange and send no snapshot frame — read the current state
with the /v1/account/* operations first.
| Options | Type | Description |
|---|---|---|
topic | Topic | |
instrumentoptional | InstrumentAddress | Required for market topics; ignored for account.*. |
connectionIdoptional | number | Required for account.*; chosen by the general rule for market topics when omitted. |
paramsoptional | BookTopParams | Only book.top reads them; wire names (depth, interval_ms). |
unsubscribe()
unsubscribe(subscription: Subscribed | SubscribedFrame | string): Promise<void>Remove a subscription immediately. Accepts the value subscribe resolved
with or the bare sub id. Resolves on the server's unsubscribed.
close()
close(code: number = CLOSE_NORMAL, reason?: string): Promise<void>Close the stream. The server completes the close handshake with the client's code; the promise resolves when it has, or after a short grace period if it never does. Safe to call more than once.
Discovery
| Constants | Value | Description |
|---|---|---|
DEFAULT_PORT | 48180 | The port the terminal listens on unless SPECTRE_LOCAL_API_PORT overrides it. |
TOKEN_ENV | "SPECTRE_LOCAL_API_TOKEN" | The environment variable the token is read from. |
instancePath()
function instancePath(options: DiscoveryEnvironment = {}): stringPath of the terminal's instance.json, per OS:
- Linux:
$XDG_DATA_HOME/spectre-terminal/instance.json, falling back to~/.local/share/spectre-terminal/instance.json; - macOS:
~/Library/Application Support/spectre-terminal/instance.json; - Windows:
%LOCALAPPDATA%\spectre-terminal\instance.json, falling back to%USERPROFILE%\AppData\Local\....
This mirrors the terminal's own data directory (dirs::data_local_dir).
readPort()
function readPort(options: ReadPortOptions = {}): Promise<number | undefined>The Local API port published in instance.json.
Resolves to undefined when the file is missing or unreadable (no running
terminal, or a terminal that does not publish the field): the caller falls
back to DEFAULT_PORT. Throws LocalApiDisabledError when the
file exists but local_api_port is null or absent — the terminal is
running and the API is switched off. Reads only this one field.
tokenFromEnv()
function tokenFromEnv(env: Record<string, string | undefined> = process.env): string | undefinedThe token from SPECTRE_LOCAL_API_TOKEN, or undefined when unset or empty.
Errors
SpectreTerminalError
class SpectreTerminalError extends ErrorBase class of every error thrown by this package.
ApiError
class ApiError extends SpectreTerminalErrorThe terminal answered with a non-2xx status.
code is the stable code from the contract's error envelope
(unauthorized, not_found, rate_limited, …); status is the HTTP
status. A non-2xx body that is not the envelope gives code "unknown".
| Field | Type | Description |
|---|---|---|
code | string | Stable error code from the contract, or "unknown". |
status | number | HTTP status of the response. |
detail | string | The server's human-readable message, unprefixed. |
TerminalUnreachableError
class TerminalUnreachableError extends SpectreTerminalErrorNo HTTP response at all: connection refused, request timed out, an
unexpected redirect, or a WebSocket handshake that did not complete.
The original failure is in cause.
LocalApiDisabledError
class LocalApiDisabledError extends SpectreTerminalErrorinstance.json exists but publishes no Local API port: the terminal is
running with the API switched off, or the file was left behind by a
terminal that did not shut down cleanly. Either way there is no port to
connect to until the API is enabled in the Settings App (General → Local
API).
TokenMissingError
class TokenMissingError extends SpectreTerminalErrorNeither the token option nor SPECTRE_LOCAL_API_TOKEN provided a token.
IncompatibleTerminalError
class IncompatibleTerminalError extends SpectreTerminalError/v1/meta reported an API version this client does not speak.
| Field | Type | Description |
|---|---|---|
apiVersion | string | The api_version the terminal reported. |
appVersion | string | The app_version the terminal reported. |
StreamRequestError
class StreamRequestError extends SpectreTerminalErrorThe stream answered a subscribe or unsubscribe request with an error
frame. code is the contract's error code (not_found, rate_limited,
invalid_request, …). Other subscriptions keep flowing.
| Field | Type | Description |
|---|---|---|
code | string | Stable error code from the contract. |
detail | string | The server's human-readable message, unprefixed. |
StreamClosedError
class StreamClosedError extends SpectreTerminalErrorThe stream was closed by the server for a reason the consumer must act on:
1001 — the API was switched off or the token was reissued; 4008 — this
client read too slowly; 4029 — the per-token connection limit. It is also
raised for 1006 when the connection dropped without a close frame, and by
subscribe / unsubscribe on an already closed stream.
| Field | Type | Description |
|---|---|---|
code | number | WebSocket close code. |
reason | string | Close reason sent by the server, possibly empty. |
Generated from the code of @spectre-trade/terminal at commit 2d1c324.