このページは機械翻訳されています。英語の原文が正式版です。 英語で読む →
メインコンテンツにスキップ

WebSocket API

Hypercall のオプション取引向けリアルタイムデータストリーミングです。

インタラクティブリファレンス

ライブサンプルやスキーマの詳細を確認しやすい インタラクティブ WebSocket API リファレンス もご覧ください。

機械可読な仕様

プログラムから利用する場合は AsyncAPI 仕様 をダウンロードしてください。

追加型のスキーマ拡張

WebSocket のメッセージオブジェクトには、事前の告知なく新しいフィールドが追加されることがあります。クライアントは認識できないフィールドを無視する必要があります。Hypercall は既存のメッセージスキーマからフィールドを削除しません。

接続​

wss://HOST/ws に接続します。

エンドポイント:

  • 本番環境: wss://api.hypercall.xyz/ws
  • ローカル: ws://localhost:3000/ws
テストネットの状況

Hypercall がテストネット用の HYPE を追加で確保するまで、テストネットは一時的に無効化されています。

圧縮​

/ws は RFC 7692 の permessage-deflate に対応しています。クライアントで有効にすると、マーケットデータの帯域幅を削減できます。本番環境で取得したトラフィックでは、個別に圧縮したフレームで約 45%、インデックス価格のバッチで約 70% サイズが小さくなりました。

  • クライアントはアップグレードリクエストで拡張を提示します。例: Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  • サーバーが受け入れた場合、101 レスポンスに Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover が含まれます。この場合、サーバーの各メッセージは共有スライディングウィンドウを使わずに個別に圧縮され、数百バイト未満のメッセージは引き続き非圧縮で送信されます。展開はライブラリが透過的に行います。
  • レスポンスに Sec-WebSocket-Extensions ヘッダーがない場合、すべてのフレームは非圧縮です。圧縮は環境ごとに有効化されるため、クライアントは両方のケースに対応する必要があります。どちらの場合も JSON メッセージの内容は同一です。本番環境はまだこの拡張を受け入れていないため、現時点で本番環境のフレームは非圧縮です。
  • クライアントは送信するメッセージを圧縮しても構いません。サーバーはクライアントの各メッセージを最大 256 KiB まで展開し、それを超えるメッセージの場合は接続を切断します。

ブラウザは拡張を自動的にネゴシエートします。多くのライブラリでは変更は不要です。

Python(websockets はデフォルトで圧縮を有効にします):

import websockets

async with websockets.connect("wss://api.hypercall.xyz/ws", compression="deflate") as ws:
...

Node.js(ws):

import WebSocket from "ws";

const ws = new WebSocket("wss://api.hypercall.xyz/ws", { perMessageDeflate: true });

Rust: hypercall-client の WsClient はデフォルトで permessage-deflate をネゴシエートします(例: Rust クライアント を参照)。素の tungstenite および tokio-tungstenite はまだこの拡張を実装していないため、非圧縮で接続します。独自のソケットで圧縮を使う場合は、yawc など拡張を実装したクライアントを使用してください。

let url = "wss://api.hypercall.xyz/ws".parse()?;
let mut ws = yawc::WebSocket::connect(url)
.with_options(yawc::Options::default().with_low_latency_compression())
.await?;

ウォレットの識別​

認証が必要なチャネル(注文、約定、ポートフォリオ)でデータを受信するには、接続後に 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安全上限を超えたフレームの配信クラス。
causemessage_limit、byte_limit、message_age、または write_timeout。
recovery次に必要な対応。resubscribe、snapshot_resubscribe、portfolio_refetch、rest_reconcile など。

切断が発生した場合は、再接続し、必要に応じてウォレットを再度識別し、再購読したうえで、新しいイベントを処理する前に現在の状態を照合してください。順序付きの公開チャネルでは、新しいスナップショットが必要です。プライベートなイベントチャネルでは、カーソルによるリプレイがまだ利用できないため、正となる REST API を通じた照合が必要です。完全に停止した接続はクローズ理由を読み取る前に終了することがあるため、クリーンでない切断の場合もクライアントはこの復旧フローを使用する必要があります。

