Skip to main content
Two things move an IB’s go-live date more than any engineering work: the reporting pack, and three record-level mistakes that break NFA reports after the record is expensive to change.
Prerequisites:
  • the read:reports and read:cash-movements scopes granted against your client — ask for both at the scopes gate, not later. See Path to production,
  • Funds handling — several reports are balance reports and the balance fields need reading carefully,
  • your firm strings and your IB anchor DCO account — see Firms, participants and accounts.

Reporting pack

Start this in week one. Several of the ten reports below have no platform source today, and the gap between “we can pull that” and “nobody has built that” is what moves an IB’s go-live date. ISVs never ask for this pack. It exists because your registration requires it, so the questions below arrive in our channel from IBs and nowhere else.

The pack

Five pieces, of which the reports are the largest:
  1. The NFA/CFTC demo of your system.
  2. Flow of customer funds — where money sits at each step, which for you is constrained by the prohibition on accepting or holding customer funds.
  3. A back and middle office overview.
  4. A risk-monitoring overview — intraday, overnight, limits and thresholds, and liquidation.
  5. Ten named reports.

The ten reports

“What we can supply today” below is the platform surface, not a report product. We do not produce these reports for you; where a source exists, you build the report from it.
Five of the ten have no evidenced platform source. Take the five marked VERIFY to your integration lead as a written list in week one, with the format your regulator expects for each. Do not assume a report exists because it is named in the pack — the pack names what you must produce, not what we hand you.
Partner-facing funding APIs for embedded partners are reported not to have been live when an IB asked for them. What is recorded, and is adjacent: the daily Vendor Fees report has no delivery mechanism (“Delivery method TBD”), the firm-level balance-ledger stream is “coming soon” with no date, and there is no bulk-export path and no async report job on the reporting surface. Confirm availability before you commit a delivery date to a regulator.

Reporting mechanics that break IB reports specifically

These are the four that produce tickets. POST /v1/report/trades/search unfiltered hits the 30-second CloudFront 504 about two thirds of the time. The same call with a symbol filter returns in ~130 ms, reliably. There is no documented bulk-export path, no published window limit and no async report job, so a month-end pull is a loop over symbols, not one call. Stored execution history is archived during maintenance, and pre-maintenance execution queries return empty. This is a material retention fact that appears only in the changelog. Maintenance is not the stable window the FAQ describes: August–September 2026 ran near-weekly one-off windows at 2–8am, 3–7am, 4–7am and 5–8am ET. Pull and persist your own copy of every traded day’s executions on the day. If your statement generation reaches back across a maintenance window, it can come back empty rather than wrong, which is harder to notice. GetTradeStats does not behave the way a reporting engineer expects. bars is a divisor, not an interval — 6 bars over 14 days gives 2.8-day buckets. Empty buckets are returned, not omitted, as an all-zero object, so treat zero as “no trades”, never as a print at price 0. cleared_* counterparts reflect post-clearing state and read zero for recently executed trades. Use where_clause, not field_filter: field_filter validates against a fixed column allowlist that excludes update_time and create_time, so a time cursor there returns InvalidArgument: field not allowed. Page tokens are offset-based, so dedupe on symbol when sweeping pages. The push channel does not scale to a customer book. The balance-ledger stream is per-account and counts against the 20-concurrent-streams-per-firm cap, so it cannot be run per customer. The firm-level ledger stream is “coming soon” with no date. That leaves no scalable push channel for RESOLUTION entries at scale — poll and reconcile instead. The reconciliation mistake this causes is specific: the most common one is using raw order_qty as the contract count. On an instrument with fractional_quantity_scale = 100 that overstates the fee 100×. Instruments with scale 1 make the naive arithmetic accidentally correct, so the error often surfaces only on the first fill in a scale-100 market. One dollar is priceScale × fractionalQtyScale notional units: when both are 100, commission_notional_collected = 100 means 0.01,not0.01, not 1.00.
There is no fee-schedule endpoint, and the taker coefficient has changed.Fee = Θ × C × p × (1 − p), rounded to the cent with banker’s rounding. Θ changed from 0.06 to 0.0695 on 2026-09-14 and every partner hand-edited their systems, because no endpoint publishes it. Put the coefficient in configuration, not in code, and reconcile fees against drop copy rather than recomputing them from a constant you trust.
Also relevant to any report that reaches settlement: RESOLUTION ledger entries may be gross with COMMISSION deducted separately, or net, and that is unanswered. Executions fold commission into a single net ORDER_EXECUTION entry, so do not assume settlement behaves the same way.

Risk-monitoring overview

