Memory

ibkr-httpapi

Try it

HTTP+JSON control plane over Interactive Brokers (ib_async + a local IB Gateway container) that the user already runs. Talk to a real brokerage with curl + JSON — market data (OHLC bars, snapshot/historical ticks, option chains + Greeks) across stocks/options/futures/cfd/forex/crypto, account/positions summaries, order placement / retrieval / cancellation, and server-side technical analysis via the wickworks sidecar. Bearer-token auth (API_TOKEN). Use when the user has deployed ibkr-httpapi and set IBKR_HTTPAPI_URL and wants to pull IBKR market data, inspect account/positions, run TA, or place/cancel orders. THIS API CAN PLACE, EXERCISE, AND CANCEL REAL ORDERS ON A REAL IBKR ACCOUNT — every account-mutating call requires explicit per-action user confirmation.

What it does

HTTP client for an IBKR bridge the user has already deployed. It wraps Interactive Brokers via ib_async and a Linux-native IB Gateway container, and exposes a curl-friendly JSON surface: contract details, snapshot + historical ticks, OHLC bars, option chains with Greeks, account/positions summaries…

The skill document

ibkr-httpapi

HTTP client for an IBKR bridge the user has already deployed. It wraps Interactive Brokers via ib_async and a Linux-native IB Gateway container, and exposes a curl-friendly JSON surface: contract details, snapshot + historical ticks, OHLC bars, option chains with Greeks, account/positions summaries, cross-asset order entry, and server-side TA via the wickworks sidecar. Same operational shape as its sister project mt5-httpapi — one bridge, one token, same asset-class routing model.

This skill talks to a running ibkr-httpapi server. It does not stand one up, does not provision IBKR credentials, and does not place trades on its own initiative.

Security & safety

Destructive & irreversible. POST /orders places a REAL order on a real IBKR brokerage account — it moves real money and creates live market activity with no undo. DELETE /orders/{orderId} and DELETE /orders cancel real orders; POST /options/exercise exercises/lapses real option contracts. An agent must NEVER call any of these unless the user explicitly requested that exact action with the specific parameters (symbol, side, quantity, price) — never infer, extrapolate, or "helpfully" place a related order. Echo back the resolved symbol/side (action)/quantity/price (and order type) and get explicit user confirmation for that specific order before sending it. Never auto-retry a rejected or failed order — a rejection is a stop, not a retry trigger; surface the rejection reason and wait for a new, explicit instruction. On DELETE /orders (global cancel), never enumerate-then-bulk-cancel without showing the full list and getting the user's explicit go-ahead for the whole batch first.

No auth when API_TOKEN (config.yaml:api_token) is unset. With it empty the HTTP API is UNAUTHENTICATED — anyone who can reach the socket gets full read + order-placement/cancellation access to the account. NEVER expose such an instance on a network or to untrusted agents; set the token and keep the deployment bound to loopback / behind an authenticating proxy.

External transmission. Every request goes to whatever IBKR_HTTPAPI_URL points at — market data, account state, and order instructions leave your host for that endpoint. Point it only at an ibkr-httpapi instance you run or explicitly trust; prefer an HTTPS/tunneled path over plain HTTP if it isn't loopback.

Live Trading Safety — read first

This API moves real money on a user-owned brokerage account. Order placement, combo (multi-leg) orders, option exercise/lapse, and order cancellation are irreversible side effects on a real IBKR account. Treat every account-mutating endpoint as a live wire.

