Understand the Flex reporting boundary
IBKR Flex reporting is an account-reporting workflow, not a TWS socket request. A saved query template is configured manually in Client Portal; a standalone HTTPS service generates and returns an instance of that template; your application validates, parses, and persists the returned XML. TWS or IB Gateway does not need to be running for this workflow.
That last sentence is an explicit inference from two separately sourced facts: IBKR describes Flex as a standalone HTTP API, and pinned ib_async 2.1.0 implements its helper with direct urllib.request.urlopen, without an IB connection or TWS client.
Three owners, three failure boundaries
| Owner | Responsibility | Typical failure boundary |
|---|---|---|
| Client Portal | Define an Activity or Trade Confirmation Flex Query, select its output, and configure Flex Web Service access. | The template, query ID, token, expiration, or optional IP restriction is wrong or unavailable. |
| Flex Web Service | Accept an HTTPS report request, prepare the report, and make it available for retrieval. | The request is rejected, remains in progress, or ends without a usable report. |
| Your application | Bound HTTP and overall deadlines; validate the response; parse exact values; persist provenance; reconcile duplicates. | The response is malformed, unexpectedly shaped, too large, partially persisted, or parsed lossily. |
Do not collapse those owners into one “IBKR API call.” A portal configuration error is not a socket-session error. Successful XML retrieval does not prove that every field your application expects was selected in the saved template.
Choose the report family by data freshness
IBKR's current introduction distinguishes two Flex Query families:
- Activity Flex Queries are updated once daily at close of business. IBKR describes retrieving the prior day's Activity Statement at the start of the following day as the normal pattern.
- Trade Confirmation Flex Queries update during the day as executions become available, but they are not real-time. IBKR says a new execution is typically available within five to ten minutes.
The same source says the service is not suitable for active polling for newly generated reports. Polling while one requested report is being prepared is a different operation from repeatedly creating fresh reports in search of new account activity.
Use TWS execution callbacks and reconciliation requests for live trading state. Use Flex reports for reporting records whose freshness and schema follow the saved Flex Query.
Distinguish reports from Flex Query templates
The Client Portal Flex Query guide draws this customization boundary:
| Portal reporting surface | Customization boundary |
|---|---|
| Activity Statement | A standard account-activity report. A Customized Activity Statement can include or exclude whole sections. |
| Activity Flex Query | A saved template for Activity Statement data that can include or exclude individual fields and choose TEXT or XML output. |
| Trade Confirmation Report | The ordinary report is not customizable. |
| Trade Confirmation Flex Query | A saved, field-selectable template for Trade Confirmation data. |
Creating a Flex Query does not configure TWS or create a socket API route. It defines the reporting template later addressed by its query ID through Client Portal or the Flex Web Service.
The saved template owns the returned shape
The same official guide describes the template as controlling fields, time period, field order, and TEXT or XML output. Two operational inferences follow:
- A missing XML attribute may mean “not selected in this template,” not “the account value is null.”
- Changing a saved query is a schema change for every consumer of that query ID.
For automated ingestion, select XML and version the expected template shape in application configuration. Record the query identity and a template/schema revision beside every ingested report. The Activity Flex Query Reference is the current official index of selectable Activity sections and fields; it is not a guarantee that a particular saved query includes them.
Keep service credentials in the control plane
The current Flex Web Service configuration guide documents enabling or disabling the service, generating a token, rotating it so the prior token becomes invalid, selecting an expiration, and optionally restricting a valid IP address.
Treat the token as a secret and the query ID as sensitive account configuration:
- inject them from a secret manager;
- never commit them, include them in fixtures, or render them in exception text;
- redact URL query strings, because clients may place both values in the URL;
- record a non-reversible configuration identifier for operational correlation;
- plan rotation before expiration and distinguish rotation from report-request retry.
Authenticated portal HTML, screenshots, real identifiers, and downloaded statements are not documentation fixtures.
Know what pinned ib_async.FlexReport does
ib_async.flexreport.FlexReport is a convenience client and parser. It is not an async IB method despite the package name.
| Surface in pinned 2.1.0 | Exact library behavior | Production consequence |
|---|---|---|
| Constructor | Truthy token and queryId call download immediately; otherwise a truthy path calls load. | Construction can block on network or disk I/O. |
get_url | IB_FLEXREPORT_URL overrides the default. Validation requires a scheme and network location, not specifically HTTPS. | Validate the configured scheme and allow-listed host outside the helper. |
download | Builds t, q, and v=3 into a URL and calls blocking urlopen without an explicit HTTP timeout. | Do not call it on an event loop or expose the URL in logs. Wrap or replace it with finite connect/read and overall deadlines. |
| Polling | Sleeps for one second in an unbounded loop while the first root child reports generation in progress. | The helper has no maximum attempts, deadline, cancellation seam, capped backoff, or jitter. |
| First response | Requires ReferenceCode and Url after Status=Success, then uses the returned URL as the polling base. | Validate the current official protocol independently; do not treat this pinned implementation as protocol authority. |
topics and extract | topics returns tags for elements with attributes. extract maps matching element attributes to dynamic objects. | Topic presence and object shape follow the report, not a declared schema. |
| Numeric parsing | With parseNumbers=True, extract attempts float and then int conversion for every attribute. | Identifiers can lose leading zeros and money can lose decimal exactness. Prefer parseNumbers=False until fields are typed deliberately. |
df | Passes extract output to util.df. | A DataFrame does not add schema validation or exact numeric policy. |
load and save | load reads the complete file as bytes and parses it with ElementTree; save writes the retained bytes. | Enforce size, XML-safety, root, and shape checks before trusting a loaded report. |
See the generated ib_async.flexreport reference for version-pinned signatures and per-symbol provenance.
Evidence and publication boundary
This section uses the same pipeline as the TWS documentation:
- Canonical source and redirect history are recorded in the manifest.
- Robots and public terms are reviewed before retrieval.
- Retrieval is sequential, conditional where possible, and content-addressed.
- Raw HTML and normalized section records remain private.
- Only atomic facts, hashes, retrieval times, original explanations, and short source links enter the public site.
- Real tokens, account identifiers, authenticated portal state, and customer XML remain outside the repository and generated site.
Continue with Client Portal query setup, design the saved template as a versioned consumer contract, configure and rotate Flex Web Service access, and request and retrieve a report through the version 3 lifecycle. Later slices add the full error model, bounded production polling, XML validation and typing, parser comparison, and the production ingestion owner.