高頻度の公開マーケットデータと、認証が必要なコマンドやプライベートストリームには、別々の接続を使用してください。配信クラスによってメトリクスと復旧時の挙動が決まりますが、同じ接続上のフレームは単一の順序付きソケット書き込み経路を共有します。そのため、公開データの書き込みが停滞すると、書き込み期限により接続が切断されるまで、同じ接続上の後続のプライベートフレームも遅延する可能性があります。

チャネルの購読​

購読するには 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 を指定しない場合、ご自身のウォレットに関するすべての更新が配信されます。

公開チャネルの orderbook、trades、indicative_market_data、indicative_market_data_v2 も symbols を受け付けますが、照合対象は原資産ではなく、銘柄シンボルの完全一致(大文字・小文字を区別しない)です。

{"type": "Subscribe", "channel": "orderbook", "symbols": ["BTC-20260131-100000-C"]}

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"。各銘柄の満期の UTC 暦日と照合されますすべての満期
option_type"call"、"put"、"both"。省略すると両方両方

バッチ配信​

indicative_market_data_v2 は indicative_market_data と同じ行を、1 フレームに複数行まとめて配信します。

{"type": "Subscribe", "channel": "indicative_market_data_v2", "symbols": ["BTC-20260131-100000-C"]}

サーバーはバッチマーカー付きで確認を返します。

{"type": "Subscribed", "channel": "indicative_market_data_v2", "batch": true}

その後、サーバーは各行を最大で 1 バッチウィンドウ(デフォルトは 25 ms)保持し、そのウィンドウ内に発行された行を 1 つの IndicativeMarketDataBatch フレームとして送信します。バッチが 256 行に達した場合は、ウィンドウの終了を待たずに送信されます。

  • 対応状況の確認: "batch": true 付きの確認を受け取った場合にのみ、サーバーがバッチ配信を行っています。このチャネルより前にリリースされたサーバーは、任意のチャネル名に対してマーカーなしで確認を返し、その後何も送信しません。現行のサーバーは未知のチャネルに対して unknown_channel エラー を返します。いずれの場合も、同じ接続上で indicative_market_data_v2 の購読を解除し、indicative_market_data を購読してください。
  • レイテンシ: 行は indicative_market_data よりも最大 1 ウィンドウ分遅れて届きます。デフォルトのウィンドウで本番トラフィックを計測したところ、待機時間は平均 12 ms、最大でも 25 ms でした。個々のクォート更新に数ミリ秒以内で反応する必要がある場合は、v1 チャネルを使用してください。
  • 帯域幅: バッチ化のみでは約 7% のバイト削減にとどまります。大きな削減効果は permessage-deflate と組み合わせた場合に得られます。圧縮したバッチは、非圧縮の 1 行フレームと比べて、フィルタなしの購読で約 9.8 分の 1、単一のオプションチェーンで約 8.3 分の 1 のサイズになります。行を 1 つずつ圧縮した場合は約 1.8 分の 1 です。
  • 順序: updates 内の行は発行順に並び、バッチも順番どおりに届きます。行は統合されないため、同じ銘柄が 1 つのバッチに複数回現れることがあります。行を順に適用すれば、v1 チャネルと同じ状態になります。
  • スナップショット: 購読時のスナップショットもバッチフレームで届きます。
  • フィルタ: symbols は indicative_market_data と同様に機能します。フィルタを絞り込む、または購読を解除すると、旧フィルタのもとで保留中だった行がまず送信され、その後に Unsubscribed の確認が届きます。そのため、行の欠落や重複は発生しません。
  • 独立したチャネル: 1 つの接続で、異なるフィルタを指定して両方のチャネルを購読できます。indicative_market_data に変更はありません。

