/me), the money side of the wallet (/account/*), and a single cross-vertical roll-up of positions and trades across every group (/positions, /trades).
Everything here is a read. The only “write” in the funding story is depositing USDC to an address you read from GET /account — and there is no withdrawal endpoint at all (see below).
Every monetary value on the wire is a full-precision plain decimal string in USD (
"12.50",
never a number, never raw base units, never scientific notation). Parse with a decimal library;
round only for display. See Money & precision.Environment
Authorization: Bearer $MURMO_API_KEY. The examples below use curl,
fetch, and requests; swap in your HTTP client of choice.
Identity — GET /me
The bootstrap call. It echoes the user behind the credential, which key you’re using (metadata
only — never the secret), and your rate budget. Nothing financial lives here; for balances and
the deposit address use GET /account.
Response
apiKey and rateLimit are null and authMethod is "jwt". The
Me fields:
Account summary and the deposit address
GET /account is the one call that gives you both your wallet’s headline value and the address
to fund it.
Response
AccountSummary fields:
Balances — GET /account/balances
Cash and token balances held in the main wallet. Each row is a WalletBalance; the response wraps
them in a named balances array.
Response
WalletBalance fields:
Spot holdings — GET /account/positions
Token holdings (spot positions) in the main wallet — the same WalletBalance shape as /balances,
plus a nextCursor for pagination when there are more pages.
Response
nextCursor is null when there are no more pages. When it is a string, pass it back to fetch the
next page (it is null in the common single-page case).
Portfolio value and 24h change — GET /account/portfolio
Aggregate portfolio value plus 24-hour change, with the underlying positions inline.
Response
Portfolio fields:
PnL — GET /account/pnl
Just the 24h change numbers, when you don’t need the full portfolio body.
Response
Fund and check your account
1
Read the deposit address
GET /api/v1/account and read data.deposit.walletAddress (plus tokenMint to confirm you’re
sending the right token — USDC).2
Send USDC on Solana
Transfer USDC to that address on Solana. This is an on-chain transfer you make from your own
wallet/exchange — it is not an API call. There is no API path that pulls funds for you.
3
Poll the balance until it lands
Re-
GET /api/v1/account (or /account/balances) until cashBalanceUsd reflects the deposit.
Settlement follows Solana confirmation, so allow a few seconds.4
Deploy it
Once funded, the same key can open group proposals, predict, or open perps. To move money
out, use the app — there is no withdrawal endpoint.
Cross-vertical positions and trades
Three endpoints under/api/v1 give you everything you hold and everything you’ve traded across
all groups in one call, without iterating group by group. Spot, prediction, and perp positions
each have their own per-vertical endpoints elsewhere; these are the aggregated views.
Open positions — GET /positions
Open positions across perps + spot + predictions, in every group.
Response
perps[]→PerpPosition(theidis theassignmentId; reduce/claim it via the perps endpoints). Persisted/realized USD fields and live mark/PnL/price fields are all decimal strings; base-lot quantities (currentSizeBaseLots) are quantity strings.spot[]→SpotProposalWithPosition({ proposal, userPosition, participantCount, participantAvatars }). NoteuserPosition.currentTokenAmountRawis a base-unit quantity (humanize with the token’sdecimals).predictions[]→PredictionWithPosition({ proposal, market, userPosition, remainingTokenAmount, createdBy }).marketis venue-native, normalized (marketTicker= market slug,eventTicker= event slug, prices already human dollar strings);tokenAmount/remainingTokenAmountare already humanized.
Past positions — GET /positions/past
Identical { perps, spot, predictions } shape, but for closed/resolved positions across all three
verticals.
Trade history — GET /trades
Executed trade history for spot + predictions. (Perp fills are not here — surface those via
GET /api/v1/perps/positions.)
Response
limit is optional (default 50, max 200; out-of-range values are clamped). Both arrays use
the same money convention: tokenAmount is an already-humanized decimal-string quantity (interpret
alongside tokenDecimals), and every ...Usd / pnl* field is a USD/percent decimal string
(pnl* is null on opening buys). On prediction trades, totalCostUsd is the gross fill value
(tokenAmount × pricePerTokenUsd), venueFeeUsd is the venue fee charged on the fill, and
pnlPct/pnlUsd are net of venue fees.
data envelope cheat-sheet
The thing to internalize: every response is wrapped in a top-level { "data": ... }, but the
shape inside data varies. Here is every endpoint on this page:
Errors
All four standard error statuses apply.401 means a missing/invalid Authorization header or key;
404 on GET /account means the wallet couldn’t be resolved for the credential. Error bodies come
in two shapes — coded business errors { message, code } and generic framework errors
{ statusCode, message, error }. See Errors.
Where to next
Money & precision
Why every value is a decimal string, and how to parse it.
Authentication
The Bearer header, what a key can (and can’t) do, and rate limits.
Groups & proposals
Why positions live as proposals inside groups — the model behind the
spot/predictions arrays.API Reference
Full schemas for
Me, AccountSummary, WalletBalance, Portfolio, and CrossVerticalPositions.