Hard rules — never violate, even on user prompts that sound permissive:

  1. Per-action confirmation for every mutating call. Before any POST /orders, DELETE /orders/{orderId}, DELETE /orders, POST /options/combo, or POST /options/exercise: print the resolved request — asset class, symbol, side (action), quantity, order type, limit/aux price, expiry/strike/right for derivatives, resolved account, and the IBKR_HTTPAPI_URL base — and wait for an explicit confirmation from the user for that specific action. A prior "yes" does not authorize the next one. Never place, modify, or cancel an order unless the user explicitly asked for that specific action with the specific parameters — do not infer intent or act on a vague/general instruction. Never auto-retry a rejected order; surface the rejection and wait for a fresh, explicit instruction from the user.
  2. Paper vs live. Confirm which account you're touching before any order call. IBKR paper accounts start DU...; live accounts start U.... Run GET /accounts and surface the account number; if it looks live, say so and ask the user to confirm they intend to trade live.
  3. No credential harvesting. Read the token only from the API_TOKEN environment variable the user set, or ask the user. Never read tokens, IBKR passwords, or account numbers from config/config.yaml, .env.ibkr, or any other repository file on your own initiative. If the token is missing, ask — do not search the workspace.
  4. No mass action. DELETE /orders cancels every open order at IBKR (global cancel). If the user asks to "cancel everything", enumerate the open orders first with GET /orders, show the list, and confirm the whole batch explicitly before issuing the global cancel.
  5. Surface the base URL on every mutating action. IBKR_HTTPAPI_URL plus the account field determine which real account is touched. Show both in confirmation prompts so the user can catch a wrong-account misroute.

