DocsHomeOpen the app

Stratos API

Generated by pnpm stratos api-doc from a paper service on 2026-11-07: every answer below is real. Use @stratos/client from an interface: it signs actions, retries failovers and reconnects the stream.

Reads

Service info

Mode, chain, coins, fees, roll schedule, leverage tiers, vault address.

GET /v1/info

{
  "mode": "paper",
  "chainId": 99801,
  "coins": [
    "ETH",
    "HYPE"
  ],
  "faucet": true,
  "fees": {
    "standard": 0.0005,
    "degen": 0.0002,
    "degenProfitShare": 0.05,
    "liquidation": 0.01,
    "insuranceShare": 0.1
  },
  "roll": {
    "weekday": 5,
    "hourUtc": 8,
    "windowMs": 3600000
  },
  "tiers": [
    {
      "poolUsd": 0,
      "maxLeverage": 5,
      "degenMaxLeverage": 50
    },
    {
      "poolUsd": 250000,
      "maxLeverage": 10,
      "degenMaxLeverage": 75
    },
    "… 1 more"
  ],
  "vault": null,
  "stage": "ask"
}

Markets

Eight markets: X², X³ and their straddles on ETH and HYPE. maxLeverage is what a new position can take now. It slides down as the book's gap risk fills its budget (docs/PRICING_AND_LIQUIDATION.md). reduceOnly is set for 15 min after a fast move.

GET /v1/markets

[
  {
    "id": "ETH2",
    "coin": "ETH",
    "kind": "power",
    "power": 2,
    "name": "ETH²",
    "indexPrice": 3000,
    "markPrice": 3000,
    "ref": 3000,
    "nf": 1,
    "fundingRateYear": 0.417,
    "fundingRateHour": 0.0000476027,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 10,
    "degenMaxLeverage": 75,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 73,
    "nextRoll": 1794556800000
  },
  {
    "id": "ETH2S",
    "coin": "ETH",
    "kind": "straddle",
    "power": 2,
    "name": "ETH² straddle",
    "indexPrice": 3000,
    "markPrice": null,
    "ref": 3000,
    "nf": 1,
    "fundingRateYear": 0.317,
    "fundingRateHour": 0.0000361872,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 10,
    "degenMaxLeverage": 75,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 73,
    "nextRoll": 1794556800000
  },
  {
    "id": "ETH3",
    "coin": "ETH",
    "kind": "power",
    "power": 3,
    "name": "ETH³",
    "indexPrice": 3000,
    "markPrice": 3000,
    "ref": 3000,
    "nf": 1,
    "fundingRateYear": 1.101,
    "fundingRateHour": 0.000125685,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 6.66667,
    "degenMaxLeverage": 50,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 73,
    "nextRoll": 1794556800000
  },
  {
    "id": "ETH3S",
    "coin": "ETH",
    "kind": "straddle",
    "power": 3,
    "name": "ETH³ straddle",
    "indexPrice": 3000,
    "markPrice": null,
    "ref": 3000,
    "nf": 1,
    "fundingRateYear": 0.951,
    "fundingRateHour": 0.000108562,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 6.66667,
    "degenMaxLeverage": 50,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 73,
    "nextRoll": 1794556800000
  },
  {
    "id": "HYPE2",
    "coin": "HYPE",
    "kind": "power",
    "power": 2,
    "name": "HYPE²",
    "indexPrice": 40,
    "markPrice": 40,
    "ref": 40,
    "nf": 1,
    "fundingRateYear": 0.8225,
    "fundingRateHour": 0.0000938927,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 5,
    "degenMaxLeverage": 37.5,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 64,
    "nextRoll": 1794556800000
  },
  {
    "id": "HYPE2S",
    "coin": "HYPE",
    "kind": "straddle",
    "power": 2,
    "name": "HYPE² straddle",
    "indexPrice": 40,
    "markPrice": null,
    "ref": 40,
    "nf": 1,
    "fundingRateYear": 0.6225,
    "fundingRateHour": 0.0000710616,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 5,
    "degenMaxLeverage": 37.5,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 65,
    "nextRoll": 1794556800000
  },
  {
    "id": "HYPE3",
    "coin": "HYPE",
    "kind": "power",
    "power": 3,
    "name": "HYPE³",
    "indexPrice": 40,
    "markPrice": 40,
    "ref": 40,
    "nf": 1,
    "fundingRateYear": 2.1675,
    "fundingRateHour": 0.000247432,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 3.33333,
    "degenMaxLeverage": 25,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 65,
    "nextRoll": 1794556800000
  },
  {
    "id": "HYPE3S",
    "coin": "HYPE",
    "kind": "straddle",
    "power": 3,
    "name": "HYPE³ straddle",
    "indexPrice": 40,
    "markPrice": null,
    "ref": 40,
    "nf": 1,
    "fundingRateYear": 1.8675,
    "fundingRateHour": 0.000213185,
    "openInterest": {
      "long": 0,
      "short": 0
    },
    "maxLeverage": 3.33333,
    "degenMaxLeverage": 25,
    "degenMinLeverage": 1,
    "halted": false,
    "reduceOnlyUntil": null,
    "priceAgeMs": 65,
    "nextRoll": 1794556800000
  }
]

