Skip to main content

The Money shape

Every monetary amount on the public API uses one shape:
{ "code": "USD", "amount": "100.50" }
{ "code": "USDC", "chain": "ethereum", "amount": "100" }
FieldTypeNotes
codestringAsset code in SCREAMING_CASE (USD, EUR, USDC, USDT, ETH, BTC, SOL).
chainstring (optional)Blockchain network. Omitted for fiat assets. Never null.
amountstringDecimal string. See precision rules below.
The same shape is used in request bodies, response bodies, and webhook payloads. There is no second representation (no base units, no integer minor units, no separate assetAmount envelope).

Amount as a string

Amounts are always JSON strings, never numbers. JavaScript and most JSON parsers lose precision on values like 0.1 + 0.2; representing money as Number is unsafe for any asset with more than 15 significant digits (e.g. 1.000000000000000001 ETH cannot round-trip through a JS number). Strings sidestep this entirely. Use a decimal library (BigNumber.js, decimal.js, Python Decimal, Go shopspring/decimal) to do arithmetic.

Input precision

Requests accept up to the asset’s precision. Padding with trailing zeros is optional.
AssetPrecisionExamples accepted
USD, EUR2"100", "100.5", "100.50"
USDC, USDT6"1", "1.5", "1.500000"
BTC8"1", "0.00000001" (1 satoshi)
ETH18"1", "0.000000000000000001" (1 wei)
SOL9"1", "0.000000001" (1 lamport)
JPY (zero-precision)0"1500", "0" — integer string only
Inputs with more fractional digits than the asset allows are rejected at request validation:
{
  "type": "VALIDATION_ERROR",
  "title": "Validation failed",
  "status": 400,
  "errors": [
    {
      "pointer": "/amount",
      "detail": "amount must be a decimal string with up to 6 digits after \".\" for USDC"
    }
  ]
}
Other rejected forms (regardless of asset):
  • Leading sign ("+1", "-1")
  • Leading zero on the integer part ("01.00")
  • Scientific notation ("1e6")
  • Trailing dot with no fractional digits ("1.")

Output precision

Responses and webhook payloads always emit amounts at the asset’s exact precision (canonical exact-scale form). The amount you sent as "1" USD will come back as "1.00". The amount you sent as "1.5" USDC will come back as "1.500000". This means: echo what we send you, do not parse-and-rebuild. If you store the response amount in a database, store the string as-is; round-tripping through Number or a non-decimal type will silently corrupt the precision.

Idempotency and amount

Idempotency-Key fingerprints canonicalise the amount before hashing. A replay with amount: "1" against an original amount: "1.00" for USD will return the original response, not an IDEMPOTENCY_KEY_CONFLICT.

Why not base units

A common alternative is to send amounts as integer base units (e.g. 100000000 for 1 BTC). Conduit does not do this on the public surface for two reasons:
  1. Asymmetry. Fiat and crypto amounts would have to agree on a representation. Sending 100000000 for both 1 BTC and 1,000,000 USD is error-prone.
  2. No precision context at the call site. Integrators have to look up the asset’s decimal places to know whether 1000 is 0.001 ETH or 1000 USDC. Decimal strings carry the precision visually.
Conduit converts to base units exactly once, at the service boundary, when it needs to do exact-precision arithmetic against the ledger. Customers never see base units on the wire.