Skip to main content
Spot trading on Murmo works in two modes: standalone swaps (a private, one-off trade in your own wallet) and group spot proposals (a shared token idea inside a group that other members can follow and act on). Both are signed server-side via your delegated wallet — you never handle a private key, and slippage and the wallet ID are always resolved for you. Everything lives under /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.
Set up your environment before starting:
export MURMO_API_KEY="murmo_your_key_here"
export MURMO_BASE="https://api.alpha-labs.trade"

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).
curl "$MURMO_BASE/api/v1/spot/tokens/search?q=bonk&limit=5" \
  -H "Authorization: Bearer $MURMO_API_KEY"
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.
Use search for discovery only. Once you have a candidate mint, fetch its canonical price and decimals with the by-mint endpoint below before you trade.

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.
curl "$MURMO_BASE/api/v1/spot/tokens/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" \
  -H "Authorization: Bearer $MURMO_API_KEY"
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.
sell
string
required
Mint address of the token to sell, or "USDC".
buy
string
required
Mint address of the token to buy, or "USDC".
amountUsd
string
required
Input amount as a decimal string in USD, e.g. "25.00". Sizes the sell side.
amountUsd sizes the input and is interpreted as USDC base units, so swaps are practically sized by spending USDC (sell: "USDC"). To exit a token back to cash, prefer a proposal sell (below), which is sized by your desired USDC output.
curl -X POST "$MURMO_BASE/api/v1/spot/swap" \
  -H "Authorization: Bearer $MURMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sell": "USDC", "buy": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", "amountUsd": "25.00" }'
On success, data is a SwapResult:
Success response
{
  "data": {
    "success": true,
    "signature": "4nP...solana_sig",
    "inputAmountRaw": "25000000",
    "outputAmountRaw": "138000000000",
    "alphaFeeUsd": "0.05"
  }
}
On failure, the request still returns 200 with success: false — no signature, no output amount:
Failure response
{
  "data": {
    "success": false,
    "inputAmountRaw": "25000000",
    "error": "No route found for this pair",
    "errorCode": "DFLOW_ROUTE_NOT_FOUND"
  }
}
FieldMeaning
successWhether the swap landed. Always check this before reading anything else.
signatureSolana transaction signature (success only).
inputAmountRawBase units of the sell token actually spent. Humanize with the sell token’s decimals.
outputAmountRawBase units of the buy token received (success only). Humanize with the buy token’s decimals.
alphaFeeUsdAlpha fee for the trade as a USD decimal string.
error / errorCodePresent on failure. errorCode is a stable code you can branch on (often DFLOW_*).
inputAmountRaw and outputAmountRaw are token base units, not USD. To get a human quantity, divide by 10 ** decimals (from GET /api/v1/spot/tokens/{mint}) using a decimal type: Decimal("138000000000") / (Decimal(10) ** 5)1380000. Money fields like alphaFeeUsd are already human decimal strings.

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.
Every proposal endpoint is members-only. Reading or trading a proposal in a group you don’t belong to returns 403 with code: NOT_GROUP_MEMBER. Creating a proposal additionally requires a leader or admin role. See Errors.

The proposal lifecycle

1

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.
groupId
string
required
The group to open the proposal in.
contractAddress
string
required
The token’s Solana mint address.
amountUsd
string
required
The opening buy size in USDC as a decimal string, e.g. "50.00".
reason
string
Your thesis, shown to the group (optional).
curl -X POST "$MURMO_BASE/api/v1/spot/proposals" \
  -H "Authorization: Bearer $MURMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "groupId": "1a9d212a-de67-45f4-88f5-6e9f41e78dc0",
    "contractAddress": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
    "reason": "Momentum breakout",
    "amountUsd": "50.00"
  }'
Returns { data: { proposal, trade } } — a SpotProposal and the opening SpotTrade. Keep proposal.id for all subsequent calls.
Response
{
  "data": {
    "proposal": {
      "id": "prop_abc123",
      "groupId": "1a9d212a-...",
      "reason": "Momentum breakout",
      "...": "..."
    },
    "trade": {
      "tradeType": "BUY",
      "tokenAmount": "1380000",
      "tokenDecimals": 5,
      "pricePerTokenUsd": "0.0000362",
      "totalCostUsd": "50",
      "alphaFeeUsd": "0.10",
      "pnlUsd": null
    }
  }
}
2

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).
# Buy a fixed $20
curl -X POST "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID/buy" \
  -H "Authorization: Bearer $MURMO_API_KEY" -H "Content-Type: application/json" \
  -d '{ "amountUsd": "20.00" }'