One market

GET /v1/markets/ETH2

{
  "id": "ETH2",
  "coin": "ETH",
  "kind": "power",
  "power": 2,
  "name": "ETH²",
  "indexPrice": 3000,
  "markPrice": 3000,
  "ref": 3000,
  "nf": 1,
  "fundingRateYear": 0.417,
  "fundingRateHour": 0.0000476027,
  "openInterest": {
    "long": 0,
    "short": 0
  },
  "maxLeverage": 10,
  "degenMaxLeverage": 75,
  "degenMinLeverage": 1,
  "halted": false,
  "reduceOnlyUntil": null,
  "priceAgeMs": 76,
  "nextRoll": 1794556800000
}

Quote

What an open would cost, its leverage and liquidation prices, and whether the engine would take it now (ok, or a reason). Pass account to check the user's own caps.

GET /v1/quote?market=ETH2&side=long&size=1000&collateral=200

{
  "ok": true,
  "reasons": [],
  "market": "ETH2",
  "side": "long",
  "size": 1000,
  "collateral": 200,
  "leverage": 5,
  "fee": 0.5,
  "fundingRateYear": 0.417,
  "fundingPerDay": 1.14247,
  "liquidationPrice": {
    "low": 2752.99,
    "high": null
  },
  "entryPrice": 3000,
  "maxLeverage": 10
}

Writes

Faucet (paper and testnet)

Test dollars once a day per account. Not on mainnet.

POST /v1/faucet {"account":"0xf77dbb8941bafb73767e13b0d91e80d7e47f8238"}

{
  "ok": true,
  "seq": 51,
  "events": [
    "Deposited"
  ]
}

The signed body

Every write looks like this (client.sign):

{
  "action": "open",
  "payload": "{\"market\":\"ETH2\",\"side\":\"long\",\"size\":1000,\"collateral\":200}",
  "nonce": "1794040341934000",
  "expiry": 1794040401934,
  "account": "0xf77dbB8941baFB73767E13b0d91E80d7E47F8238",
  "signature": "0xa2163dc821a70930a7e7e8e55df667460b6b90…"
}

Open

size is notional USD and collateral is USD taken from free cash. degen: true gives fixed knock-out leverage. The position id is account:nonce.

POST /v1/exchange {action:"open", payload:{"market":"ETH2","side":"long","size":1000,"collateral":200}}

{
  "ok": true,
  "seq": 52,
  "events": [
    "Opened"
  ]
}

Re-sending the same body

The same nonce is the same command: same answer, nothing done twice.

POST /v1/exchange (same body)