利用可能なチャネル​

チャネル認証説明
orderbook不要全シンボルの L2 オーダーブック更新
trades不要公開の約定フィード
market_updates不要銘柄の上場状況の変更(作成/削除/満期)
options_chain不要オプションチェーンの差分更新(シンボル、満期、option_type でフィルタ可能)
index_prices不要全原資産のリアルタイムのスポット/インデックス価格
indicative_market_data不要許可リスト制のクォートプロバイダー向けストリーム。一般提供はまだ開始していません
indicative_market_data_v2不要同じストリームをバッチフレームで配信。バッチ配信 を参照
order_updates必要ご自身の注文ステータスの変更(シンボルでフィルタ可能)
fills必要ご自身の約定(シンボルでフィルタ可能)
portfolio必要ご自身のポジションと残高の更新
liquidation必要ご自身の清算状態の変更
rfq必要RFQ のクォート、ステータス更新、約定通知
experimental_order_updates, experimental_combo_fills必要実験的なコンボ用チャネル。実験的コンボ API を参照
experimental_combo_trades不要実験的な公開コンボ約定

コンペティションやリーダーボードのデータは、WebSocket・REST のいずれでも api.hypercall.xyz からは提供されません。廃止済みの competition または competition_engagement チャネルを購読すると Error が返されます。トレーディングアプリは、https://api-ui.hypercall.xyz のアナリティクスサービスから HTTP 経由でコンペティション情報を取得します。例: GET /v2/competitions、GET /v2/competitions/{id}、GET /v2/competitions/leaderboard、GET /v2/competitions/all-time/leaderboard。

メッセージの種類​

注文の発注(認証必須)​

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": 1780000000000,
"signature": "0x..."
}

上記の nonce は説明用の値です。注文ごとに、現在の Unix 時間(ミリ秒)から新しい値を生成してください(例: JavaScript の Date.now())。固定値をコピーして使うと、受付可能な範囲を外れて拒否されます。

フィールド型説明
walletstring注文を保有するウォレットアドレス
symbolstringオプションのシンボル
sidestring"Buy" または "Sell"
sizestring契約サイズ。署名した値と完全に一致する必要があります
pricestring指値価格。署名した値と完全に一致する必要があります
tifstring任意の執行条件(time-in-force)。デフォルトは "gtc"
routestring"book_only" を使用してください。route を省略した場合も引き続き受け付けられますが非推奨であり、廃止予定日はすでに過ぎています。
client_idstring任意のクライアント注文 ID
reduce_onlyboolean任意。デフォルトは false。reduce-only 注文は PlaceOrderReduceOnly に署名し、route を明示的に指定する必要があります
mmp_enabledboolean任意。デフォルトは false
builder_code_addressstring任意のビルダーコード用ウォレット
nonceinteger必須の署名用ノンス。現在の Unix 時間(ミリ秒)を指定します。現在時刻の 2 日前から 1 日後までの範囲内である必要があります。各ノンスは署名者ごとに 1 回のみ受け付けられ、REST と WebSocket の注文は同じノンス空間を共有します。リプレイされたフレームは拒否されます。
signaturestringEIP-712 の PlaceOrder 署名

接続で事前に Authenticate を送信している必要があります。送信していない場合、サーバーは {"type": "Error", "message": "Not authenticated"} を返します。署名者は wallet 本人、またはそのウォレットに承認されたエージェントである必要があります。

WebSocket の PlaceOrder は現在、オーダーブックに直接ディスパッチされます。この経路ではまだ RPI/RFQ ルーティングを実行しないため、WebSocket では route="best_execution" と route="rfq_only" は拒否されます。best_execution を使う場合は POST /order を使用してください。

受け付けられた注文には、同じ接続上で OrderResult が返されます。

{
"type": "OrderResult",
"order_id": 12345,
"status": "ACKED",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"price": "100",
"size": "1"
}

