How to read a brokerage account from code

Positions, balances and transactions out of a consented brokerage account. Connecting takes a day; keeping the connection alive is the product.

Six aggregation APIs read a consented brokerage account: SnapTrade, Plaid Investments, Akoya, MX, Yodlee and Wealthica Business. Only SnapTrade sells to a two-person shop or places an order; the rest are read-only and quote by contract. The connection is a day's work. What you maintain afterwards is re-authentication, a coverage list you did not choose, and a per-connection bill that runs while the connection is broken.

The short way

SnapTrade is the one you can start on this afternoon. Your backend registers a user, hands them a hosted Connection Portal to log into their broker, and reads normalised accounts, balances, positions and orders back through one schema:

from snaptrade_client import SnapTrade, SnapTradeAuth

client = SnapTrade(auth=SnapTradeAuth.commercial_api_key(
    client_id="YOUR_CLIENT_ID",
    consumer_key="YOUR_CONSUMER_KEY",
))

# once per end user — the userSecret comes back only here, so store it
registered = client.authentication.register_snap_trade_user(user_id="user-123")

# send the user to the redirect_uri this returns; they log into their broker there
portal = client.authentication.login_snap_trade_user(
    user_id="user-123", user_secret="YOUR_USER_SECRET",
)

accounts = client.account_information.list_user_accounts(
    user_id="user-123", user_secret="YOUR_USER_SECRET",
)
positions = client.account_information.get_all_account_positions(
    account_id="ACCOUNT_ID", user_id="user-123", user_secret="YOUR_USER_SECRET",
)

One thing to get right on the first day rather than the second: the convenient single call that returned an account's balances, positions and orders together is deprecated. The reference page for GET /accounts/{accountId}/holdings says it returns HTTP 410 Gone for every customer that signed up after 11 May 2026, and points at the finer-grained balances, positions and orders endpoints instead. Write against those three.

If you are reading only your own accounts, SnapTrade Personal is a free mode of the same API and needs no commercial agreement. Every other product on this page does.

What the options are

Brokerage-first, self-serve, and the only one that writes. SnapTrade is built for brokerages rather than banks: 40 integrations on 13 September 2026, of which 16 support order placement and 24 are read-only. Starter is free for five connected accounts; past that it is $1 per connected user per month for once-daily cached data or $2 for real-time, billed in arrears with no contract. Transactions are cached and a day behind on every plan — for intraday activity you read orders instead.

Banking-first, with investments bolted on. Plaid Investments is three endpoints on the Link flow everyone already recognises: holdings, up to 24 months of transactions, and a billable refresh. Its coverage file of 12 August 2026 flags 3,213 institutions with investments support — 3,198 US, 15 Canadian. Holdings carry a nullable cost_basis and a tax_lots array that is empty when the institution supplies no lots, and CUSIP and ISIN are null by default unless you hold a CUSIP Global Services licence.

Identifiers that reconcile. Yodlee returns cusipNumber, isin and sedol as first-class fields on a holding, which is the one thing separating it from everything else here, and reaches US, UK, Australian and Indian institutions. The cost is that there is no route to production without a signed contract and a provisioned environment, and the sandbox is missing services the real one has.

Canada. Wealthica Business published 125 providers on 19 September 2026 — 21 banks, 84 brokerages, 20 others, with 102 returning positions — and it is the one that reaches Canadian group retirement plans and advisor platforms. Positions carry book_value, market_value and option_details; securities carry symbol and cusip but no ISIN and no per-lot array.

No scraping at all. Akoya is a network rather than an aggregator: banks and brokerages join as data providers, the consumer authenticates at their own institution, and nothing credential-shaped reaches you. Investments are a real product there — holdings with typed security objects, an asset-class breakdown, open orders, vesting and equity grants, and a separate tax-lot endpoint. Fidelity is the anchor brokerage.

The platform a bank already runs. MX bills holdings as their own product, and a user is enrolled in it the moment you call any of its read or list endpoints for them. A holding carries cost_basis, purchase_price, current_price with an as-of timestamp and equity-comp vesting, but no tax lots and no CUSIP. Mastercard Open Finance — the old Finicity — is the fourth US aggregator in the same shape, with holdings arriving as a position array on the account object.

One account rather than everybody's. If the account is yours and sits at a broker with its own API, the aggregator is a layer you are paying for and do not need. ib_async reads account summary, positions and PnL streams straight out of a running TWS or IB Gateway, under a BSD 2-Clause licence and with no per-connection bill — at the cost of being useless for anyone else's broker.