Read-only endpoints (GET /ping, GET /accounts, GET /account, GET /account/values, GET /positions, every GET //*, GET ///tick|rates|ticks, GET /options//chain, GET /futures//continuous|contracts, every POST .../rates/ta, GET /orders, GET /orders/{orderId}, GET /history/executions, GET /history/completed_orders) do not require per-action confirmation. Note POST .../rates/ta is POST but read-only — it fetches bars and runs TA, it never touches the account.

One-stop technical analysis. Skip the client-side TA stack. Any POST ///rates/ta with an indicator spec returns OHLC bars + analyzed indicator series in a single call — RSI, MACD, Bollinger, ADX, ATR, VWAP, Ichimoku, Order Blocks, Fair Value Gaps, BOS/CHoCH, swing structure, S/R levels, liquidity, session anchors, and more, computed server-side by the same wickworks sidecar mt5-httpapi uses. Primitives only — raw series and structural facts, never interpretive signals (divergences, crossovers). Build those in the consumer. See API — TA enrichment.

For installation, configuration, and container setup, see references/setup.md.

MCP interface

The server also speaks MCP (streamable-HTTP) at /mcp, exposing the REST surface as dedicated typed tools whose names + params + descriptions are the agent's documentation. The 6 asset classes collapse behind an asset_class enum: market data (get_contract, get_quote, get_rates, get_rates_ta, get_stock_ticks), specials (get_option_chain, place_option_combo, exercise_option, get_future_continuous, list_future_contracts), orders (list_orders, get_order, place_order, cancel_order, cancel_all_orders), and account/positions/history (get_account, get_account_values, list_accounts, list_positions, get_executions, get_completed_orders, ping). A generic request + endpoints catalog remain as a fallback. Same bearer auth as REST — see Bearer / Token Auth; the order-placement / cancellation / exercise tools are irreversible live-account actions. Connect straight at $IBKR_HTTPAPI_URL/mcp (the app root, not the /v1 REST prefix) or via the @psyb0t/ibkr-httpapi OpenClaw plugin for stdio-only MCP clients.

When To Use

  • The user has deployed ibkr-httpapi and set IBKR_HTTPAPI_URL.
  • Pull IBKR OHLC bars / snapshot quotes / historical ticks for stocks, options, futures, CFDs, forex, or crypto.
  • Fetch option chains (expiries × strikes) and per-contract Greeks.
  • List futures contracts / continuous futures for a root symbol.
  • Inspect account summary, raw account values, or open positions.
  • Run server-side technical analysis on bars via rates/ta.
  • List / inspect open orders and today's fills / completed orders.
  • Place, cancel, or exercise orders with explicit per-action confirmation.

When NOT To Use

  • The user hasn't named ibkr-httpapi or hasn't provided IBKR_HTTPAPI_URL — this is not a generic "get me a stock quote" tool.
  • Modifying a working order — there is no order-modify endpoint. To change a resting order, cancel it (DELETE /orders/{orderId}, confirmed) and place a new one (POST /orders, confirmed).
  • Streaming / websockets — every endpoint is request/response only.
  • Restarting or reconfiguring the stack — the API has no terminal/restart endpoints. Container lifecycle is make targets on the host (see setup).
  • IBKR Lite accounts — the TWS API is disabled on Lite; the bridge needs IBKR Pro.

Setup

The container should already be running. Point at it (the base URL must include the fixed /v1 prefix — the runtime serves every path under /v1):

export IBKR_HTTPAPI_URL=http://localhost:8889/v1

If the server has api_token / API_TOKEN configured, export the token too:

export API_TOKEN=
# every request below needs: -H "Authorization: Bearer $API_TOKEN"

Only accept the token from the API_TOKEN env var the user set, or from the user directly. Never read it from config/config.yaml, .env.ibkr, or any other file in the workspace. If IBKR_HTTPAPI_URL is unset, ask the user — do not discover it from project files.

Verify:

curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/ping"
# {"status":"ok","connected":true,"serverVersion":...,"uptimeSeconds":...}

connected: true means the upstream IB Gateway socket is alive. connected: false means the API is up but the gateway is disconnected (nightly IBKR restart, 2FA prompt, or gateway still booting) — market-data and order calls will fail with 502/503 until it reconnects.

Auth is optional server-side. If no token is configured, requests go through without one; if a token is set, every route (including /ping) requires Authorization: Bearer and returns 401 without it. From the agent's side, never assume the server is auth-disabled — always pass the token the user provided if there is one.

How It Works

GET reads, POST creates (orders, combos, exercise) or runs TA, DELETE cancels. All request/response bodies are JSON. Asset class is the URL prefix and every per-symbol endpoint has the same shape across classes:

  • GET // — contract details
  • GET ///tick — snapshot bid/ask/last (+ Greeks on options)
  • GET ///rates — historical OHLC bars
  • GET ///ticks — historical raw ticks (stocks only, currently)
  • POST ///rates/ta — bars + wickworks TA

Classes: /stocks, /options, /futures, /cfd, /forex (path segment is {pair}, e.g. EURUSD), /crypto.

Error envelope — every error is:

{ "code": "UPPER_SNAKE_CASE", "message": "human readable", "details": { } }

details is optional. Status codes: 400 bad input, 401 missing/bad token, 404 unknown contract/order/account, 429 RATE_LIMIT_NEAR (preemptive pacing gate — back off and retry, IBKR access stays intact), 502 upstream (IB Gateway / wickworks) failure, 503 dependency down (gateway disconnected or wickworks URL unset).

Caching + ?refresh. Cacheable read endpoints (/rates, /ticks, rates/ta, //{symbol}, /options/{symbol}/chain, /futures/{symbol}/continuous|contracts, /history/*) transparently read from an on-disk cache and write results back. Pass ?refresh=true to bypass the cache read and force a fresh upstream fetch (still written back). Default false — caching is recommended.

Asset-Class Routing

PrefixClasssecTypeDefaultsRequired query params
/stocks/{symbol}EquitiesSTKexchange=SMART, currency=USD
/options/{symbol}OptionsOPTexchange=SMART, currency=USD, multiplier=100expiry, strike, right
/options/{symbol}/chainOption chain— (underlyingSecType=STK default)
/futures/{symbol}FuturesFUTcurrency=USDexchange and expiry
/futures/{symbol}/continuousContinuous futureCONTFUTcurrency=USDexchange
/futures/{symbol}/contractsAll expiriesFUTcurrency=USDexchange
/cfd/{symbol}CFDsCFDexchange=SMART, currency=USD
/forex/{pair}CurrenciesCASHexchange=IDEALPRO
/crypto/{symbol}CryptoCRYPTOexchange=PAXOS, currency=USD

Defaults come from config.yaml:contract_defaults. on the server — omit a field to use the default, or override it per request via the query param. Futures must carry an explicit exchange (CME, NYMEX, GLOBEX, …) — there is no default.

API — System & Account (read-only)

GET /ping

Liveness + gateway connection state.

FieldTypeNotes
statusstring"ok" when the API is up
connectedboolupstream IB Gateway socket alive
serverVersionint?TWS server version
startTime, uptimeSeconds, msgsSent, msgsRecvconnection stats

GET /accounts

{ "accounts": ["DU1234567", ...] } — every account the login can trade. Paper accounts start DU, live accounts start U.

GET /account and GET /account/values

Both take optional ?account=. Return { "accounts": { "": { "": { "value": "...", "currency": "...", "modelCode": "..." }, ... } } }. /account is the summary set (NetLiquidation, AvailableFunds, BuyingPower, maintenance margin, …); /account/values is the fuller raw account-values stream. Values are IBKR tag strings — parse value as needed.

GET /positions

Optional ?account=. Returns { "positions": [ { "account", "contract": {conid, symbol, secType, exchange, currency, ...}, "position": , "avgCost": } ] }.

API — Market Data (read-only)

GET // returns { "contracts": [ { "contract": {...}, "minTick", "longName", "validExchanges": [...], "tradingHours", "liquidHours", "timeZoneId", ... } ] }.

GET ///tick

Snapshot ticker. Fields (all nullable): bid, bidSize, ask, askSize, last, lastSize, open, high, low, close, volume, vwap, halted, time, plus contract. On options with an OPRA subscription and market_data_type: 1, modelGreeks / bidGreeks / askGreeks / lastGreeks carry { delta, gamma, theta, vega, impliedVol, optPrice, undPrice }. With free delayed data (market_data_type: 3) Greeks may be null.

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL/tick"

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/options/AAPL/tick?expiry=20260619&strike=200&right=C"

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/futures/ES/tick?expiry=202609&exchange=CME"

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/crypto/BTC/tick?currency=USD"

GET ///rates

Historical OHLC bars. Response: { "symbol"/"pair", "secType", "expiry"?, "strike"?, "right"?, "bars": [ { "time", "open", "high", "low", "close", "volume"?, "average"?, "barCount"? } ] }.

ParamRequiredDefaultNotes
durationyesIBKR duration string: 60 S / 1 D / 13 W / 6 M / 1 Y (URL-encode the space as + or %20)
barSizeno1 min / 15 mins / 1 hour / 1 day etc. (IBKR bar-size strings)
endDateTimenonow"" = now, or YYYYMMDD HH:MM:SS UTC
whatToShownoTRADES / MIDPOINT / BID / ASK / ADJUSTED_LAST / …
useRTHnofalseregular trading hours only
exchange, currency, primaryExchangenoclass defaultscontract overrides
refreshnofalsebypass cache read

Options/futures rates also take the contract-selecting params (expiry, strike, right for options; expiry + exchange for futures).

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL/rates?duration=1+Y&barSize=1+day&whatToShow=ADJUSTED_LAST"

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/forex/EURUSD/rates?duration=30+D&barSize=1+hour&whatToShow=MIDPOINT"

curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/futures/ES/rates?expiry=202609&exchange=CME&duration=30+D&barSize=1+day"

GET /stocks/{symbol}/ticks

Historical raw ticks (equities). Response { "symbol", "secType", "ticks": [ { "time", "price"?, "size"?, "bid"?, "ask"?, "bidSize"?, "askSize"? } ] }.

ParamRequiredDefaultNotes
startDateTime / endDateTimenoUTC window bounds
numberOfTicksno10001–1000
whatToShownoTRADES / BID_ASK / MIDPOINT
useRTHnofalse
refreshnofalse

GET /options/{symbol}/chain

Full option chain. Params: underlyingSecType (default STK), futFopExchange, underlyingConId, refresh. Response { "symbol", "underlyingConId"?, "chains": [ { "exchange", "tradingClass", "multiplier", "expirations": ["YYYYMMDD", ...], "strikes": [, ...] } ] }.

GET /futures/{symbol}/continuous and .../contracts

Both require exchange. /continuous returns one continuous contract; /contracts returns every expiry (?includeExpired=true to include expired). Both return the ContractDetailsList shape ({ "contracts": [...] }).

API — POST ///rates/ta

Bars + wickworks TA in one round-trip. POST but read-only — no account mutation. Contract-selecting params (expiry/strike/right, exchange/currency) go in the query string; the bar window + indicator spec go in the JSON body.

Request Body

FieldRequiredDefaultNotes
durationyesIBKR duration string (200 D, 1 Y)
barSizenoIBKR bar-size string
endDateTimeno"" = now, or YYYYMMDD HH:MM:SS UTC
whatToShownoTRADES / MIDPOINT / ADJUSTED_LAST / …
useRTHnofalse
indicatorsnowickworks indicator spec (see below)
recentBarsnoreserved; wickworks may ignore it

Response: { "symbol"?, "secType"?, "bars": [ ... ], "ta": { }, "asOf"? }.

indicators shape — "name": true for defaults, or "name": {"length": 21, ...} to tune (params flat on the object; add "type": "" only when the output key must differ from the indicator name, e.g. two RSIs as rsi14/rsi21). Catalog (same wickworks build as mt5-httpapi):

  • Moving averages: ema sma hma wma dema tema t3 kama alma linreg jma zlma rma fwma swma sinwma trima vwma vwap
  • Momentum: rsi mfi willr cci roc mom uo stoch stochrsi macd tsi trix fisher
  • Trend strength: adx aroon vortex
  • Volatility: atr natr
  • Volume / flow: obv ad cmf adosc kvo
  • Bands / channels: bbands kc donchian
  • Trailing signals: supertrend psar chandelierExit ichimoku
  • Compression: squeeze
  • SMC primitives: orderBlocks fvg bosChoch swingLevels srLevels recentRange liquidity previousHighLow sessions retracements
  • Analysis summaries: price levels momentum volume position slope

Full catalog with every param + output shape: github.com/psyb0t/docker-wickworks.

Match duration to your slowest indicator's lookback × ~2 for warmup (e.g. sma(200) → fetch ≥ 400 bars). Under-feed and wickworks returns a per-indicator deficit list. Returns 503 if the server has no wickworks URL configured.

curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL/rates/ta" \
  -d '{
    "duration": "200 D",
    "barSize": "1 day",
    "whatToShow": "ADJUSTED_LAST",
    "indicators": { "rsi": true, "macd": true, "bbands": {"length": 20, "std": 2} }
  }'

API — Orders (MUTATING — confirmation required)

Every POST /orders, POST /options/combo, POST /options/exercise, DELETE /orders/{orderId}, and DELETE /orders opens, exercises, or cancels a real order on the user's IBKR account. Before invoking any of them you MUST: (1) print the full resolved request (base URL, resolved account, asset class, symbol, action, quantity, orderType, prices, and expiry/strike/right for derivatives); (2) ask the user to confirm that specific action; (3) wait for an explicit yes. A prior confirmation does not carry over. Never place, modify, or cancel an order unless the user explicitly requested that specific action with the specific symbol/side/quantity/price — do not act on a vague instruction, and never place a "similar" or "adjusted" order the user didn't ask for. Never auto-retry a rejected order — a 4xx/5xx or a Trade whose orderStatus.status shows a rejection is a stop; report the rejection reason to the user and wait for a fresh, explicit instruction before submitting anything again, even with the same parameters.

GET /orders and GET /orders/{orderId} (read-only)

GET /orders{ "trades": [ Trade, ... ] }. GET /orders/{orderId} → one Trade. A Trade is { "contract": {...}, "order": { orderId, permId, action, totalQuantity, orderType, lmtPrice?, auxPrice?, tif, ... }, "orderStatus": { status, filled, remaining, avgFillPrice, permId, ... }, "fills": [...], "log": [...] }.

POST /orders

Place an order on any asset class. Body (OrderRequest):

FieldRequiredDefaultNotes
assetClassyesstock / option / future / cfd / forex / crypto
symbolyesroot symbol
actionyesBUY or SELL
quantityyes> 0
orderTypenoMKTMKT / LMT / STP / STP LMT / … (IBKR order types)
lmtPricenorequired for LMT
auxPricenostop trigger for stop orders
tifnoDAYtime-in-force
outsideRthnofalseallow fills outside regular hours
transmitnotruefalse = stage without transmitting
expiry / strike / rightfor derivativesoption/future contract selectors
exchange / currency / multiplier / tradingClass / primaryExchangenoclass defaultscontract overrides
conidnopass a resolved conid to skip contract lookup
accountnoserver defaulttarget account
goodAfterTime / goodTillDate / ocaGroup / parentIdnoadvanced routing

Returns a Trade snapshot (check orderStatus.status). This places a REAL order and moves real money — only call it for a symbol/side/quantity/price the user explicitly asked for. Example (place ONLY after explicit per-action confirmation):

# STOP: echo back "BUY 10 AAPL @ MKT" (or the LMT/STP price) to the user and
# get an explicit yes for THIS order before running the curl below.
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/orders" \
  -d '{"assetClass":"stock","symbol":"AAPL","action":"BUY","quantity":10,"orderType":"MKT"}'

# Futures limit order — same rule: echo symbol/side/qty/price, confirm, then send.
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/orders" \
  -d '{"assetClass":"future","symbol":"ES","expiry":"202609","exchange":"CME",
       "action":"BUY","quantity":1,"orderType":"LMT","lmtPrice":5500.00}'