{
  "ok": true,
  "seq": 52,
  "events": [
    "Opened"
  ]
}

Positions

Live P&L, equity, leverage and liquidation prices.

GET /v1/accounts/0xf77dbb8941bafb73767e13b0d91e80d7e47f8238/positions

[
  {
    "id": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238:1794040341934000",
    "market": "ETH2",
    "kind": "power",
    "power": 2,
    "side": "long",
    "degen": false,
    "size": 1060.9,
    "entryNotional": 1000,
    "collateral": 200,
    "pnl": 60.9,
    "funding": -0.000001,
    "equity": 260.9,
    "leverage": 4.06631,
    "marginRatio": 4.91847,
    "liquidationPrice": {
      "low": 2752.99,
      "high": null
    },
    "entryPrice": 3000,
    "indexPrice": 3090,
    "fundingRateYear": 0.417,
    "openedAt": 1794040341949
  }
]

Add margin

POST /v1/exchange {action:"addMargin", payload:{"position":"…","amount":50}}

{
  "ok": true,
  "seq": 61,
  "events": [
    "MarginAdded"
  ]
}

Close (part)

fraction closes part of the position; leave it out to close all of it.

POST /v1/exchange {action:"close", payload:{"position":"…","fraction":0.5}}

{
  "ok": true,
  "seq": 62,
  "events": [
    "Settled"
  ]
}

LP deposit

Mints pool shares at NAV.

POST /v1/exchange {action:"poolDeposit", payload:{"amount":500}}

{
  "ok": true,
  "seq": 63,
  "events": [
    "PoolDeposited"
  ]
}

Withdraw

Takes free cash out of the engine. In testnet and mainnet the answer carries withdrawal: pass it to vault.withdraw(amount, nonce, deadline, signature) (vaultWithdrawArgs). Paper mode has no vault, so its signature is null.

POST /v1/exchange {action:"withdraw", payload:{"amount":100}}

{
  "ok": true,
  "seq": 64,
  "events": [
    "Withdrew"
  ],
  "withdrawal": {
    "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
    "amount": 100000000,
    "nonce": "1794040341984000",
    "deadline": 1794126741,
    "signature": null,
    "vault": null,
    "chainId": null
  }
}

Linked devices (agent keys)

An account can let another key sign for it, as Hyperliquid's agent wallets do: a phone linked from the desktop. The account's own wallet signs approveAgent; after that a body with account set to the account and signed by the agent's key is accepted. An agent can trade, manage positions and orders, and use the pool; it can't withdraw or approveAgent, and it can revokeAgent only itself. At most 5 at a time, each for up to 180 days. GET /v1/info says whether the service has it on (agents: true); GET /v1/accounts/{account} lists them under agents.

POST /v1/exchange {action:"approveAgent", payload:{"agent":"0x…","name":"Phone","expiresAt":1797000000000}} POST /v1/exchange {action:"revokeAgent", payload:{"agent":"0x…"}}

With @stratos/client: client.approveAgent({ agent, name, expiresAt }), and an agent's client is new StratosClient({ baseUrl, signer: { address: agentAddress, account: ownerAccount, signTypedData } }).

A rejection

HTTP 422 with a stable code.

POST /v1/exchange {action:"open", payload:{"size":1000000,"collateral":10,…}}

{
  "ok": false,
  "code": "leverage_too_high",
  "message": "leverage 100000.00x is over 10x (rises w…"
}

Account, pool and transparency

Account

Free cash, positions, P&L and pool shares.

GET /v1/accounts/0xf77dbb8941bafb73767e13b0d91e80d7e47f8238

