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:

  1. Flex token (valid 1 year)
  2. Transactions query ID (a single combined query - recommended)
  3. (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

  1. Log into Account Management (Lynx/IBKR portal).
  2. Open Reporting -> Settings -> Flex Web Service.
  3. Click "Configure" -> enable the service.
  4. IBKR shows a long alphanumeric Flex token. Copy it - it is shown

only once.

  1. 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:

SectionMandatory fields
TradestradeID, 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 TransactionstransactionID, type, description, amount, symbol, isin, currency, fxRateToBase, exDate, payDate, reportDate, accountId, conid
Corporate ActionstransactionID, type, description, symbol, underlyingSymbol, dateTime, quantity, proceeds, costBasis, fifoPnlRealized, fxRateToBase, assetCategory, multiplier, currency
Commission DetailstradeID, 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 1018 the 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 SO get

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:

  1. Flex client: 4 attempts within ~100 seconds (linear backoff

10 s, 20 s, 30 s, 40 s).

  1. 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:

  1. The manual endpoint kicks off a fresh Flex pull (with retry).
  2. On success the failure counter and pause are cleared automatically;

the next auto tick then runs normally.

  1. On failure the pause remains, but you see the current IBKR error

message immediately.