注文が受け付けられなかった場合は reason が追加されます。バリデーション、署名、レート制限によるエラーは、message が Order placement failed: で始まる Error として送信されます。その後のステータス変更は order_updates で届きます。

オーダーブック更新​

シンボルごとの L2 オーダーブックのスナップショット/更新です。

{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"option_token_address": "0x...",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
フィールド型説明
symbolstringオプションのシンボル
option_token_addressstring?オンチェーンのオプショントークンアドレス(判明している場合)
bidsarray[price, size] タプル形式のビッドの板。サイズは人が読める単位の契約数です
asksarray[price, size] タプル形式のアスクの板。サイズは人が読める単位の契約数です
timestampintegerUnix タイムスタンプ(ミリ秒)

約定(公開)​

公開の約定イベントです。

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "Buy",
"timestamp": 1737331200000
}
フィールド型説明
symbolstringオプションのシンボル
pricestringUSD 建ての約定価格
sizestring契約数単位の約定サイズ
sidestringアグレッサー側(Buy または Sell)
timestampintegerUnix タイムスタンプ(ミリ秒)

約定通知(認証必須)​

ご自身の約定に関する通知です。

{
"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,
"builder_code_address": null,
"builder_code_fee": null,
"instrument_type": "option"
}
フィールド型説明
order_idintegerご自身の注文 ID
fill_idinteger約定 ID
symbolstringオプションのシンボル
sidestring取引におけるご自身のサイド(Buy または Sell)
pricestringUSD 建ての約定価格
sizestring契約数単位の約定サイズ
timestampintegerUnix タイムスタンプ(ミリ秒)
wallet_addressstringご自身のウォレットアドレス
feestring課された取引手数料。ローンチ期間中の取引所手数料が無効な間は 0 を返します
trade_idinteger一意の取引 ID
is_takerbooleanご自身がテイカーだったかどうか
builder_code_addressstring?ビルダーコード用ウォレット(ある場合)
builder_code_feestring?ビルダーコード手数料。ローンチ期間中の取引所手数料が無効な間は null を返します
instrument_typestring"option"

ポートフォリオ更新(認証必須)​

portfolio チャネルで、ポジション、残高、証拠金、グリークスについて送信されます。購読時にサーバーは Initial スナップショットを送信し、その後は差分更新を送信します。

各フレームの type は更新の種類です。

更新の種類timestamp 以外のフィールド
Initialpositions
PositionUpdateposition
BalanceUpdatetotal_margin_used
MarginUpdatespan_margin, margin_summary, margin_mode, total_margin_used, available_balance
GreeksUpdateper_leg, aggregate

portfolio フレームの timestamp は、他のチャネルのミリ秒単位のタイムスタンプとは異なり、Unix 秒です。

グリークス更新の例:

{
"type": "GreeksUpdate",
"timestamp": 1737331200,
"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

注文更新(認証必須)​

注文ステータスの変更通知です。PARTIALLY_FILLED の更新も含まれます。 filled_size は、直近の約定数量ではなく、その注文の全約定にわたる累計約定数量です。

{
"type": "OrderUpdate",
"order_id": 12345,
"client_id": "my-order-1",
"request": {
"price": "0.0523",
"size": "10.0",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"tif": "gtc"
},
"status": "PARTIALLY_FILLED",
"filled_size": "0.75",
"timestamp": 1767225600000,
"reason": null,
"wallet_address": "0x0000000000000000000000000000000000000001",
"instrument_type": "option"
}

status は ACKED、OPEN、PARTIALLY_FILLED、FILLED、CANCELED、REJECTED のいずれかです。注文に client_id がない場合は省略されます。instrument_type は "option" または "perp" です。

マーケット更新​

銘柄の上場状況の変更です。

銘柄の作成:

{
"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
}

action は Created、Expired、Deleted(symbol と timestamp のみを含む)、または ComboCreated(実験的コンボ API を参照)のいずれかです。

オプションチェーン更新​

銘柄の上場状況、または最良気配が変化したときに options_chain で送信されます。action は Upsert または Remove です。

{
"type": "OptionsChainUpdate",
"action": "Upsert",
"currency": "BTC",
"expiry": 1769846400,
"row": {
"strike": 100000.0,
"call": {
"symbol": "BTC-20260131-100000-C",
"bid_price_usd": 1520.0,
"ask_price_usd": 1580.0
}
},
"timestamp": 1737331200000
}

Upsert の行には、オプションチェーンのスナップショットと同じレッグフィールドを持つレッグ(call または put)が 1 つ含まれます。フィールドは symbol、option_token_address、ビッドとアスクの価格、IV、契約数単位のサイズと USD 建て想定元本、greeks_abs、greeks_cash です(上記の例は一部を省略しています)。利用できない値は null になり、更新に含まれない側のレッグは省略されます。Remove は、銘柄が削除された場合、満期を迎えた場合、または決済待ちになった場合に送信され、currency、expiry、strike、option_type、symbol、timestamp を含みます。expiry は Unix 秒です。

ポジションの満期(認証必須)​

ご自身のポジションが満期で決済されたときに portfolio チャネルで送信されます。

{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"settlement_entry_price": "100.0",
"cost_basis": "1000.0",
"net_pnl": "-500.0",
"timestamp": 1738281600000
}

settlement_entry_price、cost_basis、net_pnl は、利用できない場合 null になります。

清算状態の変更(認証必須)​

アカウントの清算状態が変化したときに liquidation チャネルで送信されます。

{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "healthy",
"new_state": "pre_liquidation",
"liquidation_mode": "partial",
"margin_mode": "standard",
"equity": "10000.0",
"mm_required": "10500.0",
"maintenance_margin": "-500.0",
"shortfall": "500.0",
"partial_liquidation": { "...": "..." },
"full_liquidation": null,
"timestamp": 1737331200000
}
フィールド説明
previous_state, new_statehealthy、pre_liquidation、in_liquidation、liquidated のいずれか
liquidation_modepartial、full、または清算フローが進行していない場合は null
margin_modestandard または portfolio
equityアカウントの純資産
mm_required維持証拠金要件
maintenance_margin純資産から維持証拠金要件を差し引いた額
shortfallアカウントが維持証拠金を下回っている額
partial_liquidation部分清算の進捗(開始時刻、目標純資産、エスカレーション期限、有効な清算注文、ボーナス)、または null
full_liquidation全額清算オークションの詳細(オークション ID、開始時刻、必要証拠金、完了時には落札者、ボーナス、解決トランザクション)、または null

各状態の意味については 清算 を参照してください。

インデックス価格更新​

全原資産のスポット/インデックス価格をまとめて配信します。

{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50", "timestamp": 1737331200000},
{"underlying": "ETH", "price": "3200.00", "timestamp": 1737331199980},
{"underlying": "NVDA", "price": "182.40", "timestamp": 1737331199950}
],
"timestamp": 1737331199950
}
フィールド型説明
pricesarray追跡中の各原資産について {underlying, price, timestamp} を持つエントリの配列
prices[].underlyingstring原資産のシンボル(例: "BTC"、"ETH")
prices[].pricestringUSD 建ての現在のスポット/インデックス価格
prices[].timestampintegerこの原資産のソース観測時刻(Unix ミリ秒)
timestampintegerprices に含まれるソース観測時刻のうち最も古いもの(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,
"published_at": 1737331200004,
"timestamp": 1737331200000
}
フィールド型説明
instrumentstringオプションのシンボル
best_bidstring任意。集約された最良ビッド価格
best_askstring任意。集約された最良アスク価格
bid_ivnumber任意。最良ビッドのインプライド・ボラティリティ
ask_ivnumber任意。最良アスクのインプライド・ボラティリティ
indicative_bid_sizestring任意。全プロバイダー合計のビッドサイズ
indicative_ask_sizestring任意。全プロバイダー合計のアスクサイズ
num_providersintegerアクティブなクォートプロバイダーの数
rfq_provider_quotesarray任意。プロバイダーごとのクォート: wallet、bid_price、ask_price、max_bid_size、max_ask_size、updated_at
published_atintegerこの行が発行された API クロック上の時刻(Unix ミリ秒)。rfq_provider_quotes の経過時間は、ローカルの時計ではなくこの値を基準に計測してください
timestampinteger最新のプロバイダークォートの時刻(Unix ミリ秒)