{
  "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
  "cash": 9304.68,
  "accountValue": 9460.13,
  "collateral": 125,
  "notional": 530.45,
  "pnl": {
    "realized": 30.45,
    "unrealized": 30.45,
    "fees": 0.765225,
    "funding": -0.000001,
    "total": 60.1348
  },
  "volume": 1530.45,
  "trades": 2,
  "liquidations": 0,
  "knockouts": 0,
  "deposited": 10000,
  "withdrawn": 100,
  "pool": {
    "shares": 500000000,
    "value": 500,
    "queued": 0
  },
  "positions": [
    {
      "id": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238:1794040341934000",
      "market": "ETH2",
      "kind": "power",
      "power": 2,
      "side": "long",
      "degen": false,
      "size": 530.45,
      "entryNotional": 500,
      "collateral": 125,
      "pnl": 30.45,
      "funding": -0.000001,
      "equity": 155.45,
      "leverage": 3.41235,
      "marginRatio": 5.86106,
      "liquidationPrice": {
        "low": 2665.57,
        "high": null
      },
      "entryPrice": 3000,
      "indexPrice": 3090,
      "fundingRateYear": 0.417,
      "openedAt": 1794040341949
    }
  ]
}

Trades

Newest first. Page with before (a time) and limit (at most 500).

GET /v1/accounts/0xf77dbb8941bafb73767e13b0d91e80d7e47f8238/trades

[
  {
    "seq": 62,
    "t": 1794040341975,
    "kind": "close",
    "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
    "position": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238:1794040341934000",
    "market": "ETH2",
    "side": "long",
    "notional": 530.45,
    "spot": 3090,
    "pnl": 30.45,
    "funding": 0,
    "fee": 0.265225
  },
  {
    "seq": 52,
    "t": 1794040341949,
    "kind": "open",
    "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
    "position": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238:1794040341934000",
    "market": "ETH2",
    "side": "long",
    "notional": 1000,
    "spot": 3000,
    "pnl": 0,
    "funding": 0,
    "fee": 0.5
  }
]

Candles

Index candles per coin, oldest first: interval 1m, 5m, 15m, 1h, 4h or 1d; limit up to 5,000 (default 500); end (ms, exclusive) pages backwards. The engine's own candles start when the node did; before that the node serves Hyperliquid's public candles for the coin (daily back to August 2020 for ETH and December 2024 for HYPE, 4h about two years, 1h about seven months, 1m a few days), synced every minute. The two are spliced at the first live candle, so a chart is continuous and its recent part is exactly what the engine priced on.

GET /v1/candles?coin=ETH&interval=1m&limit=2

[
  {
    "t": 1794040320000,
    "o": 3000,
    "h": 3090,
    "l": 3000,
    "c": 3090
  }
]

Pool

LP pool NAV, shares, the next roll (withdrawals settle there).

GET /v1/pool

{
  "nav": 300500,
  "cash": 300500,
  "sharePrice": 1,
  "shares": 300500000000,
  "queuedShares": 0,
  "navMarkedAt": 0,
  "nextRoll": 1794556800000,
  "insuranceFund": 0.026523,
  "tier": {
    "poolUsd": 250000,
    "maxLeverage": 10,
    "degenMaxLeverage": 75
  },
  "revenue": {
    "tradingFees": 0.738702,
    "liquidationFees": 0,
    "insuranceIn": 0.026523
  }
}

Stats

Volume, fees, liquidations, revenue.

GET /v1/stats

{
  "openInterest": 530.45,
  "volume": 1530.45,
  "positions": 1,
  "accounts": 2,
  "insuranceFund": 0.026523,
  "protocolRevenue": 0.738702,
  "seq": 64
}

Risk

Each coin's gap risk against its budget: what's driving leverage limits right now.

GET /v1/risk