Where this breaks

Consent expires, and the re-authentication is yours to build. This is the maintenance that nobody budgets for. Plaid documents that certain institutions enforce an expiry on an Item's consent, exposes it as consent_expiration_time on /item/get, and fires a PENDING_DISCONNECT webhook in the US and Canada — PENDING_EXPIRATION in the UK and EU — seven days before it lapses; an ITEM_LOGIN_REQUIRED error means the same thing after the fact, and the fix in every case is to send the user back through Link in update mode. Akoya's shape is the same and its numbers are published: the ID token has a 24-hour maximum and the docs suggest treating it as good for no more than 15 minutes, while the refresh token may be perpetual, fixed — commonly one year — or rolling, depending on the provider, and when it expires the consumer goes through the consent flow again. SnapTrade calls the same state a disabled connection and requires you to generate a portal link with the existing connection id in a reconnect field; the user must log back into the same brokerage, because changing the connection during a reconnect returns an error. Budget the re-consent UI at the same size as the first-connect UI, because it is the one your users will see more often.

OAuth and a typed-in password are not the same integration. Where the broker offers OAuth, the user authenticates at the broker and no credential reaches the intermediary. Where it does not, the user types their brokerage login into a portal, and that connection breaks whenever the broker changes its login flow or adds a step. The split is published per integration and it is not uniform: of SnapTrade's 40 integrations, 26 are OAuth, 10 are credential-based, and 4 — Binance, Interactive Brokers, Kraken and Trading212 — require the end user's own broker-issued API keys, and the vendor's integrations page lets you filter on exactly that. Wealthica's split is 117 credentials, 5 token and 3 OAuth, so every Canadian bank-owned brokerage on it is a scraped connection. Akoya is the opposite corner: API-only by design, which is a security property and a coverage ceiling in the same sentence. Read the list before you promise anyone a break rate, because none of these vendors publishes one.

The coverage list chooses the product, not the feature comparison. Every one of these APIs does substantially the same thing to a payload; what differs is which institutions answer. Plaid publishes a coverage file you can read before you sign. Wealthica publishes a supported-providers page. SnapTrade publishes its integrations with their auth and trade flags. MX publishes no institution list at all, and its development environment reaches only MX's own test institutions — so you cannot verify a real brokerage connection before signing. Yodlee claims 90% of top-volume sites in four countries and names none of them. Akoya's provider directory sits behind the Data Recipient Hub login. Two of the six make you sign to find out whether they cover your users' brokers.

"Read-only" is about writes, and trading is a separate grant. Plaid Investments, Akoya, MX, Yodlee and Wealthica place no orders at all; nothing in their APIs would. SnapTrade does, at a minority of its integrations, and the integration list hides this unless you look: Fidelity, Vanguard US, Robinhood, Interactive Brokers, Questrade, Chase and Wells Fargo are all read-only there, and Schwab is read-only unless you bring your own Schwab commercial API key. Read access and trade access are separate grants at the broker, so a broker being "supported" tells you nothing about which one you have. What read-only does not mean is limited visibility — account numbers, orders and full transaction history are inside the read scope, and Yodlee is the only one here that puts full account numbers and holder names behind a second approval.

The price is a conversation, and the meter runs on broken connections. SnapTrade is the only one of the six that publishes a number. Plaid's own billing documentation states plainly that a price list is not available in the documentation and that rates appear during the Production access application — and the billing shape, which is published, is the part that stings: Investments is a per-Item subscription that Plaid charges "even if no API calls are made for the Item or API calls cannot be successfully made for the Item (e.g. because the Item is in an error state)", and only /item/remove ends it. SnapTrade behaves the same way for the same reason — a broken connection keeps billing because the vendor retains it so the user can reconnect. Akoya, MX, Yodlee and Wealthica print no figure at any volume; MX and Wealthica have no pricing page at all. Assume a quote, assume a minimum, and assume you are paying for connections that are currently returning a cached snapshot.

If you outgrow this

When it is one account and it is yours, stop paying per connection. The broker's own API is free, the entitlements are already yours, and ib_async is the card for the most common version of that. The trade is that it connects to nothing but Interactive Brokers, and to a desktop application that has to stay running.

When a file would do, it probably would. A CSV from the broker's own statements menu is the primary record, it goes back further than any API window, and it costs nothing — how to export your broker trade history is that path, and it is the right one until you need the data to refresh by itself.