If the response shows a rejection (non-2xx, or orderStatus.status indicating rejection/error), do not resubmit. Report the rejection to the user and wait for a new explicit instruction — even a retry of the identical order requires fresh confirmation.

DELETE /orders/{orderId} — cancel one

{ "status": "cancelling", "orderId": }. Confirmation required.

DELETE /orders — cancel ALL (global cancel)

{ "status": "global_cancel_requested" }. Cancels every open order. Enumerate with GET /orders, show the list, confirm the whole batch.

POST /options/combo — multi-leg (BAG)

Vertical / condor / butterfly / calendar. Body (ComboOrderRequest): symbol (req), legs (req — array of { conid, ratio (default 1), action (BUY/SELL), exchange (default SMART) }), action (req), quantity (req), orderType (default LMT), lmtPrice, tif (default DAY), exchange (default SMART), currency (default USD), account. Returns a Trade. Resolve leg conids from GET /options/{symbol}/chain + GET /options/{symbol} first. Confirmation required.

# Vertical call spread — confirmed action only.
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/options/combo" \
  -d '{"symbol":"AAPL",
       "legs":[{"conid":681000001,"ratio":1,"action":"BUY"},
               {"conid":681000002,"ratio":1,"action":"SELL"}],
       "action":"BUY","quantity":1,"orderType":"LMT","lmtPrice":1.20}'