[
  {
    "coin": "ETH",
    "designGap": {
      "down": 0.15,
      "up": 0.2
    },
    "gapNow": {
      "down": 0.15,
      "up": 0.2
    },
    "volMultiple": 1,
    "realizedVol": null,
    "baseVol": 0.6,
    "lossOnGap": {
      "down": 11.9351,
      "up": 21.218
    },
    "worst": 21.218,
    "side": "up",
    "budget": 52587.5,
    "used": 0.00040348,
    "poolCarriedConvexityShare": 1,
    "maxLossShare": 0.25,
    "leverageScale": 1,
    "maxLeverageNow": {
      "squared": 10,
      "degen": 75
    }
  },
  {
    "coin": "HYPE",
    "designGap": {
      "down": 0.3,
      "up": 0.4
    },
    "gapNow": {
      "down": 0.3,
      "up": 0.4
    },
    "volMultiple": 1,
    "realizedVol": null,
    "baseVol": 0.9,
    "lossOnGap": {
      "down": 0,
      "up": 0
    },
    "worst": 0,
    "side": "down",
    "budget": 22537.5,
    "used": 0,
    "poolCarriedConvexityShare": 0,
    "maxLossShare": 0.25,
    "leverageScale": 0.5,
    "maxLeverageNow": {
      "squared": 5,
      "degen": 37.5
    }
  }
]

Reserves

Proof of reserves: liabilities (a Merkle tree of balances) against the vault plus the hedge.

GET /v1/reserves

{
  "seq": 64,
  "t": 1794040342016,
  "root": "0x72b35b8f8fb304e8cc581409926f4438201947bb1a7d15c615ba1ab409c04d66",
  "accounts": 1,
  "liabilities": 9960.13,
  "internalLiabilities": 300000,
  "reserves": {
    "vault": 9400,
    "hedge": 300000,
    "total": 309400
  },
  "coverage": 0.998193,
  "reserveRatio": 0.0303265,
  "bridge": null,
  "vault": null
}

Your proof

Check it against the root posted on the vault (verifyBalance). It's also what the escape hatch pays if the service ever stops.

GET /v1/reserves/proof/0xf77dbb8941bafb73767e13b0d91e80d7e47f8238

{
  "root": "0x72b35b8f8fb304e8cc581409926f4438201947bb1a7d15c615ba1ab409c04d66",
  "seq": 64,
  "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
  "balanceMicro": "9960134774",
  "balance": 9960.13,
  "proof": []
}

Stream

WS /ws, send {"subscribe":"markets"} or {"subscribe":"account:0x…"}. Frames are {channel, data}: the whole markets list, or the account view (same shape as GET /v1/accounts/…), at most a few times a second. client.subscribe reconnects and re-subscribes.

{
  "channel": "account:0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
  "data": {
    "account": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238",
    "cash": 9304.68,
    "accountValue": 9460.13,
    "collateral": 125,
    "notional": 530.45,
    "pnl": {
      "realized": 30.45,
      "unrealized": 30.45,
      "fees": 0.765225,
      "funding": -0.000001,
      "total": 60.1348
    },
    "volume": 1530.45,
    "trades": 2,
    "liquidations": 0,
    "knockouts": 0,
    "deposited": 10000,
    "withdrawn": 100,
    "pool": {
      "shares": 500000000,
      "value": 500,
      "queued": 0
    },
    "positions": [
      {
        "id": "0xf77dbb8941bafb73767e13b0d91e80d7e47f8238:1794040341934000",
        "market": "ETH2",
        "kind": "power",
        "power": 2,
        "side": "long",
        "degen": false,
        "size": 530.45,
        "entryNotional": 500,
        "collateral": 125,
        "pnl": 30.45,
        "funding": -0.000001,
        "equity": 155.45,
        "leverage": 3.41235,
        "marginRatio": 5.86106,
        "liquidationPrice": {
          "low": 2665.57,
          "high": null
        },
        "entryPrice": 3000,
        "indexPrice": 3090,
        "fundingRateYear": 0.417,
        "openedAt": 1794040341949
      }
    ]
  }
}

Operations

GET /healthz (200 while serving; leader checks price freshness), GET /readyz (200 when the node can take traffic: leader, or a caught-up standby), GET /metrics (Prometheus text; docs/OPERATIONS.md), GET /v1/bridge (bridge transfers in flight, docs/BRIDGING.md).

Stratos · paper modeapp.stratos.cash