1. Call the API so a failure is a failure
Every answer that is not a2xx is the error envelope. The helper below returns the body on a 2xx and retries a 429, 503, or 408 after Retry-After, up to 4 tries. It raises on anything permanent, so a bad key or a lapsed subscription never turns into an empty table.
400,401,402,403,404, and423do not clear on a retry. A429witherror.reasonmonthly_quota_exceededclears on the first of next month, which is too far off to sleep through. All of them raise at once.- A
408onPOST /traders/batchcarries noRetry-After, because a mutation that timed out may have completed. This batch is a read, so repeating it is safe, and the loop’s own backoff covers it. - Step 4 is the only step that can produce a
404: a wallet value that resolves to nothing. Fix the value; waiting will not change the answer. requests.requestraises on a dropped connection. Let it: a run that cannot reach the API has nothing truthful to print.
2. Read profit and loss, 25 wallets per call
Batch traders reads 1 to 25 wallet addresses, usernames, ortrd_ ids in one call. The fields that matter are optional rather than nullable: when 0xinsider has no value, the key is left out of the JSON entirely, so read them with .get.
3. Sum only what is known, and say what is not
A missingpnl.total is not zero. It is a wallet whose profit and loss 0xinsider does not have, and adding 0 for it prints a total that is wrong by that wallet’s whole result. Keep three figures apart: the subtotal over the wallets that have a figure, the wallets that have none, and the wallets whose figure is old.
freshness.status of fresh only says that a sync timestamp exists. There is no age limit behind the word, so as_of is the number that matters and the 24-hour cutoff above is yours to choose.
A wallet with sync_status unknown
0xinsider does not track that wallet. Reading it does not start tracking it: a wallet joins the tracked set when 0xinsider sees it on a large trade, a large position, or the leaderboard, never because an API call asked for it.
Re-check it on your next scheduled run and keep it in the missing list until then. Polling it every few seconds spends your request budget and changes nothing.
4. Read the open positions
Positions with thewallet parameter reads one wallet, or up to 25 of them, in one call. You get every open position those wallets hold that 0xinsider has valued, largest current_value_usd first, paged with a cursor. Asking by wallet costs the page you read rather than a scan of the whole board, and min_size drops to 0 so nothing is left out by value.
An address 0xinsider has never tracked returns whatever rows it has, or an empty list. A username or
trd_ id that resolves to nothing returns 404 with error.param set to wallet, which means you should fix the value rather than retry it.
requests sends a list value as a repeated parameter, so the dictionary above becomes one wallet= per address on the wire. Print freshness beside each value: a stale position is a hint rather than a fact, and an absent cash_pnl prints as None, which is the truthful reading.
5. Set the refresh interval
Two budgets apply to this script, and both are per account rather than per key. Every key on the account draws on the same pool. See Rate limits.
One run costs
ceil(wallets / 25) batch requests, plus one positions request per 100 rows in each group of 25 wallets. A 100-wallet book holding 350 positions is 4 batch requests and 4 to 8 positions requests. If a book holds many small positions, raise min_size to cut the page count.
The positions route returns an ETag. Send it back as If-None-Match, and branch on a 304 before you parse: a 304 has no body.
Run on a timer, every 5 or 15 minutes, and let call sleep through a 429. Nothing here needs a tight loop, because profit and loss only moves when a new sync is written, and pnl_as_of tells you when that was.
To see the fills that built one position, read Position timeline.
What this does not do
- Place an order or move funds. No endpoint on this API does.
- Read a live balance. Profit and loss is the figure from the last sync, stamped by
trust.total_pnl.freshness.as_of. - Start tracking a wallet. A
sync_statusofunknownstaysunknownuntil 0xinsider meets the wallet in its own data, and no request you send changes that. - Show a closed position, or one 0xinsider has not valued yet. Asking by
walletreturns open, valued positions only, so a wallet with no rows is holding nothing 0xinsider has valued. - Show a position on a market with more than two outcomes. The route carries
YESandNOlegs only. - Print a book total when a wallet has no figure. Step 3 prints the covered subtotal and names the wallets left out of it.