The pack requires you to describe four things: intraday risk, overnight risk, limits and thresholds, and liquidation.
The platform side of all four is unpublished. Nothing in the verified ledger describes intraday or overnight risk monitoring, a limits-and- thresholds surface, or a liquidation mechanism for a participant account. Do not describe a platform control that has not been confirmed to you in writing — an NFA reviewer will ask where it is documented.
Three constraints you can state from the platform’s actual behaviour, because they shape your own risk model:
  • Your order surface is fill-or-kill only and you are always the taker. You cannot rest an order, so you cannot manage risk by working an order; every order is prefunded with an exact atomic transfer and either crosses or expires.
  • **An open short carries an obligation of up to 1.00percontract,andbalancereservationandmarginrequirementcamebackemptyontheledgerentriesforone.Holdback1.00 per contract**, and `balance_reservation` and `margin_requirement` came back **empty** on the ledger entries for one. Hold back 1.00 per open short contract in your own model until the field is named.
  • Day orders cancel at the traded-day roll as of 2026-09-13 (v0.0.89); GTD is the alternative. This does not apply to the fill-or-kill partner surface, but it applies to any generic order-entry question your reviewer asks about.

The NFA demo

The demo requirement is real and the environment question is not settled, because preprod cannot demonstrate a settled market.
Which environment the NFA/CFTC demo runs in is not decided. Raise the date and the environment in your channel as soon as the demo is scheduled, and say in the first line that it is a regulatory deadline with a date. Do not schedule a demo that depends on a preprod settlement.

What can go wrong

Naming and record requirements

Three record-level mistakes break IB reporting, and all three are cheap to prevent and expensive to unpick after go-live. Check every production record against this section before your first customer. At the account level and at the user level, the legal name must be a physical person’s name, or NFA reports error. Not your company name, not a DBA, not a product name, not “Operations”. One partner’s production record was entered as the company name. This is an internal SOP gap on our side as much as a partner-facing rule — nothing validates it at entry, so the failure surfaces later, in a report, against a record you can no longer casually change.
There is no self-service correction path for a production account or user record.There is also no re-KYC, reset or PII-update path on the KYC surface. Treat the first entry as the only cheap entry: check the records before first traffic, not after your first report run.
What to check, per record, before production traffic:
  • The account-level legal name is a natural person’s full legal name.
  • The user-level legal name matches that person’s government identity, not a display name from your app.
  • No record carries your firm’s name, a team name, or a test string.
  • Your own customer row stores the participantId we issued, verbatim, so the mapping back to the record is unambiguous.

Address format

The one published constraint is narrow: postal_code is five digits. A nine-digit ZIP+4, a hyphenated form or a non-US postal code will not satisfy it.
The full address format requirement is not published. The five-digit postal_code constraint is the only address rule in the verified ledger, and it is not plausible that it is the only rule NFA reporting imposes. Ask for the field-by-field format before you build your address capture, and validate on entry rather than on submission.
Related field constraint on the same payload: external_id is capped at 49 characters.
There is also no authoritative excluded-states or jurisdiction list in our docs. One partner asked three times and was never answered.Do not infer eligibility from the address fields you collect.

participantType casing, per path

This is a live defect, and the IB path is the accidental beneficiary of it. introducing_broker is spelled identically in both vocabularies. The IB path has therefore only ever worked by orthographic accident — not because the create path handles IB correctly, but because there is no casing difference to trip over. Canonical casing to send, per path:
  • Create: send the vocabulary spelling the create path validates against, exactly. For an IB that is introducing_broker; do not assume the uppercase transformation that ISV requires applies to you, and do not experiment on a production create.
  • Adopt and provision: introducing_broker. Anything you send is lowercased, so this is the spelling that survives.
Which casing is canonical per endpoint is a defect being corrected, not a design.Because the two vocabularies agree on introducing_broker today, a fix to either one could change your working call without any error you would predict. Do not hard-code the type string in more than one place, and if you get an HTTP 400 naming the participant type, report it verbatim rather than trying casings against production.

Do not confuse the DCO clearing-member ID with the DCM firm name

You hold three identity strings, and two of them look interchangeable and are not. Confusing a DCO clearing-member ID with a DCM firm name has stalled an onboarding outright. The failure is on our side, triggered by the record mismatch, and no error is returned to you — onboarding simply does not complete. Expect diagnosis to take time, so give us the identity strings up front. Record all three strings verbatim at your credential gate, label them in your own configuration by what they are rather than by which page you got them from, and never construct one from another. provisionedAccount, the fully-qualified DCM account name, is separately opaque: its account identifier cannot be derived from participant or user data.

Your recorded partner type

Get your firm’s recorded partner type in writing. The taxonomy is unresolved internally and leaks to partners as mislabelled tickets and wrong account structures. TSP is a fourth type in use internally — one partner was labelled ISV and was actually a TSP. A wrong type produces a wrong account structure, and the account structure is what your reports are built on.

What can go wrong with a record

Next

Connect