> ## Documentation Index
> Fetch the complete documentation index at: https://platform.trendlinelabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Account reads

Keys granted `account:read` read their own user's balances, positions, orders and fills. Both access
levels, `read_only` and `trading`, include `account:read` for keys created while account reads are enabled ([Authentication](https://platform.trendlinelabs.ai/guides/authentication.md)).

| route | operation |
| - | - |
| `GET /public/v1/account/balances` | getAccountBalances |
| `GET /public/v1/account/positions?venue=` | listAccountPositions |
| `GET /public/v1/account/orders?venue=&state=` | listAccountOrders |
| `GET /public/v1/account/fills?venue=` | listAccountFills |
| `GET /public/v1/account/portfolio` (not yet enabled; its own switch) | getAccountPortfolio |

## Venues served

`yes`: the route reads that venue. `no`: positions, orders and fills answer 422 venue\_unsupported, and
balances lists the venue as unsupported.

| route | kalshi | polymarket | limitless | predictfun |
| - | - | - | - | - |
| balances | yes | yes | yes | yes |
| positions | yes | yes | yes | yes |
| orders, state=open | yes | yes | no | no |
| orders, state=recent | yes | no | no | no |
| fills | yes | yes | no | no |

## Codes

| status | code | meaning |
| - | - | - |
| 401 | unauthorized | missing or partial credential headers, parts that do not belong together, or a key that is unknown, revoked or expired |
| 403 | access\_not\_granted | API access is free but granted on request; request it on [https://trendlinelabs.ai/developer](https://trendlinelabs.ai/developer) |
| 403 | tier\_required | the key owner's plan does not include API access |
| 403 | insufficient\_scope | the key lacks account:read |
| 403 | ip\_not\_allowed | outside the key's allowlist |
| 404 | venue\_not\_connected | we hold no usable account of yours for that venue: not connected, held by another account, or (Limitless positions) an empty answer for a profile not verified as your sub-account (found only through its public profile); the message names the reason |
| 409 | venue\_auth\_failed | the venue refused your own stored credential; reconnect it |
| 422 | invalid\_request | an unknown parameter, limit outside 1-100, or a cursor replayed elsewhere |
| 422 | venue\_unsupported | the route does not serve that venue yet |
| 429 | rate\_limited | too many requests |
| 500 | internal\_error | an unexpected failure on our side |
| 503 | dependency\_unavailable | our own store could not be read |
| 503 | venue\_unavailable | the venue could not be read; the message names why; retry after `Retry-After` |
| 503 | venue\_busy | another read of the same venue for your account is running, or the venue budget is spent; retry after `Retry-After` |

Polymarket balances are two tokens on Polygon, each listed on its own in `amounts`: pUSD (Polymarket USD, 6
decimals, the cash Polymarket's exchanges trade in) and USDC.e (6 decimals; at the deposit wallet, money deposited but not yet
converted to pUSD). Both are worth \$1 each, so an address's dollar amount is pUSD plus USDC.e. The website's header shows
that sum for your deposit wallet, so for most accounts the `deposit_wallet` entry here equals the header. They
differ in four ways:

* **More addresses.** This route reads every address that can fund your Polymarket orders: the deposit wallet,
  the Safe, your Polymarket proxy wallet if you have one, and the wallet itself (`kinds` names each; one address
  serving two roles is listed once). The header reads the deposit wallet only, so money at the other addresses
  shows here and not there.
* **Which wallet.** Both start from one wallet and derive the deposit wallet from it. This route uses the
  wallet you chose for Polymarket on the website, if you chose one; otherwise your first linked wallet; otherwise
  your Trendline wallet. The header ignores that choice and always uses your first linked wallet, else your
  Trendline wallet. With a chosen Polymarket wallet that is not your first linked wallet, the two read different
  addresses; `wallet` names the one read here.
* **Failures.** If any token at any address cannot be read, Polymarket reads unavailable here; it is never shown
  as 0. The header shows 0 for an empty answer.
* **Freshness.** This route reads the chain on every request. The header keeps its figure for up to 30 s, and on
  a new page first shows the last figure saved in your browser, so it can briefly lag a deposit or a trade.

predict.fun balances are the USDT (18 decimals) on BNB Chain held by your Trendline wallet, the token and
wallet the website's header reads, with two differences: a user with no Trendline wallet reads not\_connected
here (the header falls back to a linked wallet), and the header can be set to show another address for
display, which this route never reads. The venue reads unsupported with reason venue\_disabled while
predict.fun is switched off on our side.

predict.fun positions are read for the same wallet: open positions, and positions in resolved markets
not yet redeemed (those on a losing outcome are not listed); `size` reads the venue's `amount` as 18-decimal shares
and `avg_price` is its average buy price in USD. While predict.fun is switched off on our side, its positions answer 422 venue\_unsupported.

A venue that cannot be read is never an empty 200. On balances, a venue over its budget reads
unavailable with reason venue\_busy while the route answers 200.

Each venue read has 5 s to answer; a slower venue answers 503 venue\_unavailable (on balances, that
venue reads unavailable with reason timeout). Polymarket positions are read at most 4 pages of 500 rows
per wallet address; a wallet holding more answers 503 venue\_unavailable. Polymarket holdings of 0.1 shares or less
(the venue's dust floor) are not listed, and neither are positions in markets Polymarket has archived. Venue calls also spend from
per-venue call budgets; a spent budget answers 503 venue\_busy.

## Portfolio (not yet enabled)

`GET /public/v1/account/portfolio` answers 404 until it is switched on, separately from the other account
routes. It needs `account:read` and takes no parameters. `venues` always holds kalshi, polymarket, limitless
and predictfun, each with three components:

| component | what it is |
| - | - |
| `cash` | exactly that venue's entry in `GET /public/v1/account/balances` (status, reason, wallet, held) |
| `positions_value` | the venue's own value field for your positions, summed exactly; `field` names it |
| `pnl` | the venue's own unrealized profit and loss field, summed exactly |

Each component has a `status` (ok, not\_connected, unavailable or unsupported). A component that is not ok
carries a `reason` and no amount; an unreadable venue is never shown as 0. A venue over its budget reads
unavailable with reason venue\_busy while the route still answers 200. Components resolve on their own: when
positions cannot be read, cash still reads ok.

### Fields and units per venue

Amounts are exact decimal strings in USD (stablecoin) units, never floats.

| venue | `positions_value` | `pnl` |
| - | - | - |
| polymarket | Σ `currentValue` over every address read (the Data API's decimal) | `cash_pnl`: Σ `cashPnl` |
| limitless | Σ `marketValue` over the sides you hold; the venue sends 6-decimal integers (`"100000000"` is `100`), and `collateralToken.decimals` must read 6 or the venue reads unavailable bad\_response | `unrealized_pnl`: Σ `unrealizedPnl`, signed |
| predictfun | Σ `valueUsd` (decimal strings) over every page of your positions (100 a page, at most 40 pages, beyond that unavailable too\_many\_rows); share `amount`s are 18-decimal and are not summed | `pnl_usd`: Σ `pnlUsd` |
| kalshi | unsupported, reason not\_defined\_by\_venue, until we confirm `portfolio_value` excludes cash | unsupported, reason not\_reported\_by\_venue |

Polymarket cash is pUSD and USDC.e at every address read (see above). No realized P\&L is served: Polymarket
`realizedPnl` and Limitless `realisedPnl` are not read. Whether `cashPnl` equals `currentValue − initialValue`, and
whether Limitless `unrealizedPnl` equals `marketValue − cost`, is not yet confirmed against a live account. There is
no history.

`resolved_rows` (on predict.fun and Limitless `positions_value` and `pnl`) counts the rows summed that sit in a
resolved, paused or unpriced market, when there is at least one.

predict.fun pages spend the same per-user call budget as `GET /public/v1/account/positions?venue=predictfun`,
one call per page.

### The total

`total.amount` adds every venue's `cash` and `positions_value`, each stablecoin and USD at \$1
(`basis: stablecoins_at_par`). It is `null` unless every component it needs is whole, and then
`incomplete_because` lists each cause as `{venue, component, status, reason}`. `excluded` lists components
left out by rule. The rules, top to bottom, first match wins:

| # | component | effect |
| - | - | - |
| 1 | any `pnl` | never part of the total |
| 2 | predict.fun, while it runs on its testnet | excluded, reason testnet |
| 3 | unavailable, any reason | incomplete |
| 4 | unsupported venue\_disabled | excluded |
| 5 | unsupported not\_built or not\_defined\_by\_venue | incomplete |
| 6 | not\_connected no\_credential or no\_wallet | counts as 0 |
| 7 | not\_connected no\_profile, profile\_held\_elsewhere or empty\_answer\_unverified | incomplete |
| 8 | Polymarket cash ok without pUSD at every address | incomplete, reason pusd\_unread |
| 9 | Kalshi cash ok | incomplete, reason resting\_orders\_unverified: Kalshi reports available balance, and where cash held by resting orders sits is not yet confirmed |
| 10 | predict.fun `positions_value` ok with a row whose market is RESOLVED, PRICE\_PROPOSED, PRICE\_DISPUTED, REMOVED or PAUSED, or whose outcome carries a status | incomplete, reason resolved\_value\_unreported; else, with a row whose outcome has no best bid, reason no\_bid |
| 11 | Limitless `positions_value` ok with a row whose market is not open (open: `closed` false, `status` FUNDED, `winningOutcomeIndex` and `payoutNumerators` present and null) | incomplete, reason resolved\_value\_unverified |
| 12 | `cash` or `positions_value` ok | added |
| 13 | anything else | incomplete, reason unclassified |

So any Kalshi user with a credential, and any account holding a resolved or unpriced predict.fun row or a
not-open Limitless row, reads `total.amount: null` for now, with the cause named. A Limitless wallet with no
sub-account reads not\_connected no\_profile here, and its USDC is not counted.

The total covers only the wallets we read. Funds in a predict.fun smart account, and anything outside the
addresses listed in `held`, are outside every component and the total.

Compared with the website's header and portfolio page: cash matches the header per venue as described above;
the website adds Kalshi cash only, reads a failed venue as 0 and labels Kalshi realized P\&L as unrealized, so its
figures can differ from these.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.