Set up the IBKR Flex import
WheelTrading reads your trade, dividend and cash-movement history from the IBKR Flex Web Service. This is the official end-of-day source at Interactive Brokers (with commissions, realized P/L, cost basis, withholding tax and spin-offs).
You need exactly three values from your IBKR account, entered once in WheelTrading:
- Flex token (valid 1 year)
- Transactions query ID (a single combined query - recommended)
- (optional) two legacy query IDs (trades + dividends) as a
fallback
All three are stored encrypted (Fernet/AES) in WheelTrading and are only visible to your own account. Other users (multi-user setup) cannot see your IDs - each user maintains their own triple.
Recommended for new users: create just the transactions query (section 3). The two separate legacy queries are no longer needed (since May 2026) - the combined query delivers everything and halves the number of IBKR calls.
1. Enable the Flex Web Service in IBKR
- Log into Account Management (Lynx/IBKR portal).
- Open Reporting -> Settings -> Flex Web Service.
- Click "Configure" -> enable the service.
- IBKR shows a long alphanumeric Flex token. Copy it - it is shown
only once.
- In WheelTrading: Settings -> Globals -> API keys ->
IBKR Flex token -> paste and Save.
Token validity: 1 year. WheelTrading warns 14 days before expiry via a banner; create a new token in IBKR and replace it in Globals.
2. Create the transactions query in IBKR
Reporting -> Custom Statements -> Flex Queries -> Create -> Activity Flex Query.
Name: anything, e.g. WheelTrading Transactions. Period: Last 365 Calendar Days (recommended) or Year To Date. Format: XML, Version: 3.
Sections - tick all of these
Mandatory:
- Trades
- Cash Transactions *(dividends, withholding tax, deposits/withdrawals,
interest)*
- Cash Report (balances per currency)
- Commission Details (individual fees)
- Transaction Tax (SEC/stamp fees)
- Interest Accruals (tiered)
- Forex P/L Details (FX transactions, USD<->EUR conversions)
Strongly recommended (tax completeness):
- Corporate Actions *(spin-offs etc. - required for correct cost basis
on VSNT, WBD, T-Mobile etc.)*
- Change in Dividend Accruals
- Open Dividend Accruals
- Sales Tax Details
You do NOT need (noise only): Accrued Interest, IBSS, IBG-Notes, FDIC, HK IPO, CFD Fees, Debit Card, Soft Dollar, Foreign Currency Balances, Bond/Rights Issues.
Fields
Each section offers detailed field lists. The simplest path is to click "All" in every ticked section. WheelTrading uses these mandatory fields:
| Section | Mandatory fields |
|---|---|
| Trades | tradeID, ibExecID, assetCategory, symbol, underlyingSymbol, currency, buySell, quantity, tradePrice, tradeDate, dateTime, proceeds, ibCommission, taxes, netCash, fxRateToBase, accountId, conid, notes, openCloseIndicator, multiplier, putCall, strike, expiry, settleDateTarget |
| Cash Transactions | transactionID, type, description, amount, symbol, isin, currency, fxRateToBase, exDate, payDate, reportDate, accountId, conid |
| Corporate Actions | transactionID, type, description, symbol, underlyingSymbol, dateTime, quantity, proceeds, costBasis, fifoPnlRealized, fxRateToBase, assetCategory, multiplier, currency |
| Commission Details | tradeID, commission, currency, dateTime |
With "All" you are safe. A missing field shows no obvious error in the UI - but cost basis or tax values may be incomplete.
Webhook field
Leave the "Webhook" field on the IBKR query page empty. WheelTrading uses standard pull mode (polling twice a day); webhooks are an IBKR premium feature and not supported.
Save -> note the query ID
After saving, IBKR displays the query ID (5- to 7-digit number, e.g. 1532801).
3. Enter the query ID in WheelTrading
Settings -> Globals -> API keys -> IBKR Flex query ID (Transactions) -> paste the ID and Save.
Once saved:
- The combined-flex-scheduler fetches the XML centrally **twice
daily** (cron 06:30 + 18:30 UTC) and feeds in parallel:
- trade history + cost basis (tax)
- dividends + withholding tax
- corporate actions (spin-off override for cost basis 0)
- transactions / cash movements
- The two older single-purpose schedulers (trades 06:15/18:15,
dividends 06:00/18:00) skip your user automatically - no duplicate call.
- The Globals panel shows after every run: last sync (with age),
result badge (+3 new, 12 known green / red on error).
Tip: right after entering the ID, hit the manual import button (Globals -> IBKR data import -> "Import trade history") so you don't have to wait for the next cron tick.
4. Multi-user notes
- Each user maintains their own triple (token + query ID).
- Your IDs are never shown to or shared with other users.
- If you have a joint/family account with multiple login users,
create a dedicated IBKR sub-account per WheelTrading user and one query per sub-account - otherwise everyone sees the same trades.
- The combined-flex-scheduler iterates active users sequentially with a
2-3 second gap to respect IBKR's 15-minute rate limit (error 1018 Too many requests).
- On
1018the scheduler auto-retries with exponential backoff
(max 3 attempts).
5. Optional: legacy separate trades and dividends queries
If you do not want to use the combined transactions query (e.g. your IBKR plan limits large queries), you can still create two separate queries the old way:
- `WheelTrading Trades` (Trade Confirmation Flex Query, section
Trades only) -> ID in IBKR Flex query ID (Trades)
- `WheelTrading Dividends` (Activity Flex Query, section *Cash
Transactions only) -> ID in IBKR Flex query ID (Dividends)*
As soon as the transactions query ID is set, it overrides these two fields for the auto-sync. The manual import buttons continue to use each respective single query when available.
6. What happens after the import?
- History: all trades visible under Trades -> History.
- Cost basis: computed automatically from BUY / SELL / Assignment +
premium adjustment of the wheel strategy.
- Spin-offs: stocks from corporate actions of type
SOget
cost_basis = 0 automatically (German tax law § 20 Abs. 4a EStG); the full proceeds at sale show up as profit. Marker: "Spin-Off lot (cost basis 0)" in the description.
- Taxes: withholding tax is capped at the 15 % DBA rate and shown
under Tax -> Dividends.
- Transactions (coming soon): the combined query already supplies
everything; the UI page is on the roadmap.
Idempotent: known entries are counted as skipped; you can repeat the import any time.
7. Common errors
- `Code 1001: Statement could not be generated`
IBKR is busy right now, or the query was just created and still needs to be registered (5-15 minutes). WheelTrading auto-retries on two levels:
- Flex client: 4 attempts within ~100 seconds (linear backoff
10 s, 20 s, 30 s, 40 s).
- Scheduler: if the client gives up, the scheduler tries up to
2 additional rounds with 180 s + 360 s backoff. Together up to ~10 minutes per auto tick.
If it still fails after that: open the query in IBKR Account Management, set period to Last 365 Calendar Days, save (even without changes) and wait. The next auto tick will pick it up. To test immediately: click "Now" on the performance page or under Account -> Globals.
- `Code 1018: Too many requests`
15-minute rate limit hit (e.g. because you also did a manual import). Automatically treated as transient and covered by the scheduler retry. Just wait 15 min or the next auto tick.
- Token expired
Flex tokens are valid 1 year. Create a new one in IBKR and replace it in Globals. NOT retried (not a transient problem).
- Query returns 0 trades
Wrong period (e.g. Today instead of Last 365 Days) or section Trades not ticked.
- Spin-off stock shows negative P/L in the tax tab
Section Corporate Actions missing. Edit in IBKR -> add it -> run the manual import in WheelTrading.
- `Code 1019: Statement generation in progress`
IBKR is currently generating the data. The scheduler waits; for manual imports try again 30 s later.
8. Automatic sync, retry & pause
WheelTrading fetches your Flex data in multiple layers so that you don't have to handle transient IBKR hiccups yourself.
Two fixed auto slots per day
- Trades: 06:15 + 18:15 UTC
- Dividends: 06:00 + 18:00 UTC
- Combined query (if you configured one): 06:30 + 18:30 UTC
(halves the IBKR quota load, replaces the two individual queries).
You can trigger an on-demand import any time via "Now".
Two-level retry
Every auto tick tries the Flex pull up to three times in a row. Between attempts there are 180 s and 360 s of wait time -- long enough that a short IBKR hiccup is typically over. Retries happen ONLY for transient error codes (1001, 1018, 1019, 1020). An expired token or a deleted query is reported immediately, waiting doesn't help there.
Within each attempt the Flex client itself retries another 4x with linear backoff (10/20/30/40 s). Combined this gives up to ~10 minutes per auto tick.
Circuit breaker: automatic pause after repeated failures
If two consecutive auto ticks fail despite the retry, WheelTrading automatically pauses the sync for 6 hours and sends one Telegram message (if you set that up):
⏸️ Flex sync paused The trades import is paused after 2 consecutive failed runs. Next attempt at earliest: 15.07.2026 22:00 UTC
Purpose: don't hammer against a known IBKR issue and don't burn rate limits. While the pause is active, every scheduled tick is silently skipped.
You see the pause in two places in the frontend:
- Performance page (header): the yellow banner additionally shows
"| Auto-sync paused until HH:MM".
- Account -> Globals -> Auto-sync: an amber notice above the
trades/dividends tiles explains the cause and next auto attempt.
Clearing the pause manually
Clicking "Now" (performance header or Globals panel) always goes through, even during an active pause:
- The manual endpoint kicks off a fresh Flex pull (with retry).
- On success the failure counter and pause are cleared automatically;
the next auto tick then runs normally.
- On failure the pause remains, but you see the current IBKR error
message immediately.