Getting started
This page takes you from nothing to a running stack that answers GET /v1/ping with "connected": true. Use a paper account for all of it. Every order endpoint acts on whatever account the gateway logs into.
Before you start
- An IBKR Pro account (Lite accounts have no API access) and its paper trading login.
- IBKR Mobile paired with the account. The first login and then roughly one login a week ask for a 2FA push.
- Docker with the Compose plugin, Make, and
python3with PyYAML on the host.run.shreadsconfig/config.yamlwith Python before it starts the stack.
1. Clone
git clone https://github.com/psyb0t/ibkr-httpapi
cd ibkr-httpapi
2. Pick the gateway image
The ibgateway service runs whatever IBKR_GATEWAY_IMAGE names. Unset, it pulls ghcr.io/gnzsnz/ib-gateway:stable. IBKR’s installer license forbids redistributing images that contain the gateway, so the intended route is to build one yourself from gnzsnz/ib-gateway-docker (its build downloads the installer and checks its checksum) and point the variable at it:
export IBKR_GATEWAY_IMAGE=registry.example.com/ib-gateway@sha256:<digest>
run.sh rewrites .env on every start, so set this in your shell or edit the image: line in docker-compose.yml after the first run. Do not put it in .env.
3. Write config/config.yaml
cp config/config.yaml.example config/config.yaml
Change these three things:
api_token: set it to a random value, for example the output ofopenssl rand -hex 32. Empty means no auth at all.market_data_type: the example ships with1(live), which needs paid market data subscriptions. Set3(delayed, free) if you have none.gateway.port:4002for paper,4001for live. See troubleshooting if the API cannot connect with the gnzsnz image.
Every other key is described on the configuration page.
4. Write .env.ibkr
cp .env.ibkr.example .env.ibkr
TWS_USERID=your_ibkr_username
TWS_PASSWORD=your_ibkr_password
TRADING_MODE=paper
Compose loads this file into the gateway container only. The API never sees your IBKR password.
5. Start the stack
make up
make up runs run.sh, which:
- creates
logs/,.data/ibgateway/and.data/nginx/; - copies
docker-compose.yml.exampletodocker-compose.ymlif it does not exist yet; - stops with an error if
config/config.yamlor.env.ibkris missing; - copies
nginx/nginx.conf(or the example) to.data/nginx/nginx.conf; - writes
.envwithAPI_TOKEN,IBKR_GATEWAY_PORT,API_HOST_PORTandWICKWORKS_URLtaken fromconfig.yaml; - asks before restarting if the stack is already up, then runs
docker compose up -d.
The first start builds the api image and pulls nginx and wickworks. IBC then logs the gateway into IBKR. Watch it and approve the 2FA push on your phone when it arrives:
docker compose logs -f ibgateway api
The API logs ib_async_connected once the socket is up.
6. Check it
export API_TOKEN=<the api_token from config.yaml>
curl -s -H "Authorization: Bearer $API_TOKEN" http://localhost:8889/v1/ping
{
"status": "ok",
"connected": true,
"serverVersion": 178,
"startTime": "2026-06-19T00:00:00+00:00",
"uptimeSeconds": 12.5,
"msgsSent": 20,
"msgsRecv": 31
}
Every REST path lives under /v1. http://localhost:8889/ping without the prefix is a 404.
7. First real calls
# Contract details
curl -s -H "Authorization: Bearer $API_TOKEN" \
http://localhost:8889/v1/stocks/AAPL
# Snapshot quote
curl -s -H "Authorization: Bearer $API_TOKEN" \
http://localhost:8889/v1/stocks/AAPL/tick
# 30 days of daily bars
curl -s -H "Authorization: Bearer $API_TOKEN" \
"http://localhost:8889/v1/stocks/AAPL/rates?duration=30+D&barSize=1d"
# Option chain, then one contract's quote with Greeks
curl -s -H "Authorization: Bearer $API_TOKEN" \
http://localhost:8889/v1/options/AAPL/chain
curl -s -H "Authorization: Bearer $API_TOKEN" \
"http://localhost:8889/v1/options/AAPL/tick?expiry=20260619&strike=200&right=C"
Pick an expiry and strike that exist in the chain response. With delayed data (market_data_type: 3) the Greeks fields are often null.
Next
- Every endpoint and its parameters: REST API.
- Connect an agent: MCP server and Agent integrations.
- Before you open it to anything but localhost: Security.