インディカティブ・マーケットデータ・バッチ​

indicative_market_data_v2 チャネルで送信されます(バッチ配信 を参照)。updates の各要素は、type を除いて IndicativeMarketData メッセージと同じフィールドを持ちます。

{
"type": "IndicativeMarketDataBatch",
"flushed_at": 1737331200025,
"updates": [
{
"instrument": "BTC-20260131-100000-C",
"best_bid": "0.0520",
"best_ask": "0.0530",
"num_providers": 3,
"published_at": 1737331200004,
"timestamp": 1737331200000
},
{
"instrument": "BTC-20260131-105000-C",
"best_bid": "0.0310",
"best_ask": "0.0322",
"num_providers": 2,
"published_at": 1737331200004,
"timestamp": 1737331200001
}
]
}
フィールド型説明
flushed_atintegerバッチが送信された API クロック上の時刻(Unix ミリ秒)。flushed_at - published_at が各行のバッチ化による遅延です
updatesarrayウィンドウ内に発行された行(古い順)

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"
}

クロック同期​

任意の nonce 文字列を付けて ClockSync を送信すると、同じ接続上で API クロックのサンプルを取得できます。たとえば、伝送遅延の上限を見積もる際に利用できます。

{"type": "ClockSync", "nonce": "abc"}
{"type": "ClockSynced", "nonce": "abc", "server_at": 1737331200000}

server_at は Unix ミリ秒です。認証は不要です。

エラー​

サーバーのエラーメッセージです。code がある場合は、message ではなく code で判定してください。

{
"type": "Error",
"message": "Unknown channel 'foobar'",
"code": "unknown_channel",
"channel": "foobar"
}
フィールド型説明
messagestring人が読める形式の説明
codestring任意。安定した理由コード。unknown_channel: Subscribe で存在しないチャネルが指定されました
channelstring任意。拒否された Subscribe で指定されたチャネル

利用可能なチャネル に記載されていないチャネルへの Subscribe には unknown_channel エラーが返され、購読は作成されません。以前のサーバーは任意の名前に対して確認を返し、その後何も送信していませんでした。

その他のエラーは message のみを含みます。例: Authenticate の前に認証が必要なチャネルを購読した場合の Authentication required for this channel、Authenticate の前に PlaceOrder を送信した場合の Not authenticated、および Invalid wallet address: ...。

認証​

認証が必要なチャネルでは、接続後にウォレット識別メッセージを送信する必要があります。

{"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`);
}
};

例: Rust クライアント​

hypercall-client クレートの WsClient は、ウォレットの識別、再接続後の購読の復元、サーバーからの ping への応答を自動で行います。デフォルトで permessage-deflate 圧縮を提示し、サーバーが受け入れない場合は非圧縮フレームにフォールバックします。どちらの場合も JSON メッセージは同一です。提示を止めるには with_permessage_deflate(false) を呼び出してください。

use hypercall_client::WsClient;

#[tokio::main]
async fn main() -> hypercall_client::Result<()> {
let ws = WsClient::new();
ws.connect("https://api.hypercall.xyz", None).await?;
ws.subscribe(vec!["orderbook", "index_prices"]).await?;

if let Some(msg) = ws.wait_for_message(|_| true, 5_000).await {
println!("Received: {msg:?}");
}
Ok(())
}