Skip to main content
The single most important convention in the Murmo API is how money is serialized. Get this right and an entire class of precision bugs disappears before your code ships.

The rule

Every monetary value — in both requests and responses — is a full-precision plain decimal string in USD. That means:
  • A string, e.g. "12.50" — never a bare JSON number
  • In human USD, e.g. "5" means five dollars — never raw base units like "5000000"
  • Plain decimal — never scientific notation like "5e-7"
  • Full precision — never pre-rounded; round only when you display to users
{
  "totalCostUsd": "5",
  "alphaFeeUsd": "0.05",
  "unrealizedPnlUsd": "-1.2345678"
}

Why strings instead of numbers

JSON numbers are IEEE-754 double-precision floats. The classic 0.1 + 0.2 = 0.30000000000000004 problem is real, and integers silently lose precision beyond 2^53. For money, that is unacceptable. A decimal string carries the exact value with zero rounding, and you parse it with a decimal library on your side. $5 serializes as "5" — not 5000000 (its raw base units) and not 5.0 (a float).
Token quantities that are genuinely in base units are the one exception, and they are always named with a Raw suffix — for example currentTokenAmountRaw or inputAmountRaw. Every field named ...Usd, or that represents a price, PnL, or percentage, is a human decimal string.

Correct vs. incorrect formats

When you send money in a request body, always use a decimal string. Never multiply by 1e6 and never send a plain number.
{ "amountUsd": "12.50" }
The API rejects incorrect formats with a clean 400 INVALID_AMOUNT rather than silently mis-scaling your trade.

Parsing money safely

Use a decimal type — not a float — whenever you do arithmetic on money values.
// For display only, Number() is fine:
const usd = Number(data.totalCostUsd); // 12.5

// For any arithmetic, use a decimal library (decimal.js, big.js):
import Decimal from "decimal.js";

const cost = new Decimal(data.totalCostUsd);
const fee  = new Decimal(data.alphaFeeUsd);
const net  = cost.plus(fee).toFixed(2); // "12.55"

Raw vs. human quantities

Two distinct kinds of numeric values appear in the API. The field name suffix tells you exactly which you are dealing with.
Field styleMeaningExample valueHow to use
...Usd, prices, PnL, percentHuman decimal string in USD"12.50", "-3.7"Parse with a decimal library.
...Raw, ...BaseUnits, ...BaseLotsInteger base-unit quantity string"25000000"Humanize using the token’s decimals.
tokenDecimals, decimals, counts, indicesStructural integer6, 9Plain JSON number — use as-is.
To convert a raw token quantity to a human amount, divide by 10 ** decimals using a decimal type:
from decimal import Decimal

raw      = Decimal("1380000000000")   # outputAmountRaw from a swap
decimals = 9                          # from GET /spot/tokens/{mint}
human    = raw / (Decimal(10) ** decimals)  # Decimal('1380')

Percentages

Percentage fields — pnlPct, exitPnlPct, winRate, priceChange24hPct, and others — follow the same decimal string rule. The value is expressed as a percent directly: "4.27" means 4.27% and "-12.5" means −12.5%. Do not divide by 100 before displaying.

Worked example

A $5 spot buy returns a response like the one below. Note that totalCostUsd is the human string "5", not 5000000.
{
  "data": {
    "trade": {
      "tradeType": "BUY",
      "tokenAmount": "1380.5",
      "tokenDecimals": 9,
      "pricePerTokenUsd": "0.00362",
      "totalCostUsd": "5",
      "alphaFeeUsd": "0.01",
      "pnlUsd": null
    }
  }
}
  • totalCostUsd: "5" → five dollars.
  • tokenAmount: "1380.5" → already humanized for trade rows (uses tokenDecimals).
  • pricePerTokenUsd: "0.00362" → a small price, still plain decimal — never "3.62e-3".
If you ever see a bare number where you expected a string, a value off by a factor of ~1,000,000, or scientific notation in a money field, that is a bug — please report it with the X-Request-Id header value. The API is designed so these never reach the wire.