Balances that survive a stock split.
Every historical query applies the multiplier as of the block you asked for, and returns it alongside the answer. Ask for a position at a past block without as_of and you get a 400, not a quietly-current number.
- 3,960,000CASH_DIVIDEND $0.04/sh→ ×1.0042
- 4,310,000FORWARD_SPLIT 4:1→ ×4.0168
Same wallet, same block, two answers
What was this position worth at block 4,200,000? The balance never moved — Robinhood’s stock tokens keep raw ERC-20 amounts static and express corporate actions through uiMultiplier(). Apply today’s multiplier to a past balance and the answer is wrong by construction.
balanceOf(NVDA, 4,200,000)
× uiMultiplier() ← today's, not the block's
× price_at(block)$9,210.00
Uses the current multiplier of 4.000000. The balance is right; the scaling factor is from the wrong point in time.
balanceOf(NVDA, 4,200,000)
× uiMultiplier_at(4,200,000)
× price_at(block)$2,302.50
Uses the multiplier that was actually in force at that block: 1.000000.
Every response shows its work
Raw and adjusted, plus the multiplier that converts between them and the block it was valid at. A customer can always check our arithmetic.
Price return is the wrong metric
Dividends on Robinhood Chain are not paid out. They are reinvested by moving the multiplier, which means a stock token tracks the total return of its underlying, not the share price.
A provider that computes performance from price alone understates every dividend-paying instrument — and the error compounds. We report both, labelled, with the dividend contribution broken out.
Cost basis is carried through all 13 corporate-action types rather than reset at them, so a position held across a merger still has a defensible basis.
The correct path is the easy one
Our SDKs return UI-adjusted balances by default; the raw number takes an explicit call. A historical query without as_of does not compile.
import { RobinhoodRPC } from "@robinhoodrpc/sdk"; const client = new RobinhoodRPC({ apiKey: process.env.RHRPC_KEY! }); // Multiplier applied. This is the number for the UI.const balance = await client.balance(address, "AAPL"); // The raw ERC-20 amount requires asking for it.const raw = await client.balanceRaw(address, "AAPL"); // Historical without asOf is a compile error, so the classic// "current multiplier on a past balance" bug cannot ship.const then = await client.balance(address, "AAPL", { asOfBlock: 4_200_000,}); console.log(then.balanceUi, then.multiplierApplied);A correctness linter that runs against any codebase, including one using a competitor’s SDK. It flags raw balances multiplied by a price, historical queries missing as_of, cross-session comparisons, and Chainlink prices multiplied by uiMultiplier() — which double-applies and is wrong by the square of the multiplier.
npx @robinhoodrpc/lint ./srcGet numbers you can defend.
Point-in-time correct balances, total return, and cost basis that survives corporate actions. Included on every plan.