/api/v1/spot, and tokens are addressed by their Solana mint address or the literal string "USDC".
Every monetary value in requests and responses is a full-precision plain decimal string in USD
(
"12.50", not 12.5, not 12500000, never "1.25e1"). Token quantities in base units are the
one exception and are always named with a ...Raw suffix. See
Money & precision.Find a token
GET /api/v1/spot/tokens/search is a Jupiter-backed search over Solana tokens. Pass q (a symbol, name, or mint) and an optional limit (default 20).
data is an array of token objects with pass-through shape from Jupiter/CoinGecko. Price and volume floats are rendered as decimal strings, never JS numbers.
Get price and metadata (including decimals)
GET /api/v1/spot/tokens/{mint} returns price and metadata for one token by its mint address. This is how you retrieve a token’s decimals — the value you need to humanize any ...Raw quantity returned elsewhere in the API.
data is a single token object with pass-through shape. Price fields are decimal strings; decimals is a plain integer you reuse to convert base units to human amounts.
Standalone swap
POST /api/v1/spot/swap executes a one-off, non-group swap in your own wallet, signed server-side. Provide the mint to sell, the mint to buy, and the input amount in USD.
Mint address of the token to sell, or
"USDC".Mint address of the token to buy, or
"USDC".Input amount as a decimal string in USD, e.g.
"25.00". Sizes the sell side.data is a SwapResult:
Success response
200 with success: false — no signature, no output amount:
Failure response
| Field | Meaning |
|---|---|
success | Whether the swap landed. Always check this before reading anything else. |
signature | Solana transaction signature (success only). |
inputAmountRaw | Base units of the sell token actually spent. Humanize with the sell token’s decimals. |
outputAmountRaw | Base units of the buy token received (success only). Humanize with the buy token’s decimals. |
alphaFeeUsd | Alpha fee for the trade as a USD decimal string. |
error / errorCode | Present on failure. errorCode is a stable code you can branch on (often DFLOW_*). |
Group spot proposals
A spot proposal is a token idea inside a group: a leader opens it with a buy, and other members can buy in, sell out, and track progress together. Each member manages their own position; the proposal creator can close the whole idea when they’re done. See Groups & proposals for the social model.The proposal lifecycle
Create with an opening buy
POST /api/v1/spot/proposals creates the proposal and places the creator’s opening buy in a
single call. Leader or admin role is required.The group to open the proposal in.
The token’s Solana mint address.
The opening buy size in USDC as a decimal string, e.g.
"50.00".Your thesis, shown to the group (optional).
{ data: { proposal, trade } } — a SpotProposal and the opening SpotTrade. Keep
proposal.id for all subsequent calls.Response
Buy in
POST /api/v1/spot/proposals/{id}/buy adds to your position. Send amountUsd (USDC to spend),
or max: true to spend your full USDC balance (then amountUsd is ignored).{ data: { trade } } with a SpotTrade.Sell out
POST /api/v1/spot/proposals/{id}/sell trims or exits your position. Here amountUsd is your
desired USDC output (how much cash you want back), or max: true to sell the full token
position.{ data: { trade } } with a SpotTrade.Close (creator only)
POST /api/v1/spot/proposals/{id}/close is for the proposal’s creator. It sells the creator’s
full position and moves the proposal into a closed state.{ data: { proposal, trade } } — the now-closed SpotProposal (with closedAt,
exitPriceUsd, exitPnlUsd, exitPnlPct) and the closing SpotTrade. Other members keep
their own positions and exit them with /sell.List a group’s proposals
GET /api/v1/spot/proposals?groupId=... returns every spot proposal in a group, each paired with your position on it. groupId is required.
data is an array of SpotProposalWithPosition:
| Field | Meaning |
|---|---|
proposal | The SpotProposal (token, creator, prices, lifecycle). |
userPosition | Your SpotPositionSummary on this proposal. |
participantCount | How many members hold a position (nullable). |
participantAvatars | Avatar URLs for participants (nullable). |
Proposal detail
GET /api/v1/spot/proposals/{id} returns the same SpotProposalWithPosition shape and additionally populates proposal.trades — your own trades on this proposal. If the proposal doesn’t exist, data is null.
Field reference
SpotProposal
| Field | Type | Meaning |
|---|---|---|
id | string | Proposal ID (use in /buy, /sell, /close). |
groupId | string | The group this proposal belongs to. |
createdByUserDynamicId | string | The creator’s user ID. |
tokenMetadataId | string | Internal token metadata ID. |
reason | string | null | The thesis the creator gave when opening. |
initialPriceUsd | MoneyString | null | Token price (USD) when the proposal opened. |
exitPriceUsd | MoneyString | null | Token price (USD) when the proposal closed. |
exitPnlPct | DecimalString | null | Realized PnL percent at close (e.g. "12.3" = 12.3%). |
exitPnlUsd | MoneyString | null | Realized PnL in USD at close. |
closedAt | date-time | null | When it was closed (null while open). |
createdAt / updatedAt | date-time | Timestamps. |
token | TokenRef | null | { contractAddress, symbol, name, logoUrl, verified, ... }. |
group | GroupRef | null | { uniqueId, name, image }. |
createdBy | UserRef | null | { dynamicId, username }. |
trades | SpotTrade[] | null | Detail endpoint only — your trades on this proposal. |
SpotPositionSummary (userPosition)
| Field | Type | Meaning |
|---|---|---|
hasPosition | boolean | Whether you currently hold this proposal. |
currentTokenAmountRaw | string | null | Your token holding in base units — humanize with the token’s decimals. |
totalCostUsd | MoneyString | null | What you’ve spent into the position in USD. |
avgEntryPriceUsd / avgExitPriceUsd | MoneyString | null | Average entry / exit price (USD). |
unrealizedPnlUsd / unrealizedPnlPct | MoneyString / DecimalString | null | Open PnL in USD and percent. |
realizedPnlUsd / realizedPnlPct | MoneyString / DecimalString | null | Closed PnL in USD and percent. |
currentValueUsd | MoneyString | null | Current mark value of your holding (USD). |
currentPriceUsd | MoneyString | null | Current token price (USD). |
userExitedAt | date-time | null | When you fully exited (null if still in). |
currentTokenAmountRaw is the only quantity here in base units (note the ...Raw suffix). Every
other field is a human USD or percent string. To get a human token count, divide by
10 ** decimals.SpotTrade (buy / sell / close)
Every executed trade — opening buy on create, each /buy and /sell, and the closing trade — returns a SpotTrade. Unlike position quantities, tokenAmount here is already humanized using tokenDecimals, so you don’t divide it yourself.
| Field | Type | Meaning |
|---|---|---|
id | string | Trade ID. |
tradingProposalId | string | The proposal this trade belongs to. |
groupId | string | The group. |
walletAddress | string | The wallet that executed the trade. |
tradeType | "BUY" | "SELL" | Direction. |
tokenAmount | DecimalString | Token quantity, already humanized with tokenDecimals. |
tokenDecimals | integer | The token’s decimals. |
pricePerTokenUsd | MoneyString | null | Execution price per token (USD). |
totalCostUsd | MoneyString | USD value of the trade. |
alphaFeeUsd | MoneyString | Alpha fee for this trade (USD). |
pnlUsd | MoneyString | null | Realized PnL on a sell (USD); null on buys. |
pnlPct | DecimalString | null | Realized PnL percent on a sell; null on buys. |
txSignature | string | null | Solana transaction signature. |
createdAt | date-time | When it executed. |
Two quantity conventions live side by side: a trade’s
tokenAmount is already humanized
(uses tokenDecimals), while a position’s currentTokenAmountRaw and a swap’s
inputAmountRaw/outputAmountRaw are raw base units you must humanize with decimals. The
...Raw suffix is your signal.Errors you’ll hit
| Status / code | When | What to do |
|---|---|---|
400 | Missing/invalid body or groupId, or an unroutable trade. | Fix the request; read message/code. |
401 | Missing or invalid key. | Check the Authorization: Bearer murmo_... header. |
403 NOT_GROUP_MEMBER | Reading or trading a proposal in a group you’re not in (or not leader/admin on create). | Don’t retry as-is. |
DFLOW_* | A swap route was rejected by the DFlow router. | Often transient — retry or adjust size. |
Swap failures come back as
200 with success: false (not an HTTP error). Proposal detail
returns data: null for an unknown ID. See Errors for the full reference.Where to next
Money & precision
Decimal strings and humanizing
...Raw quantities.Groups & proposals
The social model: groups, proposals, positions, and copy-trading.
Errors
Error shapes, status codes, and the codes worth handling.
API Reference
Every Spot endpoint, parameter, and response schema.