POST /options/exercise — exercise / lapse

Body (ExerciseRequest): conid (req), action (req — EXERCISE or LAPSE), quantity (req, ≥ 1), account (req), override (default false). Returns { "status", "contract": {...}, "action" }. Exercise/lapse is irreversible — confirmation required.

API — History (read-only)

GET /history/executions

Today's fills. Optional filters: account, clientId, secType, symbol, exchange, side, timeAfter (YYYYMMDD HH:MM:SS UTC), refresh. Returns { "fills": [ { "contract": {...}, "execution": {...}, "commissionReport": {...}?, "time" } ] }.

GET /history/completed_orders

?apiOnly=false (default), ?refresh. Returns { "trades": [ {...}, ... ] } (today + a historical buffer).

Bearer / Token Auth

When api_token is set on the server (via config.yaml:api_token or the API_TOKEN env), every route requires Authorization: Bearer . The token is compared in constant time (hmac.compare_digest); a missing/wrong token returns 401 with the standard error envelope (code: UNAUTHORIZED). Empty/unset token = wide open — any process that can reach the socket can read account state and place orders, so on untrusted networks the token is mandatory.

curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/ping"

The agent obtains the token only from the API_TOKEN env var the user set, or from the user directly — never by reading config.yaml / .env.ibkr / workspace files.

