WebSocket API
Hypercallオプション取引向けのリアルタイムデータストリーミングです。
ライブ例やスキーマの詳細をより快適に閲覧できるインタラクティブWebSocket APIリファレンスをご覧ください。
プログラムでの利用向けにAsyncAPI仕様をダウンロードしてください。
接続
wss://HOST/wsに接続します。
エンドポイント:
- 本番環境:
wss://api.hypercall.xyz/ws - ローカル:
ws://localhost:3000/ws
テストネットは、Hypercallがより多くのテストネットHYPEを取得するまで一時的に無効化されています。
ウォレットの識別
認証済みチャンネル(注文、約定、ポートフォリオ)でデータを受信するには、接続後にAuthenticateメッセージを送信してウォレットを識別してください。
{"type": "Authenticate", "wallet": "0x1234..."}
サーバーは確認メッセージを返します。
{"type": "Authenticated", "wallet": "0x1234..."}
Authenticatedを受信した後、認証済みチャンネルを購読できます。ウォレットアドレスが無効な場合、サーバーはErrorメッセージを返し、接続は開いたままになります。
?wallet=クエリパラメータは後方互換性のために引き続きサポートされていますが、非推奨であり、将来のリリースで削除されます。上記のメッセージベースの方法を優先してください。
接続の生存確認
サーバーはWebSocketのハートビートを強制します。
- 20秒ごとに
Ping制御フレームを送信します - 60秒以内に対応する
Pongを期待します - クライアントが応答を停止した場合、クローズコード
1008と理由pong timeoutで接続を閉じます
ブラウザのWebSocket実装は、ping/pongを自動的に処理します。tungsteniteやtokio-tungsteniteを含む多くのRust WebSocketライブラリも、制御フレームのping/pongを代わりに処理します。手動でのPong処理を追加する前に、クライアントのライブラリのドキュメントを確認してください。カスタムまたは生のソケット実装では、PingフレームにPongで応答する必要があります。
スロー・コンシューマーからの回復
サーバーは、設定されたメッセージ数、エンコード済みバイト数、キュー滞留時間、またはソケット書き込みの安全上限の範囲内で送信データを処理しきれない/ws接続を閉じます。接続がまだクローズフレームを受け入れられる場合、サーバーはコード1008と簡潔なJSON理由を使用します。
{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}
理由フィールドは次のとおりです。
| フィールド | 意味 |
|---|---|
class | フレームが安全境界を超えた配信クラス。 |
cause | message_limit、byte_limit、message_age、またはwrite_timeout。 |
recovery | resubscribe、snapshot_resubscribe、portfolio_refetch、rest_reconcileなど、必要な次のアクション。 |
切断後は、再接続し、必要に応じて再度ウォレットを識別し、再購読し、新しいイベントを処理する前に現在の状態を照合してください。順序付き公開チャンネルには新しいスナップショットが必要です。プライベート・イベント・チャンネルは、カーソルの再生がまだ利用できないため、正式なREST面を通じた照合が必要です。完全に停止した接続は、クローズ理由を読み取る前に終了する場合があるため、クライアントは不正なクローズに対してもこの回復フローを使用する必要があります。
高頻度の公開マーケットデータと、認証済みコマンドまたはプライベートストリームには、別々の接続を使用してください。配信クラスはメトリクスと回復動作を選択しますが、1つの接続上のフレームは依然として1つの順序付きソケット書き込みパスを共有します。そのため、停止した公開書き込みは、書き込みデッドラインが接続を閉じるまで、同じ接続上の後続のプライベートフレームを遅延させる可能性があります。
チャンネルの購読
購読するにはJSONメッセージを送信します。
{"type": "Subscribe", "channel": "orderbook"}
購読を解除するには:
{"type": "Unsubscribe", "channel": "orderbook"}
確認メッセージを受信します。
{"type": "Subscribed", "channel": "orderbook"}
シンボルフィルタリング
order_updatesおよびfillsチャンネルは、オプションのsymbolsフィルタをサポートします。指定された場合、サーバーは原資産が指定されたシンボルのいずれかに一致するメッセージのみを送信します。
{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}
原資産のみ("BTC")と完全な銘柄名("BTC-20260131-100000-C")の両方が受け付けられます。シンボルを追加するには、別のSubscribeを送信してください。特定のシンボルを削除するには:
{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}
symbolsが指定されていない場合、ウォレットのすべての更新が転送されます。
オプションチェーンのフィルタリング
options_chainチャンネルは、原資産シンボル、満期日、オプションの種類によるフィルタリングをサポートします。
{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
| フィルタ | 値 | デフォルト |
|---|---|---|
symbols | 完全な銘柄シンボルの配列(例: ["BTC-20260131-100000-C"]) | すべての銘柄 |
expiry | 日付文字列 "YYYY-MM-DD" | すべての満期 |
option_type | "call"、"put"、または両方の場合は省略 | 両方 |
利用可能なチャンネル
| チャンネル | 認証の要否 | 説明 |
|---|---|---|
orderbook | 不要 | すべてのシンボルのL2オーダーブック更新 |
trades | 不要 | 公開トレードフィード |
market_updates | 不要 | マーケット一覧の変更(作成/削除/満期切れ) |
options_chain | 不要 | オプションチェーンの差分更新(symbols、expiry、option_typeでフィルタ可能) |
index_prices | 不要 | すべての原資産のリアルタイムスポット/インデックス価格 |
indicative_market_data | 不要 | 許可リスト制のクオートプロバイダーストリーム。まだ一般提供されていません |
order_updates | 必要 | あなたの注文ステータスの変更(シンボルでフィルタ可能) |
fills | 必要 | あなたの約定(シンボルでフィルタ可能) |
portfolio | 必要 | あなたのポジションと残高の更新 |
liquidation | 必要 | あなたの清算状態の変更 |
competition | 必要 | あなたのコンペティションPnLサマリー、順位、最終統計 |
competition_engagement | 必要 | 順位変動、次順位との差、最終順位 |
rfq | 必要 | RFQクオート、ステータス更新、約定通知 |
メッセージタイプ
注文の発注(認証済み)
WebSocketコマンドパスを通じて注文を発注します。
{
"type": "PlaceOrder",
"wallet": "0x1234...",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"size": "1",
"price": "100",
"tif": "gtc",
"route": "book_only",
"client_id": "my-order-1",
"nonce": 1000,
"signature": "0x..."
}
| フィールド | 型 | 説明 |
|---|---|---|
wallet | string | 注文を所有するウォレットアドレス |
symbol | string | オプションシンボル |
side | string | "Buy"または"Sell" |
size | string | 契約サイズ、署名した値と完全に一致すること |
price | string | 指値価格、署名した値と完全に一致すること |
tif | string | 任意のtime-in-force、デフォルトは"gtc" |
route | string | 任意のルート。ルート対応のWebSocket注文には"book_only"を使用してください。ルートを省略した場合、少なくとも2026年7月4日までは引き続き受け付けられます。 |
client_id | string | 任意のクライアント注文ID |
nonce | integer | 一意の署名nonce |
signature | string | EIP-712 PlaceOrder署名 |
WebSocketのPlaceOrderは現在、オーダーブックに直接ディスパッチされます。route="best_execution"およびroute="rfq_only"は、このパスがまだRPI/RFQルーティングを実行しないため、WebSocketでは拒否されます。best_executionにはPOST /orderを使用してください。
オーダーブック更新
シンボルのL2オーダーブックのスナップショット/更新です。
{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
| フィールド | 型 | 説明 |
|---|---|---|
symbol | string | オプションシンボル |
bids | array | [price, size]のタプルによるビッド水準、サイズは人間が読める契約単位 |
asks | array | [price, size]のタプルによるアスク水準、サイズは人間が読める契約単位 |
timestamp | integer | Unixタイムスタンプ(ミリ秒) |
トレード
公開トレードイベントです。
{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
| フィールド | 型 | 説明 |
|---|---|---|
symbol | string | オプションシンボル |
price | string | USD建てのトレード価格 |
size | string | 契約単位のトレードサイズ |
side | string | アグレッサー側(buyまたはsell) |
timestamp | integer | Unixタイムスタンプ(ミリ秒) |
約定(認証済み)
あなたの約定通知です。
{
"type": "Fill",
"order_id": 12345,
"fill_id": 67890,
"symbol": "BTC-20260131-100000-C",
"side": "buy",
"price": "0.0523",
"size": "5.0",
"timestamp": 1737331200000,
"wallet_address": "0x1234...abcd",
"fee": "0",
"trade_id": 99999,
"is_taker": true
}
| フィールド | 型 | 説明 |
|---|---|---|
order_id | integer | お客様の注文ID |
fill_id | integer | 約定ID |
symbol | string | オプションシンボル |
side | string | 取引サイド(buy または sell) |
price | string | 約定価格(USD) |
size | string | 約定サイズ(契約数) |
timestamp | integer | Unixタイムスタンプ(ミリ秒) |
wallet_address | string | お客様のウォレットアドレス |
fee | string | 課される取引手数料。ローンチ会場の手数料が無効の間は 0 を返します |
trade_id | integer | 一意の取引ID |
is_taker | boolean | お客様がテイカーであったかどうか |
builder_code_address | string? | ビルダーコードウォレット(存在する場合) |
builder_code_fee | string? | ビルダーコード手数料。ローンチ会場の手数料が無効の間は null を返します |
ポートフォリオ更新(認証済み)
ポジション、残高、証拠金、グリークスに関するポートフォリオストリームの更新です。
グリークス更新の例:
{
"type": "PortfolioUpdate",
"timestamp": 1737331200000,
"per_leg": [
{
"symbol": "BTC-20260131-100000-C",
"quantity": "2.0",
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
],
"aggregate": {
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
}
空のポートフォリオの場合、グリークス更新は次を使用します:
per_leg: []aggregate: null
コンペティション損益サマリー(認証済み)
ヘッダー/フッターの損益表示用のコンペティションストリーム更新です。
{
"type": "CompetitionPnlSummary",
"wallet_address": "0x1234...abcd",
"lifetime_realized_pnl": "1250.50",
"active_competition": {
"competition_id": 7,
"competition_name": "Spring Sprint",
"competition_state": "active",
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null
},
"timestamp": 1737331200000
}
アクティブなコンペティションがない場合、active_competition は null です。
注文更新(認証済み)
注文ステータス変更の通知です。
{
"type": "OrderUpdate",
"order_id": 12345,
"client_order_id": "my-order-1",
"status": "filled",
"filled_size": "10.0",
"remaining_size": "0",
"avg_fill_price": "0.0523"
}
マーケット更新
マーケットの上場に関する変更です。
マーケット作成:
{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}
マーケット満期:
{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}
ポジション満期(認証済み)
お客様のポジションが満期で決済された際の通知です。
{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}
清算状態変更(認証済み)
お客様のアカウントの清算状態の変更です。
{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "Normal",
"new_state": "Warning",
"equity": "10000.0",
"mm_required": "9500.0",
"shortfall": "0",
"auction_id": null,
"timestamp": 1737331200000
}
| 状態 | 説明 |
|---|---|
Normal | アカウントは健全です |
Warning | マージンコールに近づいています |
Liquidating | 清算オークションが進行中です |
インデックス価格更新
全原資産のスポット/インデックス価格をバッチ配信します。
{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50"},
{"underlying": "ETH", "price": "3200.00"},
{"underlying": "HYPE", "price": "28.50"}
],
"timestamp": 1737331200000
}
| フィールド | 型 | 説明 |
|---|---|---|
prices | array | 追跡対象の各原資産についての {underlying, price} エントリの配列 |
prices[].underlying | string | 原資産シンボル(例:"BTC"、"ETH") |
prices[].price | string | 現在のスポット/インデックス価格(USD) |
timestamp | integer | Unixタイムスタンプ(ミリ秒) |
参考マーケットデータ
登録済みのクオートプロバイダーからの集約されたベストビッド/アスクを含む、許可リスト方式のクオートプロバイダーストリームです。このチャンネルはまだ一般提供されていません。Hypercallがお客様の連携向けにクオートプロバイダーストリーミングを有効化していない限り、REST マーケットデータおよび認証済みの注文/約定/ポートフォリオチャンネルをご利用ください。
{
"type": "IndicativeMarketData",
"instrument": "BTC-20260131-100000-C",
"best_bid": "0.0520",
"best_ask": "0.0530",
"indicative_bid_size": "50.0",
"indicative_ask_size": "25.0",
"num_providers": 3,
"timestamp": 1737331200000
}
| フィールド | 型 | 説明 |
|---|---|---|
instrument | string | オプションシンボル |
best_bid | string | 集約されたベストビッド価格(任意) |
best_ask | string | 集約されたベストアスク価格(任意) |
bid_iv | number | ベストビッドのインプライド・ボラティリティ(任意) |
ask_iv | number | ベストアスクのインプライド・ボラティリティ(任意) |
indicative_bid_size | string | 全プロバイダーにわたる合計ビッドサイズ(任意) |
indicative_ask_size | string | 全プロバイダーにわたる合計アスクサイズ(任意) |
num_providers | integer | アクティブなクオートプロバイダーの数 |
timestamp | integer | Unixタイムスタンプ(ミリ秒) |
コンペティション順位変更(認証済み)
アクティブなコンペティションでお客様の順位が変動した際の通知です。
{
"type": "CompetitionRankChange",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"from_rank": 15,
"to_rank": 12,
"delta_places": 3,
"pnl": "420.25",
"timestamp": 1737331200000
}
コンペティション差分更新(認証済み)
一つ上の順位までの差です。
{
"type": "CompetitionGapUpdate",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"next_rank": 11,
"gap_metric_value": "50.00",
"timestamp": 1737331200000
}
コンペティション最終順位(認証済み)
コンペティション終了時に、お客様の最終結果とともに送信されます。
{
"type": "CompetitionFinalStanding",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null,
"timestamp": 1737331200000
}
RFQクオート(認証済み)
お客様のRFQ送信に対して受け取ったクオートです。
{
"type": "RfqQuotes",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"quotes": [
{
"quote_id": "660e8400-e29b-41d4-a716-446655440001",
"net_premium": "52.30",
"expires_at": 1737331225000
}
],
"status": "quoted",
"taker_wallet": "0x1234...abcd"
}
RFQステータス更新(認証済み)
お客様が送信したRFQのステータス変更です。
{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}
エラー
サーバーエラーメッセージです。
{
"type": "Error",
"message": "Invalid channel: foobar"
}
認証
認証済みチャンネルでは、接続後にウォレット識別メッセージが必要です:
{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}
認証済みチャンネルのメッセージは、お客様のウォレットのデータのみが表示されるようフィルタリングされます。WebSocket接続に署名は不要です。
例:Pythonクライアント
import asyncio
import websockets
import json
async def main():
uri = "wss://api.hypercall.xyz/ws"
async with websockets.connect(uri) as ws:
# Identify the wallet before subscribing to authenticated channels.
await ws.send(json.dumps({
"type": "Authenticate",
"wallet": "0xYourWallet"
}))
# Subscribe to orderbook
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "orderbook"
}))
# Subscribe to fills for BTC only
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "fills",
"symbols": ["BTC"]
}))
# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")
asyncio.run(main())
例:TypeScriptクライアント
const ws = new WebSocket("wss://api.hypercall.xyz/ws");
ws.onopen = () => {
ws.send(JSON.stringify({ type: "Authenticate", wallet: "0xYourWallet" }));
// Subscribe to channels
ws.send(JSON.stringify({ type: "Subscribe", channel: "orderbook" }));
// Subscribe to order updates filtered to BTC
ws.send(JSON.stringify({
type: "Subscribe",
channel: "order_updates",
symbols: ["BTC"],
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`Received: ${msg.type}`);
if (msg.type === "OrderbookUpdate") {
console.log(`${msg.symbol}: ${msg.bids.length} bids, ${msg.asks.length} asks`);
}
};