Sequence/docs

Positions

Sequence unifies everything the user owns into a single primitive: a Position.

  • Fiat cash (USD on Kalshi, stablecoin-pegged USD), Crypto (BTC, ETH, USDC across CEXes and on-chain wallets), Perps (Hyperliquid signed positions with margin locks), and Event contracts (Kalshi YES/NO, Polymarket outcome tokens) all live as rows in the same positions_v2 table.
  • One endpoint, one response shape. Old /v1/balances, /v1/positions/perp, and /v1/portfolio/* have been removed.

Get Positions

GET/v1/positions

Returns active positions across every venue and every instrument kind.

Values come from three reconciled sources that all write through the same manager:

  • Fill events (hot path) — every fill routed through FillRouter decomposes into typed deltas and updates the row
  • Venue balance APIs (cold sync) — startup balance recovery and periodic reconciliation pull authoritative balances from Kraken / Coinbase / DEX / Kalshi / Hyperliquid
  • Venue portfolio APIs (cold sync) — Kalshi /portfolio/positions, Polymarket data-api/positions, Polymarket USDC via Polygon balanceOf

Query Parameters

ParameterDefaultDescription
venuesallComma-separated venue filter (e.g., kraken,coinbase)
kindsallComma-separated instrument-kind filter: fiat, crypto, perp, event_contract
include_closedfalseInclude terminal rows (closed, redeemed). Resolved rows are always in the default response so settled event contracts surface alongside open positions.

Response

json
{
  "positions": [
    {
      "id": 101,
      "venue": "coinbase",
      "instrument": { "kind": "crypto", "symbol": "USDC" },
      "qty_1e8": 237848346884,
      "locked_qty_1e8": 0,
      "available_qty_1e8": 237848346884,
      "entry_price_usd_1e9": 1000000000,
      "current_price_usd_1e9": 1000000000,
      "current_value_usd_1e9": 2378483468840,
      "unrealized_pnl_usd_1e9": 0,
      "realized_pnl_usd_1e9": 0,
      "fees_usd_1e9": 0,
      "lifecycle": { "state": "active" },
      "transferable": true,
      "settled": false,
      "settled_mark_usd_1e9": null
    },
    {
      "id": 102,
      "venue": "kalshi",
      "instrument": { "kind": "fiat", "code": "USD" },
      "qty_1e8": 10000000000,
      "entry_price_usd_1e9": 1000000000,
      "current_value_usd_1e9": 100000000000,
      "unrealized_pnl_usd_1e9": 0,
      "lifecycle": { "state": "active" },
      "transferable": true,
      "settled": false,
      "settled_mark_usd_1e9": null
    },
    {
      "id": 103,
      "venue": "hyperliquid",
      "instrument": { "kind": "perp", "symbol": "BTC-PERP", "base": "BTC" },
      "qty_1e8": 50000000,
      "entry_price_usd_1e9": 90000000000000,
      "current_price_usd_1e9": 91500000000000,
      "current_value_usd_1e9": 45750000000000,
      "unrealized_pnl_usd_1e9": 750000000000,
      "lifecycle": { "state": "active" },
      "transferable": false,
      "settled": false,
      "settled_mark_usd_1e9": null
    },
    {
      "id": 104,
      "venue": "polymarket",
      "instrument": {
        "kind": "event_contract",
        "market_slug": "0x14f1b88cd673ffb56c010fc065cdebee82f0bdb6b9a38109109cc71c1ed7aee9",
        "outcome": "DOWN",
        "token_id": "16669419551497791855954864481644480637553894270103338484394743642601464846109",
        "expiry_ts": null
      },
      "qty_1e8": 619800000,
      "entry_price_usd_1e9": 320000000,
      "current_price_usd_1e9": 0,
      "current_value_usd_1e9": 0,
      "unrealized_pnl_usd_1e9": -1983360000,
      "lifecycle": {
        "state": "resolved",
        "outcome": "Up",
        "economic_value_usd_1e9": 0,
        "resolved_at": 1776971900987654321
      },
      "transferable": false,
      "settled": true,
      "settled_mark_usd_1e9": 0
    },
    {
      "id": 105,
      "venue": "kalshi",
      "instrument": {
        "kind": "event_contract",
        "market_slug": "KXPGATOUR-ZUCONO26-THVI",
        "outcome": "YES",
        "token_id": null,
        "expiry_ts": null
      },
      "qty_1e8": 500000000,
      "entry_price_usd_1e9": 600000000,
      "current_price_usd_1e9": 1000000000,
      "current_value_usd_1e9": 5000000000,
      "unrealized_pnl_usd_1e9": 2000000000,
      "lifecycle": {
        "state": "resolved",
        "outcome": "YES",
        "economic_value_usd_1e9": 5000000000,
        "resolved_at": 1776971900987654321
      },
      "transferable": false,
      "settled": true,
      "settled_mark_usd_1e9": 1000000000
    }
  ],
  "totals": {
    "nav_usd_1e9": 48233483468840,
    "cash_usd_1e9": 2478483468840,
    "unrealized_pnl_usd_1e9": 750016640000,
    "realized_pnl_usd_1e9": 0,
    "fees_usd_1e9": 0,
    "num_positions": 5
  },
  "as_of_ns": 1776828335325953000
}

Instrument discriminant

instrument.kind selects which additional fields are populated:

kindAdditional fieldsExample identifier
fiatcode"USD"
cryptosymbol"BTC", "USDC", "ETH.B"
perpsymbol, base{symbol: "BTC-PERP", base: "BTC"}
event_contractmarket_slug, outcome, token_id?, expiry_ts?Polymarket condition_id or Kalshi ticker + "YES"/"NO"

Position fields

FieldDescription
idDatabase primary key
venueVenue identifier (lowercase)
instrumentTagged union; see instrument discriminant above
qty_1e8Signed qty in native units × 10⁸. Positive for long, negative for short perp/event contracts
locked_qty_1e8Portion of qty_1e8 reserved as perp margin
available_qty_1e8qty - locked — spendable qty
entry_price_usd_1e9Weighted-average USD entry price × 10⁹ (historical fact; not FX-sensitive)
current_price_usd_1e9Current mark price × 10⁹. Sourced from the consolidated NBBO for crypto/perp rows, from the settled mark ($1 for winners, $0 for losers) for settled event contracts, otherwise falls back to entry_price.
current_value_usd_1e9qty * current_price / 1e8 — mark-to-market value, authoritative post-settlement
unrealized_pnl_usd_1e9current_value - entry_value
realized_pnl_usd_1e9Accrued from closed portions of this row
fees_usd_1e9Cumulative fees charged
lifecycleTagged union. {"state":"active"} for open positions. For settled event contracts: {"state":"resolved", "outcome": string, "economic_value_usd_1e9": int, "resolved_at": ns} — written automatically the moment Sequence observes the Kalshi determined / Polymarket market_resolved telemetry, independent of when the venue cleans up its qty. {"state":"redeemed", "cash_received_usd_1e9": int, "redeemed_at": ns} once POST /v1/markets/:slug/redeem succeeds. {"state":"closed"} once qty goes to 0.
transferabletrue for fungible assets (Fiat, Crypto) — can deposit/withdraw between venues
settledtrue iff the position's market has resolved. Set the instant resolution telemetry lands — may briefly be true with lifecycle.state still active during the ~ms race between the hub broadcast and the DB commit (cache read-through covers this gap). Once settled, stays true through redeemed.
settled_mark_usd_1e9Settled per-unit mark × 10⁹: 1000000000 ($1) for winners, 0 for losers, null pre-settlement. Redundant with lifecycle.economic_value_usd_1e9 / qty_1e8 * 1e8 but explicit — clients don't have to pattern-match the tagged union.

totals block

Aggregates across the returned rows (respects filters):

FieldDescription
nav_usd_1e9Sum of all current_value_usd_1e9
cash_usd_1e9Sum for fiat + stablecoin rows (USDC/USDT/DAI/BUSD/FDUSD/TUSD/USDP = $1 pegs)
unrealized_pnl_usd_1e9Mark-to-market P&L across returned positions
realized_pnl_usd_1e9Sum of realized P&L
fees_usd_1e9Sum of cumulative fees
num_positionsCount of rows returned

Common queries

All cash across every venue:

bash
curl -H "Authorization: Bearer seq_live_..." \
  "https://api.sequencemkts.com/v1/positions?kinds=fiat,crypto"

Only Hyperliquid perps:

bash
curl -H "Authorization: Bearer seq_live_..." \
  "https://api.sequencemkts.com/v1/positions?kinds=perp&venues=hyperliquid"

Event contracts on Kalshi + Polymarket:

bash
curl -H "Authorization: Bearer seq_live_..." \
  "https://api.sequencemkts.com/v1/positions?kinds=event_contract&venues=kalshi,polymarket"

Resolved markets surface in the default response with settled=true and the terminal settled mark — you do not need include_closed to see them. Add include_closed=true only if you also want the redeemed or closed terminal states.


Sync Cost Basis

POST/v1/positions/sync

Triggers an immediate fetch of trade history from connected exchanges to refresh cost basis on existing crypto positions. Useful when entry_value_usd_1e9 shows 0 on an asset you deposited externally — the venue-balance poll knows the qty but not what you paid for it.

Response:

json
{ "synced": true, "message": "venue trade sync kicked off" }

The refresh runs in the background; positions update within ~30 seconds for venues with trade-history APIs.


Fee Tiers

GET/v1/fees

Maker/taker fees for one ticker across one or more venues. Returns the fee components and curve formula so latency-sensitive callers can compute the exact realized fee locally — no per-(qty, price) round-trip. Fetch once per ticker, cache, evaluate the formula client-side.

Query Parameters

ParameterDefaultDescription
tickerRequiredSymbol, Kalshi ticker, Polymarket clob_token_id, or Polymarket slug
venuesAll connectedComma-separated venue list (e.g. "kalshi,polymarket")

The handler accepts:

  • CEX symbols: BTC-USD, BTCUSDT, ETH-USDC
  • Kalshi tickers: KXMLBHR-26APR-FOO:YES
  • Polymarket clob_token_id (78-digit numeric)
  • Polymarket slug (nba-finals-okc-2026) — resolved via Gamma → conditionId → CLOB fee schedule

When venues= is omitted, only venues that can plausibly list the ticker shape are returned (Kalshi tickers route to Kalshi only; CEX symbols route to CEX/DEX only). When venues= is explicit, the user's intent is honored — useful for slug lookups that don't match a built-in shape.

Response

json
{
  "ticker": "BTC-USD",
  "fees": [
    {
      "venue": "binance",
      "maker_bps": 0,
      "taker_bps": 10,
      "fee_model": "linear",
      "components": {},
      "formula": {
        "taker_fee_usd": "qty * price * taker_bps / 10000",
        "maker_fee_usd": "qty * price * maker_bps / 10000"
      }
    },
    {
      "venue": "hyperliquid",
      "maker_bps": 0,
      "taker_bps": 2,
      "fee_model": "linear",
      "components": {},
      "formula": {
        "taker_fee_usd": "qty * price * taker_bps / 10000",
        "maker_fee_usd": "qty * price * maker_bps / 10000"
      }
    }
  ]
}

For a Polymarket prediction market:

json
{
  "venue": "polymarket",
  "maker_bps": 0,
  "taker_bps": 360,
  "fee_model": "binary_quadratic",
  "components": {
    "rate_bps": 720,
    "exponent": 1
  },
  "formula": {
    "taker_fee_usd": "qty * price * pow(1 - price, exponent) * rate_bps / 10000",
    "maker_fee_usd": "0"
  }
}

For a Kalshi market:

json
{
  "venue": "kalshi",
  "maker_bps": 0,
  "taker_bps": 350,
  "fee_model": "binary_quadratic",
  "components": {
    "rate_bps": 700,
    "multiplier": 1.0,
    "rounding": "ceil_to_cent"
  },
  "formula": {
    "taker_fee_usd": "ceil((qty * price * (1 - price) * rate_bps * multiplier / 10000) * 100) / 100",
    "maker_fee_usd": "0"
  }
}

Field Reference

FieldDescription
tickerThe queried ticker (echoed back)
venueVenue identifier
maker_bpsMaker fee in basis points. For binary_quadratic venues this is the at-mid rate (typically 0 for Polymarket and standard Kalshi markets). null = unknown
taker_bpsTaker fee in basis points. At-mid value for binary_quadratic (rate at price=0.5); flat rate for linear. null = unknown — treat as ineligible for routing
fee_modelCurve type: "linear" (CEX/DEX, fee is qty × price × bps) or "binary_quadratic" (Polymarket / Kalshi prediction, fee is qty × price × (1-price) × rate_bps)
componentsCurve parameters. Stable keys per fee_model.
formula.taker_fee_usdPlain-string formula the client can evaluate locally for the exact taker fee at any (qty, price)
formula.maker_fee_usdSame for maker fee

components keys per fee_model:

ModelKeys
linear{} (no extra params; taker_bps is the rate)
binary_quadratic (Polymarket){ rate_bps, exponent }
binary_quadratic (Kalshi){ rate_bps, multiplier, rounding }

rate_bps is the curve coefficient r × 10_000 (i.e. 2 × taker_bps_at_mid). exponent defaults to 1 (reserved for future non-linear curves). multiplier is per-Kalshi-series (currently 1.0 on every active series we've sampled). rounding: "ceil_to_cent" documents Kalshi's per-fill ceil-to-cent behavior — clients should mirror it to avoid under-quoting.

Computing fees client-side (latency-sensitive path)

Fetch /v1/fees once per ticker (cache forever — fees don't change minute-to-minute), then evaluate the formula locally per fill candidate:

python
row = fees_response["fees"][venue_index]
 
if row["fee_model"] == "binary_quadratic":
    rate = row["components"]["rate_bps"]
    exponent = row["components"].get("exponent", 1)
    fee = qty * price * pow(1 - price, exponent) * rate / 10000
    if row["components"].get("rounding") == "ceil_to_cent":
        fee = math.ceil(fee * 100) / 100   # Kalshi
elif row["fee_model"] == "linear":
    fee = qty * price * row["taker_bps"] / 10000
Note

For a server-authoritative answer that also includes size-aware slippage + total landed cost (not just fees), use POST /v1/orders/preview. That endpoint composes fee + slippage + venue-specific semantics for your exact order shape and is the canonical "how much will this cost?" surface. Use /v1/fees when you want the static fee parameters and plan to compute fees yourself per fill.

Note

The SOR uses taker fees when routing market orders and accounts for maker fees on limit orders. Fee differentials between venues are a significant factor in routing decisions — the cheapest quoted price may not be the cheapest after fees.


Removed endpoints

The following endpoints were consolidated into GET /v1/positions and now return 404:

Old endpointReplacement
GET /v1/balancesGET /v1/positions?kinds=fiat,crypto
GET /v1/positions/perpGET /v1/positions?kinds=perp
GET /v1/portfolio/summaryGET /v1/positions — read totals block
GET /v1/portfolio/snapshotsremoved (not replaced)
GET /v1/portfolio/unifiedGET /v1/positions
GET /v1/analytics/portfolioGET /v1/positions
POST /v1/positions/perp/fundingremoved; perp funding ingestion is automatic