Typical Workflows

Read-only: market data + TA (no confirmation needed)

# 1. Health.
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/ping" | jq

# 2. Contract sanity check.
curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL" | jq '.contracts[0].contract'

# 3. Daily bars for the last year.
curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL/rates?duration=1+Y&barSize=1+day&whatToShow=ADJUSTED_LAST" | jq '.bars | length'

# 4. Same bars + TA in one call.
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/stocks/AAPL/rates/ta" \
  -d '{"duration":"400 D","barSize":"1 day","whatToShow":"ADJUSTED_LAST",
       "indicators":{"rsi":true,"sma":{"length":200},"atr":true}}' | jq '.ta | keys'

# 5. Option chain → pick a strike → snapshot with Greeks.
curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/options/AAPL/chain" | jq '.chains[0].expirations[:3]'
curl -s -H "Authorization: Bearer $API_TOKEN" \
  "$IBKR_HTTPAPI_URL/options/AAPL/tick?expiry=20260619&strike=200&right=C" | jq '.modelGreeks'

Guarded: place an order (confirmation REQUIRED)

# 1. Which account am I about to touch? (paper DU... vs live U...)
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/accounts" | jq
# 2. Account state + open positions/orders — context before mutating.
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/account" | jq
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/positions" | jq
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/orders" | jq

