API Reference
Data Types

Data Types & Conventions

Decimal strings

All prices, sizes, and spreads are returned as strings, never floats. This preserves decimal precision that would be lost in JSON number parsing.

{
  "target_size": "2.5",
  "target_spread": "0.01",
  "filled_size": "1.25"
}

Use a decimal library client-side, e.g.:

  • Python: decimal.Decimal
  • JavaScript: bignumber.js, big.js, or decimal.js
  • Go: shopspring/decimal

Do not parse decimal strings as float64 / Number. You'll lose precision on values like 0.1 + 0.2.

Timestamps

All timestamps are RFC 3339 in UTC:

"2026-03-12T13:06:58Z"

The Z suffix is always present (never an offset like +00:00 or -05:00). Time zones in your local UI are your problem; the API speaks UTC.

Wallet addresses

Ethereum-style hex, always lowercase, with 0x prefix:

"0xYourWalletAddressHere"

The API normalizes mixed-case input to lowercase on storage. Your queries should also use lowercase to avoid mismatches.

Exchange identifiers

Lowercase, exactly as listed:

IdentifierExchange
hyperliquidHyperliquid
extendedExtended (x10)
lighterLighter (zkLighter)
lighter_rhLighter [RH] (Lighter on Robinhood Chain)
orderlyOrderly Network
asterAster (asterdex)
grvtGRVT
apexApeX Omni
hl_xyztrade[xyz] (Hyperliquid builder DEX)
nadoNado (maker leg only)

The API only format-checks exchange names (alphanumeric/underscore) at submission time; an unrecognized exchange fails slightly later with a credential-lookup error ("no active credentials for wallet ... on ..."), not a dedicated validation error.

Market symbols

The market field in trade creation uses canonical symbols (e.g. BTC, ETH, HYPE, SOL). Spreadr translates these into the venue-specific symbols at execution time.

Get the full list of available canonical symbols + per-exchange mappings from Available Markets.

UUIDs

trade_id is a v4 UUID, 36 characters including hyphens:

"00000000-0000-0000-0000-000000000000"

User-supplied idempotency keys must match ^[a-zA-Z0-9_-]{1,128}$ — alphanumeric, hyphen, underscore only (a UUID works).

Enum values

All enums are lowercase strings:

  • spread_condition — gte, gt, lte, lt, eq
  • maker_leg — long, short
  • size_type — base, notional
  • spread_type — absolute (raw USD price difference), percentage (% of hedge reference price), bps (basis points of hedge reference price), ticks (multiples of the coarser leg's tick size)
  • execution_type — currently only maker_taker
  • Trade status — pending, validating, active, paused, recovering, completed, canceled, rejected, failed

Failure codes

Terminal trades (completed, canceled, failed, rejected) carry failure_code and failure_detail next to the free-text failure_reason. The code is derived at read time from status + failure_reason, so trades that closed before it existed carry one too. Match on the code, not on the text.

failure_codeStatusMeaning
completedcompletedTarget size fully filled
canceled_cleancanceledNo fill was open at cancel time
canceled_with_fills_hedgedcanceledFills existed and a hedge-venue corrective left the legs balanced (the residual was hedged, or an over-hedge was reduced)
canceled_with_fills_completedcanceledFills existed; the maker leg was completed at market to match a pre-hedge
canceled_with_fills_flattenedcanceledFills existed; the residual was closed reduce-only on the maker venue
canceled_exposure_remainscanceledA corrective failed, or on_cancel_fill: "report" left the residual in place. Read net_exposure and failure_detail; the position needs attention
canceled_kill_switchcanceledHalted by the user or global kill switch (also killed_by_switch: true)
canceled_othercanceledCanceled with a reason not enumerated above
hedge_rejectedfailedThe hedge venue refused the hedge deterministically (no retry can succeed). The residual was flattened where possible — check net_exposure
hedge_failed_flattenedfailedThe hedge failed after all retries and the residual was flattened
hedge_failed_exposure_remainsfailedThe hedge failed after all retries and the flatten failed too
hedge_abandonedfailedThe hedge budget was exhausted and the residual abandoned
recovery_exhaustedfailedThe worker was repeatedly terminated during recovery
liquidationfailedA leg was liquidated
maintenancerejectedSystem or venue maintenance
market_not_tradeablerejectedMarket unknown or not tradeable on a venue
no_leveragerejectedNo user leverage available on a venue
below_min_sizerejectedTarget size or notional below the venue minimum
negative_available_balancefailedRefused before anything rested: a leg closes a position on a venue whose available balance is negative, and such closes are refused. Not on Hyperliquid or GRVT, which admit closes at any balance; and not for the hedge leg of a reduce_only trade on Extended, whose reduce-only orders Extended admits at any balance. Add collateral or raise leverage on that venue, or send the close as reduce_only with the Extended leg as the hedge, then retry
insufficient_marginfailedRefused before anything rested: a venue's available balance is below what the leg needs
reduce_only_would_openfailedA reduce_only leg holds no opposing position, or a smaller one than the size — it would open exposure, so the trade was refused before anything rested
reduce_only_unverifiedfailedA reduce_only trade whose positions could not be read to verify the close (after retries). Transient — retry
hl_address_budget_exhaustedfailedHyperliquid refused the wallet's address, not the order: its cumulative request budget (10,000 + 1 per USDC traded) is used up, and until volume raises it HL admits one request per 10 s. The trade fails on the first such rejection of a placement instead of retrying; failure_detail carries the requests used and the cap. A refused re-price does not fail the trade: the maker holds its resting order until the address has headroom again (an hl_address_budget_hold event). A hedge rejected this way also fails on the first rejection, reported as hedge_rejected with Hyperliquid's message in failure_detail
hl_action_budget_exhaustedfailedAn entry spent its own per-trade Hyperliquid action cap (hl_action_budget; by default the trade's USD notional, at least 100). Its maker would have re-priced again, so the order was cancelled and the trade ended with what had filled, hedged; a no-fill when nothing had filled. failure_detail carries the actions used and the cap. A reduce_only close that runs out is finished at market instead and completes. See Hyperliquid action cap
credential_invalidfailedThe venue says the trading key Spreadr holds for it is expired, deleted or replaced (a Hyperliquid or Orderly key past its expiry, a revoked or overwritten API key). Refused before anything rested, or a placement the venue refused for the key; no retry can succeed. failure_detail names the venue and what to reconnect (Settings → Wallets)
failed_other / rejected_otherfailed / rejectedTerminal with a reason not enumerated above

Codes are additive: a new code may appear in /api/v1 without a version bump, so treat an unknown value as "terminal, inspect failure_detail".

Pagination

The current API does not paginate. List endpoints return the most recent 50 items unconditionally. If/when pagination is added, it'll use cursor-based parameters (since, limit) — not page numbers.

Versioning

Everything is under /api/v1. Breaking changes will go under /api/v2; non-breaking additions (new optional fields, new endpoints) will land in /api/v1 without a version bump.