Request and retrieve a Flex report
Flex Web Service version 3 uses two HTTPS requests with different identifiers:
SendRequestaccepts the token and saved Query ID, starts one report instance, and returns aReferenceCode.GetStatementaccepts the same token and thatReferenceCode, then returns either the generated report or a Flex failure envelope.
This is a protocol contract, not yet the production polling policy. The later ingestion guide will add deadlines, capped backoff with jitter, cancellation, persistence, concurrency ownership, and unresolved-outcome handling. Do not turn the sequence below into an unbounded loop.
Use the current primary endpoints
The current official generation guide and retrieval guide use this base URL:
https://ndcdyn.interactivebrokers.com/AccountManagement/FlexWebService
Append /SendRequest or /GetStatement; both operations use GET. The official two-step workflow requires a User-Agent header on every request.
Build query parameters through the HTTP client's parameter encoder. Never concatenate the token into a logged string, include the complete request URL in an exception, or persist the token-bearing URL.
Step 1: submit SendRequest
Use these required query parameters:
| Name | Meaning | Version 3 rule |
|---|---|---|
t | Current Flex Web Service token | Required; secret. |
q | Query ID of the saved Flex Query template | Required; sensitive configuration. |
v | Flex Web Service version | Required; set to 3. |
The official SendRequest parameter page says versions 2 and 3 are accepted but instructs clients to use version 3. It also documents a limit of one SendRequest per second and ten per minute. That is a submission limit, not permission to create another report whenever retrieval is delayed.
Optional date overrides
The newer general request page lists only t, q, and v. A separate current official Advisor Portal guide documents these optional forms for SendRequest:
| Mode | Additional parameters | Documented boundary |
|---|---|---|
| Saved template period | None | Use the Flex configuration saved in Client Portal. |
| Explicit date range | fd=yyyymmdd and td=yyyymmdd | Range up to 365 days. |
| Period override | p=<days> | Period up to 365 days. |
The override evidence is published in the Advisor Portal guide, so its documented applicability is advisor configuration. Do not silently claim the same account-role coverage elsewhere without verification. Put overrides only on SendRequest; GetStatement identifies the already-created instance by reference code.
Validate the SendRequest XML envelope
Version 3 returns a FlexStatementResponse XML envelope for the submission outcome. Do not accept a reference code before checking Status.
For success, require:
<FlexStatementResponse timestamp="SYNTHETIC_TIMESTAMP">
<Status>Success</Status>
<ReferenceCode>SYNTHETIC_REFERENCE_CODE</ReferenceCode>
<url>LEGACY_URL_VALUE</url>
</FlexStatementResponse>
The structure is based on the official success response; every value above is synthetic. Retain ReferenceCode as the identity of this report instance. The current official page explicitly calls the lower-case <url> element legacy and says to ignore it. Do not use that value as the retrieval host.
:::warning Pinned ib_async incompatibility
ib_async 2.1.0 FlexReport.download looks for an upper-case Url, asserts that it exists, and uses its value as the polling base. That pinned library behavior conflicts with the current official lower-case legacy element and ignore instruction. Do not treat the helper as a conforming implementation of this current endpoint contract without a reviewed wrapper or upstream fix.
:::
For failure, expect the same root with a failed status and explicit error elements:
<FlexStatementResponse timestamp="SYNTHETIC_TIMESTAMP">
<Status>Fail</Status>
<ErrorCode>SYNTHETIC_ERROR_CODE</ErrorCode>
<ErrorMessage>SYNTHETIC_ERROR_MESSAGE</ErrorMessage>
</FlexStatementResponse>
The element contract comes from the official failure response. Classify by ErrorCode; never use the human-readable message as the sole machine key. The complete retry and terminal-error table is a later slice.
Step 2: retrieve with GetStatement
Use the primary base URL with /GetStatement and these required query parameters:
| Name | Meaning | Version 3 rule |
|---|---|---|
t | The same access token | Required; secret. |
q | ReferenceCode from the successful submission | Required; it is not the saved Query ID. |
v | Flex Web Service version | Required; set to 3. |
The official GetStatement parameter page explains that one saved query can generate many report instances and that the reference code selects a particular instance. Keep the Query ID and ReferenceCode in separate typed fields; reusing a variable named only q across both steps hides this critical change in meaning.
Generation may not be finished when the first retrieval is attempted. The current retrieval guide says larger requests may need a longer wait, and the official error table identifies 1019 as statement generation in progress. A FlexStatementResponse failure with 1019 means this reference is still pending; it is not a completed report and not a reason to issue another SendRequest.
The current official Advisor Portal guide shows a failed version 3 retrieval as FlexStatementResponse with Status=Fail, ErrorCode, and ErrorMessage. Its documented account-role applicability is advisor configuration. The general error table assigns its error codes to both endpoints, but does not separately define a broader failure-envelope schema.
When GetStatement returns the report, its serialization follows the saved query's output configuration. This documentation's automated path requires XML, while the official template controls also offer CSV and delimited text. For XML completion, require a FlexQueryResponse root rather than FlexStatementResponse. That root is corroborated here by the pinned ibflex v1.1 library source, not asserted as a current official protocol guarantee; the later XML-model slice will add the complete envelope/cardinality evidence.
Repository validation policy: do not treat one HTTP Content-Type value as sufficient proof of success. The reviewed current request pages define XML outcome elements and configured report formats but no normative response MIME mapping. The later XML-safety slice will require bounded size, header checks, root validation, and safe parsing together.
Keep the identities and states distinct
| State | Durable identity | Valid next action |
|---|---|---|
| Template configured | Query ID plus template revision | Submit one SendRequest. |
| Submission succeeded | Query ID plus returned ReferenceCode | Retrieve that reference with GetStatement. |
| Generation pending | Same ReferenceCode | Retry retrieval under the later bounded polling policy. |
| Report returned | Same ReferenceCode plus response-body hash | Validate and parse; do not submit a duplicate request. |
| Flex failure returned | ReferenceCode when available, plus error code | Apply the later retry/terminal classification. |
| Transport outcome unknown | Query identity and attempt record | Treat as unresolved; do not infer that no report was created. |
The final two rows state repository lifecycle policy, not additional IBKR guarantees. They prevent transport uncertainty from being mistaken for a safe duplicate submission.
Contract checklist
- Every request uses HTTPS, the primary
ndcdynbase, and a non-secretUser-Agentheader. -
SendRequestreceives token + Query ID +v=3through an encoder. - Optional
fd/tdorpoverrides are used only where their documented applicability is accepted. - The submission body must be
FlexStatementResponsewith a recognizedStatus. - Success requires a
ReferenceCode; the legacy<url>value is ignored. - Failure records
ErrorCodewithout logging the token-bearing URL. -
GetStatementreceives token + ReferenceCode +v=3, never the Query ID asq. - A pending reference is retrieved again later; it does not cause a duplicate
SendRequest. - A returned body is not trusted solely because of HTTP status or
Content-Type.
Next, the registry and error guide will classify polling, retry, throttling, expiration, completion, and terminal-error relationships before the production polling policy is implemented.