When the answer you want is a portfolio rather than rows, none of these is the product. Aggregators return quantities and institution-reported prices; performance, allocation, currency handling and tax reporting are yours to build on top. Portfolio trackers is the neighbouring listing, and several of them have already bought the aggregation you are about to.

When two accounts have to agree, the blocker is usually the security identifier rather than the connection. Plaid nulls CUSIP and ISIN without a licence, MX and Wealthica return neither or only CUSIP, and Yodlee returns all three — what CUSIP, ISIN and FIGI actually are explains why that is a licensing question rather than a technical one.

The rest of the category is brokerage account aggregation.

The tools that do this

In the order this page recommends trying them. Paid placement does not affect this order.

  1. SnapTrade

    The only one that will sell to a two-person shop. Free for five accounts, then $1–$2 per connected user a month, and 16 of 40 integrations also trade.

    One API for reading brokerage holdings and placing orders at supported brokers.

    $1/moFree tier

  2. Plaid Investments

    3,198 US and 15 Canadian institutions with investments, tax lots on holdings, 24 months of transactions. Read-only, and the rate is on the application form.

    Read-only holdings, cost basis and investment transactions from 3,200 brokerages.

    Free tier onlyFree tier

  3. Yodlee

    The one holdings payload here carrying CUSIP, ISIN and SEDOL, across US, UK, Australian and Indian institutions. Production needs a signed contract first.

    Long-running aggregation platform whose holdings carry CUSIP, ISIN and SEDOL.

  4. Wealthica Business

    Canada, where the others are thin — 125 published providers, 102 of them returning positions. 117 are credential-based rather than OAuth.

    Canadian wealth aggregation — 125 published providers, positions, transactions, CUSIP.

  5. Akoya

    Bank-owned and API-only, so nothing credential-shaped reaches you — and a provider that has not joined the network is simply unreachable.

    Bank-owned API network for consumer-permissioned account and holdings data. No scraping.

  6. MX

    Holdings are a separate billable product, enrolled the moment you call one. Ninety days of transactions unless you buy the extension.

    Bank-grade aggregation API with investment holdings billed as its own product.

FAQ

Can I read my own brokerage account without being a company?

Through SnapTrade, yes — it runs a Personal mode alongside the commercial one, free, scoped to an individual's own accounts, and it is the only mode the vendor's hosted MCP server works in. Everywhere else the answer is no. Akoya requires a security review and a data access agreement signed through DocuSign, MX issues no key without a commercial relationship, Yodlee provisions production only after a contract, and Wealthica hands out keys by email after a sales call. Plaid's Trial plan allows ten Production Items for life, which is a demo rather than a product.

Does read-only mean the API cannot see my account number?

No. Read-only is about writes — no order, no transfer — and says nothing about how much of the account is legible. SnapTrade returns account numbers, positions, orders and transaction history; Yodlee gates full account numbers and holder names behind a separate Account Profile dataset that needs its own approval. If your concern is what the integrator can see rather than what it can do, read the payload schema rather than the word.

Why does the same account show a different price in two aggregators?

Because none of them is a market feed. Plaid, MX, Akoya, Yodlee and Wealthica all return the price the institution reported, at whatever moment the institution reported it, and only some populate a timestamp beside it. Two aggregators reading the same brokerage on the same evening can disagree simply because they synced at different times. For a valuation you can defend, price the positions yourself from a market data API and use the aggregator only for quantities.

How far back does transaction history go?

It varies more than anything else on these APIs. Plaid documents up to 24 months. MX returns 90 days under Account Aggregation and 24 months only if you also buy Extended Transaction History. SnapTrade imposes no window of its own and returns whatever the brokerage exposes, which is sometimes the account's whole life and sometimes much less. Wealthica documents no lookback at all. Anything older than the window lives in the broker's own statement archive.

Sources

  1. Investments — Plaid Docs Plaid, read
  2. Link update mode — Plaid Docs Plaid, read
  3. Billing — Plaid Docs Plaid, read
  4. Account Information — List Account Holdings SnapTrade, read
  5. Fix broken connections SnapTrade, read
  6. Token overview Akoya, read

The catalogue next door

This page names a handful of cards. The rest of them are in Brokerage Account Aggregation APIs, each filled in against the same schema, with the fields to narrow it yourself.

Last updated . Corrected in place: this is a reference page, not a dated post.