# 3. STOP. Print the resolved request (base URL, account, symbol, action,
#    quantity, orderType, price) and get an explicit user "yes" for THIS order.

# 4. Only then place it.
curl -s -X POST -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  "$IBKR_HTTPAPI_URL/orders" \
  -d '{"assetClass":"stock","symbol":"AAPL","action":"BUY","quantity":10,
       "orderType":"LMT","lmtPrice":180.00,"tif":"DAY"}' | jq '.orderStatus'

# 5. Confirm state; cancel needs its own confirmation.
curl -s -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/orders" | jq '.trades[].orderStatus.status'
# curl -s -X DELETE -H "Authorization: Bearer $API_TOKEN" "$IBKR_HTTPAPI_URL/orders/"

Tips

  1. Base URL includes /v1. Every path is served under the fixed /v1 prefix. IBKR_HTTPAPI_URL=http://localhost:8889/v1.
  2. There is no order-modify endpoint. Cancel + re-place (each confirmed).
  3. Futures need exchange AND expiry. No exchange default for futures.
  4. rates/ta is POST but read-only — never account-mutating.
  5. 429 RATE_LIMIT_NEAR is expected under load — the server gates before crossing IBKR's pacing caps. Read details.retry_after_sec, back off, retry. Don't hammer through it — repeat pacing violations can get IBKR API access revoked.
  6. connected: false on /ping means the gateway socket is down (nightly IBKR restart ~01:00 ET, weekly 2FA push, or still booting). Market-data and order calls fail until it reconnects; retry after a short wait.
  7. Delayed data has null Greeks/quotes — free market_data_type: 3 gives 15–20 min delayed bars and often null option Greeks. Real-time needs an OPRA subscription + market_data_type: 1 on the server.
  8. ?refresh=true forces a fresh upstream pull on any cacheable read; the value is still cached for next time.

Related skills

Read and write Excel workbooks, worksheets, ranges, tables, and charts in OneDrive through Microsoft Graph with managed OAuth.

by byungkyu800 installs42 stars

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.

by fly0pants

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

More from psyb0t

Browse all skills

Drive a user-deployed mt5-httpapi MetaTrader 5 bridge over HTTP, with per-action confirmation on every real-money call.

by psyb0t107 installs4 stars

Docker-packaged browser automation for QA against anti-bot stacks and authorized detection testing.

by psyb0t137 installs2 stars

Self-hosted OpenAI-compatible speech service — transcription, translation, and synthesis from one container.

by psyb0t13 installs

Run ffmpeg, sox, and ImageMagick jobs against your files in a fixed-allowlist SSH sandbox.

by psyb0t71 installs

Generate speech audio via Qwen3-TTS over SSH with preset voices, voice cloning, and voice design.

by psyb0t55 installs

Drive one or more IMAP/SMTP mailboxes through a single REST + MCP endpoint — read, search, send, mark-seen, and delete across accounts in parallel.

by psyb0t15 installs