| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/ |
None | Service info JSON |
GET |
/health |
None (restrict at nginx) | JSON status |
POST |
/ibkrbot or / |
key on ORDER |
Webhook ingress |
Base URL examples:
- Dev:
http://127.0.0.1:5001 - Local nginx:
http://127.0.0.1:8088 - Production:
https://your.domain.example
Returns JSON:
{
"status": "ok",
"ib_connected": true,
"ib_client_id": 326,
"ib_last_error": null,
"queue_depth": 0,
"orders_processed": 42,
"worker_last_error": null,
"dedup_enabled": false,
"dedup_size": 0,
"dry_run": false
}Protect with nginx IP allowlist + basic auth in production (see nginx/ibkrbot-site.conf.template).
Same handler on both paths. Prefer /ibkrbot on shared nginx vhosts; use / when the domain is dedicated to ibkrbot only.
Accepts JSON body. Routes by type:
type |
Behavior |
|---|---|
ORDER |
Auth → (optional dedup) → adapter → worker → IB |
INFO |
Log only (key stripped) |
MONITOR |
Log + 200 ignored (not implemented v1) |
| Status | Body | Meaning |
|---|---|---|
| 200 | {"status":"accepted",…} |
Queued for execution |
| 200 | {"status":"duplicate",…} |
Same trade_id within TTL (TRADE_ID_DEDUP_ENABLED=1) |
| 200 | {"status":"logged"} |
INFO |
| 400 | {"status":"error",…} |
Bad JSON / schema |
| 403 | {"status":"error",…} |
Invalid key |
Detection: type=ORDER, side present, no group, schema≠v2.
See samples/legacy_flat_entry_order.json.
| Field | Required | Notes |
|---|---|---|
key |
yes | SHA224(PIN) hex |
trade_id |
yes | Client id; dedup key when TRADE_ID_DEDUP_ENABLED=1; suffix routes intent |
account_type |
yes | main → ACCOUNT_0 |
symbol, secType, currency, exchange |
yes | IB contract |
side |
yes | BUY / SELL |
size |
yes | String quantity |
est_price |
entry | Fill estimate for bracket prices |
stop_loss_percent, profit_taking |
optional | Adapter computes STP/LMT |
min_tick |
optional | Price rounding |
force_single_entry |
optional | Y blocks duplicate same-side entry |
Futures / options (legacy flat): include the same IB contract fields as v2 on the top-level payload (not nested under contract):
| Field | FUT | OPT |
|---|---|---|
lastTradeDateOrContractMonth |
yes | yes |
multiplier |
recommended | recommended |
tradingClass |
recommended | recommended |
strike |
— | yes |
right (C / P) |
— | yes |
localSymbol |
optional | optional |
Applies to Entry, Flat_, Flip, and Close. Samples: legacy_flat_fut_flat.json, legacy_flat_opt_flat.json.
Full behavior (side, size, stops, examples): INTENTS.md.
| Suffix | Intent | Summary |
|---|---|---|
Entry |
entry |
MKT open + stop/profit after fill |
Flat_ |
flat |
Cancel symbol stops + MKT flatten to zero |
Flip |
flip |
Cancel symbol stops + MKT reverse sign + new stops |
Close |
close |
Partial MKT exit (size capped to position) |
Format: {YYYYMMDDHHMM}-{TICKER}-{side}-{suffix} (NY time). Flip/Flat require side to oppose the current position (see INTENTS.md).
Note:
"v2"here is the webhook JSON format from the design spec — not thedev-ibkrbot-v1repo name. Legacy flat ORDERs (schema A) work in this repo too.
Detection: schema: "v2" or group.legs present.
See samples/v2_stock_bracket.json.
{
"schema": "v2",
"type": "ORDER",
"key": "...",
"account_type": "main",
"trade_id": "202607091200-AAPL-buy-Entry",
"intent": "entry",
"contract": {
"symbol": "AAPL",
"secType": "STK",
"exchange": "SMART",
"currency": "USD"
},
"group": {
"oca_type": 1,
"legs": [
{ "role": "entry", "action": "BUY", "qty": 1, "order_type": "MKT" },
{ "role": "stop", "action": "SELL", "qty": 1, "order_type": "STP", "aux_price": 200.0 },
{ "role": "profit", "action": "SELL", "qty": 1, "order_type": "LMT", "lmt_price": 220.0 }
]
}
}| secType | Extra fields |
|---|---|
STK |
exchange (usually SMART) |
FUT |
lastTradeDateOrContractMonth, multiplier, localSymbol, tradingClass |
OPT |
lastTradeDateOrContractMonth, strike, right (C/P), tradingClass |
CASH |
currency, exchange (IDEALPRO for FX) |
| Type | Leg fields | Notes |
|---|---|---|
MKT |
qty, action |
Market |
LMT |
+ lmt_price |
Limit |
STP |
+ aux_price |
Stop trigger |
MIT |
+ aux_price |
Market-if-touched (trigger in aux_price) |
TRAIL |
+ trailing_percent and/or aux_price |
Trailing stop (% or amount); optional lmt_price for TRAIL LIMIT. Samples: v2_futures_trail.json, v2_stock_trail_limit.json |
KEY=$(cd /opt/ibkrbot && ./venv/bin/python -c "import auth; print(auth.get_token())")
# Inject key into sample
jq --arg key "$KEY" '.key = $key' docs/samples/legacy_flat_entry_order.json \
| curl -s -X POST http://127.0.0.1:5001/ibkrbot -H 'Content-Type: application/json' -d @-Guide: ADAPTERS.md — interface, OrderGroup, plugins, tests, modifying built-ins.
Optional ibkrbot.yaml (env IBKRBOT_CONFIG):
adapters:
- module: mypackage.ibkr_adapters
class: ZapierAdapter
priority: 50
config:
source_field: source
source_value: zapierSee ibkrbot.yaml.example and adapters/example_plugin_adapter.py.
| Goal | Use this |
|---|---|
| Entry vs Close vs Flat vs Flip | INTENTS.md — side, size, sizing math, log outcomes |
| Send a webhook (HTTP JSON) | This file + samples/ — that is the ibkrbot transaction contract |
| Build / change an adapter | ADAPTERS.md |
| TradingView-style legacy ORDER | Schema A below + legacy_flat_entry_order.json |
| IB contract & order field details | IB TWS API — Contracts, Orders, Bracket orders |
| Python IB client (runtime) | ib_async — maps webhook fields to placeOrder |
Summary: Start with ibkrbot API.md + samples to build the JSON payload. Use IBKR’s TWS API docs when you need to look up valid secType fields, exchanges, expiry/strike syntax, or order types (MKT, LMT, STP, OCA). ibkrbot adapters compile your JSON into IB orders; you do not call the IB API directly from the webhook client.
v2 contract / group.legs fields align with IB’s Contract and Order objects (see ibkrbot/contracts.py and ibkrbot/executor.py).