Sequence/docs

Sandbox API

Endpoints for configuring and managing the sandbox (paper-trading) state of a client account. All endpoints require a sandbox API key (seq_test_*); calling them with a seq_live_* key returns 403 Forbidden.

Sandbox positions live in the same positions_v2 table as live positions, with is_sandbox = true. As a result, GET /v1/positions returns sandbox rows when called with a sandbox key — there is no separate read endpoint.


POST /v1/sandbox/positions

Configure explicit paper positions per (venue, kind, symbol). Writes to positions_v2 (so GET /v1/positions reflects the configured state) and mirrors cash rows into the SOR's in-memory balance cache (so reservations succeed on the order hot path).

Body

json
{
  "positions": [
    { "venue": "polymarket", "kind": "crypto", "symbol": "USDC", "qty": 10000.0 },
    { "venue": "kalshi",     "kind": "fiat",   "symbol": "USD",  "qty": 5000.0 },
    { "venue": "kalshi",     "kind": "event_contract",
      "symbol": "KXMARKET-FOO:YES", "qty": 100, "entry_price_usd": 0.40 },
    { "venue": "hyperliquid","kind": "perp",
      "symbol": "BTC-USD-PERP", "qty": 0.5, "entry_price_usd": 92000.0 }
  ],
  "replace": true
}
FieldTypeNotes
positions[].venuestringe.g. polymarket, kalshi, kraken, coinbase, dex, hyperliquid.
positions[].kindstringOne of fiat, crypto, event_contract, perp.
positions[].symbolstringFor fiat/crypto: asset code (USD, USDC, BTC). For event_contract: Kalshi ticker (KXFOO-...:YES/:NO) or Polymarket conditional token id. For perp: full symbol (BTC-USD-PERP).
positions[].qtynumberHuman-readable quantity. Must be ≥ 0 for fiat/crypto/event_contract. Perps may be negative (short).
positions[].entry_price_usdnumber?Optional cost basis per unit. Defaults: 1.0 for USD-pegged stablecoins/fiat, 0.0 otherwise.
replaceboolIf true, deletes all existing sandbox positions for the client first. Default false (upsert by (venue, kind, symbol)).

Response

json
{ "written": 4, "deleted": 7 }

Symbol-shape parsing for event_contract

InputParsed (market_slug, outcome, token_id)
KXFOO-BAR:YES("KXFOO-BAR", "YES", None)
KXFOO-BAR:NO("KXFOO-BAR", "NO", None)
1155562638... (≥30 digits)(symbol, "YES", Some(symbol)) — Polymarket token id
MARKET-SLUG(symbol, "YES", None)

To configure a Polymarket NO position, pass the NO outcome's token id directly.


POST /v1/sandbox/reset

Wipes all sandbox state for the client:

  • Deletes every positions_v2 row with is_sandbox = true.
  • Clears the in-memory sandbox balance cache.
  • Re-seeds with flat default balances ($1B per quote asset by default, configurable via PUT /v1/sandbox/settings) across all known venues — including Kalshi, Polymarket, and DEX.

Response

json
{ "reset": true, "initial_balance_usd": 1000000000.0, "venues_seeded": 9 }

PUT /v1/sandbox/settings

Set the default initial balance used by /v1/sandbox/reset. Useful when you want a different paper-portfolio size than the $1B default but don't need per-venue/per-asset granularity.

Body

json
{ "initial_balance_usd": 100000.0 }

Response

json
{ "initial_balance_usd": 100000.0 }

Changes take effect on the next POST /v1/sandbox/reset.


GET /v1/sandbox/settings

Returns the current default balance for the client.

json
{ "initial_balance_usd": 100000.0 }

How sandbox and live differ

The architecture is intentionally aligned — same storage, same write path, same read path. The only divergence is the source of initial state:

LiveSandbox
Storagepositions_v2, is_sandbox=falsepositions_v2, is_sandbox=true
Read APIGET /v1/positionsGET /v1/positions (same, auth-filtered)
Fill writesUnifiedPositionManagerUnifiedPositionManager (same)
Initial statePulled from venue RESTConfigured via POST /v1/sandbox/positions
Order executionReal venue submissionAdversarial sim against the real order book
Failure surfaceReal venue rejectionsMirrors live preflight (e.g. "market buy requires a live ask")

A sandbox order routes through the same SOR, hits the same edge process, and is dispatched to the edge's adversarial sim adapter via the per-order is_sandbox flag. Market-order safety guards (no-ask preflight) apply identically, so paper trades fail under the same conditions a live trade would fail.