# Go all-in on available USDC
curl -X POST "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID/buy" \
  -H "Authorization: Bearer $MURMO_API_KEY" -H "Content-Type: application/json" \
  -d '{ "max": true }'
Returns { data: { trade } } with a SpotTrade.
3

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.
# Take $10 of USDC back out
curl -X POST "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID/sell" \
  -H "Authorization: Bearer $MURMO_API_KEY" -H "Content-Type: application/json" \
  -d '{ "amountUsd": "10.00" }'

# Exit the whole position
curl -X POST "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID/sell" \
  -H "Authorization: Bearer $MURMO_API_KEY" -H "Content-Type: application/json" \
  -d '{ "max": true }'
Returns { data: { trade } } with a SpotTrade.
Buy amountUsd is USDC spent; sell amountUsd is USDC received. Use max: true on either side to skip sizing math — full balance on a buy, full position on a sell.
4

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.
curl -X POST "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID/close" \
  -H "Authorization: Bearer $MURMO_API_KEY"
Returns { 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.
curl "$MURMO_BASE/api/v1/spot/proposals?groupId=1a9d212a-de67-45f4-88f5-6e9f41e78dc0" \
  -H "Authorization: Bearer $MURMO_API_KEY"
data is an array of SpotProposalWithPosition:
FieldMeaning
proposalThe SpotProposal (token, creator, prices, lifecycle).
userPositionYour SpotPositionSummary on this proposal.
participantCountHow many members hold a position (nullable).
participantAvatarsAvatar 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.
curl "$MURMO_BASE/api/v1/spot/proposals/PROPOSAL_ID" \
  -H "Authorization: Bearer $MURMO_API_KEY"

Field reference

SpotProposal

FieldTypeMeaning
idstringProposal ID (use in /buy, /sell, /close).
groupIdstringThe group this proposal belongs to.
createdByUserDynamicIdstringThe creator’s user ID.
tokenMetadataIdstringInternal token metadata ID.
reasonstring | nullThe thesis the creator gave when opening.
initialPriceUsdMoneyString | nullToken price (USD) when the proposal opened.
exitPriceUsdMoneyString | nullToken price (USD) when the proposal closed.
exitPnlPctDecimalString | nullRealized PnL percent at close (e.g. "12.3" = 12.3%).
exitPnlUsdMoneyString | nullRealized PnL in USD at close.
closedAtdate-time | nullWhen it was closed (null while open).
createdAt / updatedAtdate-timeTimestamps.
tokenTokenRef | null{ contractAddress, symbol, name, logoUrl, verified, ... }.
groupGroupRef | null{ uniqueId, name, image }.
createdByUserRef | null{ dynamicId, username }.
tradesSpotTrade[] | nullDetail endpoint only — your trades on this proposal.

SpotPositionSummary (userPosition)

FieldTypeMeaning
hasPositionbooleanWhether you currently hold this proposal.
currentTokenAmountRawstring | nullYour token holding in base units — humanize with the token’s decimals.
totalCostUsdMoneyString | nullWhat you’ve spent into the position in USD.
avgEntryPriceUsd / avgExitPriceUsdMoneyString | nullAverage entry / exit price (USD).
unrealizedPnlUsd / unrealizedPnlPctMoneyString / DecimalString | nullOpen PnL in USD and percent.
realizedPnlUsd / realizedPnlPctMoneyString / DecimalString | nullClosed PnL in USD and percent.
currentValueUsdMoneyString | nullCurrent mark value of your holding (USD).
currentPriceUsdMoneyString | nullCurrent token price (USD).
userExitedAtdate-time | nullWhen 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.
FieldTypeMeaning
idstringTrade ID.
tradingProposalIdstringThe proposal this trade belongs to.
groupIdstringThe group.
walletAddressstringThe wallet that executed the trade.
tradeType"BUY" | "SELL"Direction.
tokenAmountDecimalStringToken quantity, already humanized with tokenDecimals.
tokenDecimalsintegerThe token’s decimals.
pricePerTokenUsdMoneyString | nullExecution price per token (USD).
totalCostUsdMoneyStringUSD value of the trade.
alphaFeeUsdMoneyStringAlpha fee for this trade (USD).
pnlUsdMoneyString | nullRealized PnL on a sell (USD); null on buys.
pnlPctDecimalString | nullRealized PnL percent on a sell; null on buys.
txSignaturestring | nullSolana transaction signature.
createdAtdate-timeWhen 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 / codeWhenWhat to do
400Missing/invalid body or groupId, or an unroutable trade.Fix the request; read message/code.
401Missing or invalid key.Check the Authorization: Bearer murmo_... header.
403 NOT_GROUP_MEMBERReading 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.