Skip to main content
The USDC/cNGN spot market trades on the same orderbook as the futures instruments, but its prices are reported in two different units. Read this before integrating against spot — a price read from the wrong field is off by a factor of roughly 1,370.

Discover the market

Look for:
  • market = "USDCcNGN-SPOT"
  • contract_type = "spot"
  • order_entry_spec = "usdc_cngn_spot_v1"
Prefer the market symbol over asset_address and sub_id when you call the read endpoints. The symbol is stable; the address pair can change between deployments.

Read the current price

Every order in the response carries a spot_contract object. Read the price from it:
Read spot_contract.ui_intent.price, not the top-level price or limit_price.The engine trades cNGN against internal USDC cash, so its native price is USDC per cNGN (0.000728875…). ui_intent.price is the reciprocal — cNGN per USDC (1371.977018) — which is the number a person expects to see. Reading the raw field yields a price near zero, which usually looks like a broken response rather than a unit mismatch.
GET /v1/markets publishes the conversion rules inline on the spot entry, so you can assert them at runtime rather than hardcoding them:

Book sides are named for the engine

bids and asks describe the engine’s view, and the engine side is always the inverse of the trader’s. In trader terms the arrays read backwards: Each order also carries spot_contract.ui_intent.side, which states the trader-facing direction directly. Branch on that rather than on the array name. A mid price, with the sides read correctly:

Prefer the book over the last trade

GET /v1/trades returns the most recent fills, each with its own spot_contract. That is the right source for a “last traded at” display, and every trade carries created_at so you can show its age. It is the wrong source for a current rate. In a quiet period the last fill can be hours or days old, and the endpoint returns it without any staleness signal — a stale price and a fresh one look identical. The book quotes continuously, so a mid price stays current even when nothing is trading.
Check that bids and asks are both non-empty before computing a mid. If no maker is quoting, the arrays come back empty.

Candles

Candle prices are raw engine values with no spot_contract wrapper, so invert them yourself: ui_price = 1 / engine_price. Buckets with no trades are absent rather than zero-filled.

Polling and streaming

No rate limit is enforced. Polling every one to five seconds is ample for a displayed rate; be considerate rather than aggressive. For anything latency-sensitive, subscribe to the websocket stream instead. Use the book and trades channels with "market": "USDCcNGN-SPOT", seed from the snapshot frame, and apply update deltas. Public channels need no authentication, and server-side clients are unaffected by the browser origin allowlist.

Submitting spot orders

The same translation applies in reverse when you place an order. Send trader-facing values in ui_intent, and the engine values in the signed action_json.data:
order_entry_spec and ui_intent are accepted on spot orders only — omit both on futures. See Authentication and signing for building the signed payload, and Create order for the full request body.