Sequence/docs

Data Formats & Units

Before building on the Sequence API, you need to understand how quantities, prices, and timestamps are encoded. Getting this wrong is the most common source of bugs - a misplaced scale factor makes your orders 10x or 1000x wrong.


Why fixed-point?

Floating-point arithmetic introduces rounding errors. If you represent 0.1 BTC as a float64, you get 0.10000000000000001 - close, but not exact. When you're aggregating fills across venues or calculating P&L, those errors compound. Every financial system that cares about precision uses integers instead.

Sequence encodes all order-related values as integers with a known scale factor. The field name tells you the scale:

SuffixScale factorWhat it measures
_1e8× 10⁸ (100,000,000)Quantities (how much of something)
_1e9× 10⁹ (1,000,000,000)Prices (how much it costs)
_bpsbasis points (1/100 of 1%)Fees, spreads, slippage
_nsnanoseconds since Unix epochTimestamps

If a field doesn't have a suffix (like bid_price on the BBO endpoint), it's a human-readable float provided for convenience. These float fields should not be used for order submission or P&L calculation.


Quantities (_1e8)

Quantities are scaled by 10⁸. This gives 8 decimal places of precision - enough to represent 1 satoshi (0.00000001 BTC).

You want to tradeqty_1e8 valueConversion
1 BTC100_000_0001.0 × 10⁸
0.5 BTC50_000_0000.5 × 10⁸
0.01 BTC1_000_0000.01 × 10⁸
0.001 BTC100_0000.001 × 10⁸
1 satoshi10.00000001 × 10⁸

To convert:

python
# Human-readable to API
api_qty = int(human_qty * 100_000_000)  # 0.5 BTC → 50_000_000
 
# API to human-readable
human_qty = api_qty / 100_000_000  # 50_000_000 → 0.5 BTC
javascript
// Human-readable to API
const apiQty = Math.floor(humanQty * 1e8);  // 0.5 BTC → 50000000
 
// API to human-readable
const humanQty = apiQty / 1e8;  // 50000000 → 0.5

Prices (_1e9)

Prices are scaled by 10⁹. The extra decimal place (compared to quantities) accommodates sub-cent price levels common in crypto markets.

Priceprice_1e9 valueConversion
$100,000.00100_000_000_000_000100,000.00 × 10⁹
$50,000.5050_000_500_000_00050,000.50 × 10⁹
$1.001_000_000_0001.00 × 10⁹
$0.0011_000_0000.001 × 10⁹

To convert:

python
# Human-readable to API
api_price = int(human_price * 1_000_000_000)  # $50,000.50 → 50_000_500_000_000
 
# API to human-readable
human_price = api_price / 1_000_000_000  # 50_000_500_000_000 → $50,000.50
Common mistake

A qty_1e8 value of 50_000_000_000_000 is not 0.5 BTC - that's 500,000 BTC. If your numbers look suspiciously large or small, check whether you're dividing by 10⁸ (quantities) or 10⁹ (prices). The suffixes are different for a reason.


Fees and spreads (_bps)

Fees, spreads, and slippage are expressed in basis points. One basis point is 0.01%, or 1/10,000 of the notional value.

Human-readable_bps value
0.10% (10 bps)10
0.26% (26 bps)26
1.00% (100 bps)100

To convert basis points to a decimal multiplier: bps / 10_000. So 26 bps = 0.0026, meaning a $10,000 trade costs $26 in fees.


Timestamps (_ns)

All timestamps are nanoseconds since the Unix epoch (January 1, 1970 UTC). This provides nanosecond precision for measuring latency and ordering events.

python
# Python: nanoseconds to datetime
from datetime import datetime, timezone
dt = datetime.fromtimestamp(timestamp_ns / 1_000_000_000, tz=timezone.utc)
javascript
// JavaScript: nanoseconds to Date
const date = new Date(Number(timestampNs / 1_000_000n));
// or if it's a number (not BigInt):
const date = new Date(timestampNs / 1_000_000);

Many market data messages carry a triple timestamp chain: exch_ts_ns (when the exchange generated the event), edge_ts_ns (when our edge server received it), and cc_ts_ns (when the central coordinator processed it). This lets you measure propagation delay at each hop.


Symbols

All trading pairs use BASE-QUOTE format, hyphen-delimited, case-sensitive:

code
BTC-USD      Bitcoin priced in US Dollars
ETH-USDT     Ethereum priced in Tether
SOL-USDC     Solana priced in USD Coin

Routing is exact-match

Orders route only to venues that list the exact symbol you requested. There is no automatic conversion between quote currencies:

SymbolRoutes to
BTC-USDKraken, Coinbase
BTC-USDTBinance, Bitget, Crypto.com, BitMart, OKX, Bybit
BTC-USDCBitget, Crypto.com, OKX, Bybit, Hyperliquid

If you submit a BTC-USD order but only have Binance credentials configured, it will be rejected - Binance doesn't support USD pairs. Use GET /v1/pairs/{symbol}/venues to check which venues support a given symbol.

Note

Market data endpoints like NBBO merge USD and USDC venues so you see the full liquidity picture. But order routing is always exact-match on the symbol.


When to expect floats vs fixed-point

Not every endpoint uses fixed-point. Read-only convenience endpoints return human-readable floats:

EndpointFormatExample fields
Order submission / responseFixed-pointqty_1e8, price_1e9, fee_1e9
PositionsFixed-pointqty_1e8, avg_cost_1e9, unrealized_pnl_1e9
gRPC market data streamsFixed-pointbid_px_1e9, bid_sz_1e8, exch_ts_ns
NBBO (REST)Floatbest_bid_px, best_bid_sz, mid_px
BBO (REST)Floatbid_price, bid_size, ask_price, ask_size
BalancesFloatavailable, total
Portfolio snapshotsFloatnav_usd, cash_usd

Rule of thumb: if the field name has a suffix (_1e8, _1e9, _bps, _ns), it's a fixed-point integer. If it doesn't, it's a float.


Order statuses

StatusTerminal?Meaning
ACCEPTEDNoOrder received, passing through validation and risk checks
RUNNINGNoActively being executed - child orders have been dispatched to venues
COMPLETEDYesFully filled
CANCELLEDYesCancelled by you or by the system (e.g., kill switch)
REJECTEDYesFailed validation, risk check, or insufficient balance
FAILEDYesExecution error (venue timeout, exchange rejection)
PARTIALYesPartially filled, then cancelled or failed

"Terminal" means the order has reached a final state and won't change further. Non-terminal orders are still in progress.

Algo orders (TWAP, VWAP, Iceberg) also use ACTIVE and PAUSED statuses while the algo scheduler manages their slice execution. FILLED is accepted as an alias for COMPLETED.


Error format

All errors follow the same structure:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "qty_1e8: must be positive",
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "details": [
      { "field": "qty_1e8", "message": "must be positive" }
    ]
  }
}

Use error.code for programmatic handling - it's stable. The message is for humans and may change. The details array only appears on VALIDATION_ERROR. See the API Overview for the full error code table.


Idempotency

Order submissions are idempotent via client_request_id. Submitting the same client_request_id twice returns the original parent_id without creating a duplicate order. This makes retries safe on network timeouts or 5xx errors.

If you retry with the same client_request_id but different parameters (e.g., changed quantity), you'll get a 409 Conflict.