Diese Seite wurde maschinell übersetzt. Das englische Original ist maßgeblich. Auf Englisch lesen →
Zum Hauptinhalt springen

WebSocket-API

Echtzeit-Datenstreaming für den Optionshandel auf Hypercall.

Interaktive Referenz

Nutzen Sie die interaktive WebSocket-API-Referenz für eine komfortablere Übersicht mit Live-Beispielen und Schemadetails.

Maschinenlesbare Spezifikation

Laden Sie die AsyncAPI-Spezifikation für die programmatische Nutzung herunter.

Additive Schemaentwicklung

WebSocket-Nachrichtenobjekte können ohne Vorankündigung neue Felder erhalten. Clients müssen Felder ignorieren, die sie nicht kennen. Hypercall entfernt keine Felder aus einem bestehenden Nachrichtenschema.

Verbindung​

Verbinden Sie sich mit wss://HOST/ws:

Endpunkte:

  • Produktion: wss://api.hypercall.xyz/ws
  • Lokal: ws://localhost:3000/ws
Testnet-Status

Das Testnet ist vorübergehend deaktiviert, bis Hypercall weiteres Testnet-HYPE erhält.

Komprimierung​

/ws unterstützt RFC 7692 permessage-deflate. Aktivieren Sie es in Ihrem Client, um die Bandbreite für Marktdaten zu senken: Bei aufgezeichnetem Produktionsverkehr sind einzeln komprimierte Frames etwa 45 % kleiner, Batches von Indexpreisen etwa 70 % kleiner.

  • Ihr Client bietet die Erweiterung im Upgrade-Request an, zum Beispiel Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits.
  • Akzeptiert der Server, enthält die 101-Antwort Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover. Jede Servernachricht wird dann einzeln komprimiert, ohne gemeinsames Sliding Window, und Nachrichten unter einigen hundert Bytes werden weiterhin unkomprimiert gesendet. Ihre Bibliothek dekomprimiert transparent.
  • Enthält die Antwort keinen Sec-WebSocket-Extensions-Header, ist jeder Frame unkomprimiert. Die Komprimierung wird pro Umgebung aktiviert, daher müssen Clients beide Fälle behandeln; die JSON-Nachrichten sind in beiden Fällen identisch. Die Produktion akzeptiert die Erweiterung noch nicht, daher sind Produktions-Frames derzeit unkomprimiert.
  • Ihr Client darf gesendete Nachrichten komprimieren. Der Server dekomprimiert jede Client-Nachricht bis zu 256 KiB und schließt die Verbindung, wenn eine Nachricht diese Grenze überschreiten würde.

Browser handeln die Erweiterung automatisch aus. Die meisten Bibliotheken benötigen keine Änderung:

Python (websockets aktiviert die Komprimierung standardmäßig):

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: Der WsClient aus hypercall-client handelt permessage-deflate standardmäßig aus (siehe Beispiel: Rust-Client). Reines tungstenite und tokio-tungstenite implementieren es noch nicht und verbinden sich daher unkomprimiert. Für Komprimierung mit Ihrem eigenen Socket verwenden Sie einen Client, der sie implementiert, etwa 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?;

Wallet-Identifizierung​

Um Daten auf authentifizierten Kanälen (Orders, Fills, Portfolio) zu empfangen, identifizieren Sie Ihre Wallet nach dem Verbindungsaufbau mit einer Authenticate-Nachricht:

{"type": "Authenticate", "wallet": "0x1234..."}

Der Server antwortet mit einer Bestätigung:

{"type": "Authenticated", "wallet": "0x1234..."}

Nach Erhalt von Authenticated können Sie authentifizierte Kanäle abonnieren. Ist die Wallet-Adresse ungültig, antwortet der Server mit einer Error-Nachricht, und die Verbindung bleibt offen.

Veraltet: Authentifizierung per Query-Parameter

Der Query-Parameter ?wallet= wird aus Gründen der Abwärtskompatibilität weiterhin unterstützt, ist aber veraltet und wird in einem künftigen Release entfernt. Verwenden Sie bevorzugt den oben beschriebenen nachrichtenbasierten Ansatz.

Verbindungs-Liveness​

Der Server erzwingt einen WebSocket-Heartbeat:

  • Sendet alle 20 Sekunden einen Ping-Kontroll-Frame
  • Erwartet innerhalb von 60 Sekunden ein passendes Pong
  • Schließt die Verbindung mit Close-Code 1008 und Grund pong timeout, wenn der Client nicht mehr antwortet

WebSocket-Implementierungen im Browser verarbeiten Ping/Pong automatisch. Viele Rust-WebSocket-Bibliotheken, darunter tungstenite und tokio-tungstenite, übernehmen Ping/Pong auf Kontroll-Frame-Ebene ebenfalls für Sie. Prüfen Sie die Dokumentation Ihrer Client-Bibliothek, bevor Sie eine manuelle Pong-Behandlung hinzufügen. Eigene oder rohe Socket-Implementierungen müssen auf Ping-Frames mit Pong antworten.

Wiederherstellung bei langsamen Konsumenten​

Der Server schließt eine /ws-Verbindung, die ausgehende Daten nicht innerhalb der konfigurierten Sicherheitsgrenzen für Nachrichtenanzahl, kodierte Bytes, Warteschlangenalter oder Socket-Schreibzeit abarbeiten kann. Kann die Verbindung noch einen Close-Frame annehmen, verwendet der Server den Code 1008 und einen kompakten JSON-Grund:

{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}

Die Felder des Grunds sind:

FeldBedeutung
classZustellklasse, deren Frame die Sicherheitsgrenze überschritten hat.
causemessage_limit, byte_limit, message_age oder write_timeout.
recoveryErforderliche nächste Aktion, etwa resubscribe, snapshot_resubscribe, portfolio_refetch oder rest_reconcile.

Nach jedem Verbindungsabbruch verbinden Sie sich neu, identifizieren die Wallet bei Bedarf erneut, abonnieren erneut und gleichen den aktuellen Zustand ab, bevor Sie neue Ereignisse verarbeiten. Geordnete öffentliche Kanäle erfordern einen frischen Snapshot. Private Ereigniskanäle erfordern einen Abgleich über die maßgebliche REST-Schnittstelle, da ein Cursor-Replay noch nicht verfügbar ist. Eine vollständig blockierte Verbindung kann beendet werden, bevor sie den Close-Grund lesen kann. Clients müssen diesen Wiederherstellungsablauf daher auch bei einem unsauberen Verbindungsende anwenden.

Verwenden Sie getrennte Verbindungen für öffentliche Marktdaten mit hoher Rate und für authentifizierte Befehle oder private Streams. Zustellklassen bestimmen Metriken und Wiederherstellungsverhalten, aber Frames auf einer Verbindung teilen sich weiterhin einen geordneten Socket-Schreibpfad. Ein blockierter öffentlicher Schreibvorgang kann daher nachfolgende private Frames auf derselben Verbindung verzögern, bis die Schreibfrist die Verbindung schließt.

Kanäle abonnieren​

Senden Sie zum Abonnieren eine JSON-Nachricht:

{"type": "Subscribe", "channel": "orderbook"}

Zum Abbestellen:

{"type": "Unsubscribe", "channel": "orderbook"}

Sie erhalten eine Bestätigung:

{"type": "Subscribed", "channel": "orderbook"}

Symbolfilterung​

Die Kanäle order_updates und fills unterstützen einen optionalen symbols-Filter. Ist er angegeben, sendet der Server nur Nachrichten, deren Basiswert einem der angegebenen Symbole entspricht.

{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}

Sowohl reine Basiswerte ("BTC") als auch vollständige Instrumentennamen ("BTC-20260131-100000-C") werden akzeptiert. Um weitere Symbole hinzuzufügen, senden Sie ein weiteres Subscribe. Um bestimmte Symbole zu entfernen:

{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}

Sind keine symbols angegeben, werden alle Updates für Ihre Wallet weitergeleitet.

Die öffentlichen Kanäle orderbook, trades, indicative_market_data und indicative_market_data_v2 akzeptieren ebenfalls symbols. Der Abgleich erfolgt gegen exakte Instrumentensymbole (ohne Beachtung der Groß- und Kleinschreibung), nicht gegen Basiswerte:

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

Ohne symbols liefern diese Kanäle alle Instrumente.

Filterung der Optionskette​

Der Kanal options_chain unterstützt die Filterung nach Instrumentensymbolen, Verfallsdatum und Optionstyp:

{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
FilterWerteStandard
symbolsArray vollständiger Instrumentensymbole (z. B. ["BTC-20260131-100000-C"])Alle Instrumente
expiryDatumsstring "YYYY-MM-DD", abgeglichen mit dem UTC-Kalenderdatum des Verfalls jedes InstrumentsAlle Verfallstermine
option_type"call", "put", "both" oder weglassen für beideBeide

Gebündelte Zustellung​

indicative_market_data_v2 überträgt dieselben Zeilen wie indicative_market_data, jedoch mehrere Zeilen pro Frame:

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

Der Server bestätigt mit einer Batch-Markierung:

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

Anschließend hält er jede Zeile höchstens ein Batch-Fenster lang zurück, standardmäßig 25 ms, und sendet die in diesem Fenster veröffentlichten Zeilen als einen IndicativeMarketDataBatch-Frame. Ein Batch wird außerdem vorzeitig gesendet, sobald er 256 Zeilen erreicht.

  • Unterstützung erkennen: Nur eine Bestätigung mit "batch": true bedeutet, dass der Server bündelt. Server, die vor diesem Kanal veröffentlicht wurden, bestätigen jeden Kanalnamen ohne die Markierung und senden dann nichts, und aktuelle Server beantworten einen unbekannten Kanal mit einem unknown_channel-Fehler. In beiden Fällen bestellen Sie indicative_market_data_v2 ab und abonnieren indicative_market_data auf derselben Verbindung.
  • Latenz: Eine Zeile kommt bis zu ein Fenster später an als auf indicative_market_data. Bei Produktionsverkehr mit dem Standardfenster warteten Zeilen im Durchschnitt 12 ms und nie länger als 25 ms. Verwenden Sie den v1-Kanal, wenn Sie innerhalb von Millisekunden auf einzelne Quote-Updates reagieren.
  • Bandbreite: Bündelung allein spart etwa 7 % der Bytes. Die große Ersparnis ergibt sich mit permessage-deflate: Komprimierte Batches sind bei einem ungefilterten Abonnement etwa 9,8-mal kleiner als unkomprimierte Ein-Zeilen-Frames und bei einer einzelnen Optionskette etwa 8,3-mal kleiner, gegenüber etwa 1,8-mal bei einzeln komprimierten Zeilen.
  • Reihenfolge: Zeilen in updates stehen in Veröffentlichungsreihenfolge, und Batches kommen in Reihenfolge an. Zeilen werden nicht zusammengefasst, sodass ein Instrument mehrmals in einem Batch vorkommen kann. Wenden Sie die Zeilen der Reihe nach an, erreichen Sie denselben Zustand wie auf dem v1-Kanal.
  • Snapshot: Der Snapshot beim Abonnieren kommt ebenfalls als Batch-Frames an.
  • Filter: symbols funktioniert wie bei indicative_market_data. Beim Einschränken des Filters oder beim Abbestellen werden zunächst alle unter dem alten Filter noch ausstehenden Zeilen gesendet, dann die Unsubscribed-Bestätigung, sodass keine Zeile verloren geht oder doppelt ankommt.
  • Unabhängige Kanäle: Eine Verbindung kann beide Kanäle mit unterschiedlichen Filtern abonnieren. indicative_market_data bleibt unverändert.

Verfügbare Kanäle​

KanalAuthentifizierung erforderlichBeschreibung
orderbookNeinL2-Orderbuch-Updates für alle Symbole
tradesNeinÖffentlicher Trade-Feed
market_updatesNeinÄnderungen an Marktlistings (erstellt/gelöscht/verfallen)
options_chainNeinInkrementelle Updates der Optionskette (filterbar nach symbols, expiry, option_type)
index_pricesNeinSpot-/Indexpreise in Echtzeit für alle Basiswerte
indicative_market_dataNeinStream für freigeschaltete Quote-Provider. Noch nicht allgemein verfügbar
indicative_market_data_v2NeinDerselbe Stream in Batch-Frames. Siehe Gebündelte Zustellung
order_updatesJaStatusänderungen Ihrer Orders (filterbar nach Symbol)
fillsJaIhre Trade-Fills (filterbar nach Symbol)
portfolioJaUpdates Ihrer Positionen und Salden
liquidationJaÄnderungen Ihres Liquidationsstatus
rfqJaRFQ-Quotes, Status-Updates und Fill-Benachrichtigungen
experimental_order_updates, experimental_combo_fillsJaExperimentelle Combo-Kanäle. Siehe Experimentelle Combo-API
experimental_combo_tradesNeinExperimentelle öffentliche Combo-Trades

Wettbewerbs- und Leaderboard-Daten werden nicht von api.hypercall.xyz bereitgestellt, weder über WebSocket noch über REST. Das Abonnieren der eingestellten Kanäle competition oder competition_engagement liefert einen Error. Die Trading-App liest Wettbewerbe per HTTP vom Analytics-Dienst unter https://api-ui.hypercall.xyz, zum Beispiel GET /v2/competitions, GET /v2/competitions/{id}, GET /v2/competitions/leaderboard und GET /v2/competitions/all-time/leaderboard.

Nachrichtentypen​

Order platzieren (authentifiziert)​

Platzieren Sie eine Order über den WebSocket-Befehlspfad.

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

Die obige nonce dient nur zur Veranschaulichung. Erzeugen Sie für jede Order eine neue aus der aktuellen Unix-Zeit in Millisekunden, zum Beispiel Date.now() in JavaScript. Ein kopierter fester Wert liegt außerhalb des zulässigen Fensters und wird abgelehnt.

FeldTypBeschreibung
walletstringWallet-Adresse, der die Order gehört
symbolstringOptionssymbol
sidestring"Buy" oder "Sell"
sizestringKontraktgröße, exakt identisch mit dem signierten Wert
pricestringLimitpreis, exakt identisch mit dem signierten Wert
tifstringOptionale Time-in-Force, Standard ist "gtc"
routestringVerwenden Sie "book_only". Eine weggelassene Route wird weiterhin akzeptiert, ist aber veraltet, und ihr Abschaltdatum ist bereits verstrichen.
client_idstringOptionale Client-Order-ID
reduce_onlybooleanOptional, Standard false. Eine Reduce-only-Order signiert PlaceOrderReduceOnly und erfordert eine explizite route
mmp_enabledbooleanOptional, Standard false
builder_code_addressstringOptionale Builder-Code-Wallet
nonceintegerErforderliche Signatur-Nonce: die aktuelle Unix-Zeit in Millisekunden. Sie muss zwischen zwei Tagen vor und einem Tag nach der aktuellen Zeit liegen. Jede Nonce wird pro Signer nur einmal akzeptiert, und REST- und WebSocket-Orders teilen sich denselben Nonce-Raum. Ein wiederholt gesendeter Frame wird abgelehnt.
signaturestringEIP-712-PlaceOrder-Signatur

Die Verbindung muss zuvor Authenticate gesendet haben; andernfalls antwortet der Server mit {"type": "Error", "message": "Not authenticated"}. Der Signer muss wallet oder ein dafür genehmigter Agent sein.

WebSocket-PlaceOrder leitet derzeit direkt an das Orderbuch weiter. route="best_execution" und route="rfq_only" werden über WebSocket abgelehnt, da dieser Pfad noch kein RPI/RFQ-Routing ausführt. Verwenden Sie POST /order für best_execution.

Eine angenommene Order wird auf derselben Verbindung mit einem OrderResult beantwortet:

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

reason wird ergänzt, wenn die Order nicht angenommen wird. Validierungs-, Signatur- und Rate-Limit-Fehler werden als Error gesendet, dessen message mit Order placement failed: beginnt. Nachfolgende Statusänderungen kommen über order_updates.

Orderbuch-Update​

L2-Orderbuch-Snapshot/-Update für ein Symbol.

{
"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
}
FeldTypBeschreibung
symbolstringOptionssymbol
option_token_addressstring?On-Chain-Adresse des Options-Tokens, sofern bekannt
bidsarrayBid-Level als [price, size]-Tupel, die Größe ist in lesbaren Kontrakten angegeben
asksarrayAsk-Level als [price, size]-Tupel, die Größe ist in lesbaren Kontrakten angegeben
timestampintegerUnix-Zeitstempel (Millisekunden)

Trade​

Öffentliches Trade-Ereignis.

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "Buy",
"timestamp": 1737331200000
}
FeldTypBeschreibung
symbolstringOptionssymbol
pricestringTrade-Preis in USD
sizestringTrade-Größe in Kontrakten
sidestringSeite des Aggressors (Buy oder Sell)
timestampintegerUnix-Zeitstempel (Millisekunden)

Fill (authentifiziert)​

Benachrichtigung über Ihren Trade-Fill.

{
"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"
}
FeldTypBeschreibung
order_idintegerIhre Order-ID
fill_idintegerFill-ID
symbolstringOptionssymbol
sidestringIhre Seite des Trades (Buy oder Sell)
pricestringFill-Preis in USD
sizestringFill-Größe in Kontrakten
timestampintegerUnix-Zeitstempel (Millisekunden)
wallet_addressstringIhre Wallet-Adresse
feestringBerechnete Handelsgebühr. Liefert 0, solange die Venue-Gebühren zum Launch deaktiviert sind
trade_idintegerEindeutige Trade-ID
is_takerbooleanOb Sie der Taker waren
builder_code_addressstring?Builder-Code-Wallet (falls vorhanden)
builder_code_feestring?Builder-Code-Gebühr. Liefert null, solange die Venue-Gebühren zum Launch deaktiviert sind
instrument_typestring"option"

Portfolio-Update (authentifiziert)​

Wird auf dem Kanal portfolio für Positionen, Salden, Margin und Greeks gesendet. Beim Abonnieren sendet der Server einen Initial-Snapshot, danach inkrementelle Updates.

Das type jedes Frames ist seine Update-Art:

Update-ArtFelder neben timestamp
Initialpositions
PositionUpdateposition
BalanceUpdatetotal_margin_used
MarginUpdatespan_margin, margin_summary, margin_mode, total_margin_used, available_balance
GreeksUpdateper_leg, aggregate

timestamp ist bei portfolio-Frames in Unix-Sekunden angegeben, anders als die Millisekunden-Zeitstempel auf anderen Kanälen.

Beispiel für ein Greeks-Update:

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

Bei leeren Portfolios verwenden Greeks-Updates:

  • per_leg: []
  • aggregate: null

Order-Update (authentifiziert)​

Benachrichtigung über eine Statusänderung einer Order. PARTIALLY_FILLED-Updates sind enthalten. filled_size ist die kumulierte ausgeführte Menge über alle Ausführungen der Order, nicht die Menge des letzten Fills.

{
"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 ist einer der Werte ACKED, OPEN, PARTIALLY_FILLED, FILLED, CANCELED oder REJECTED. client_id wird weggelassen, wenn die Order keine hat. instrument_type ist "option" oder "perp".

Markt-Update​

Änderungen an Marktlistings.

Markt erstellt:

{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}

Markt verfallen:

{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}

action ist Created, Expired, Deleted (enthält nur symbol und timestamp) oder ComboCreated (siehe Experimentelle Combo-API).

Optionsketten-Update​

Wird auf options_chain gesendet, wenn sich ein Listing oder dessen Top of Book ändert. action ist Upsert oder 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
}

Eine Upsert-Zeile enthält ein Leg (call oder put) mit den Leg-Feldern des Optionsketten-Snapshots: symbol, option_token_address, Bid- und Ask-Preis, IV, Größe in Kontrakten und USD-Nominalwert, greeks_abs und greeks_cash (das obige Beispiel ist gekürzt). Nicht verfügbare Werte sind null; das Leg, das nicht Teil des Updates ist, wird weggelassen. Ein Remove enthält currency, expiry, strike, option_type, symbol und timestamp, wenn ein Instrument gelöscht wird, verfällt oder in das ausstehende Settlement übergeht. expiry ist in Unix-Sekunden angegeben.

Position verfallen (authentifiziert)​

Wird auf dem Kanal portfolio gesendet, wenn Ihre Position beim Verfall abgerechnet wird.

{
"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 und net_pnl sind null, wenn sie nicht verfügbar sind.

Änderung des Liquidationsstatus (authentifiziert)​

Wird auf dem Kanal liquidation gesendet, wenn sich der Liquidationsstatus Ihres Kontos ändert.

{
"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
}
FeldBeschreibung
previous_state, new_statehealthy, pre_liquidation, in_liquidation oder liquidated
liquidation_modepartial, full oder null, wenn kein Liquidationsablauf aktiv ist
margin_modestandard oder portfolio
equityKontoeigenkapital
mm_requiredMaintenance-Margin-Anforderung
maintenance_marginEigenkapital abzüglich der Maintenance-Margin-Anforderung
shortfallBetrag, um den das Konto unter der Maintenance Margin liegt
partial_liquidationFortschritt der Teilliquidation (Eintrittszeit, Ziel-Eigenkapital, Eskalationsfrist, aktive Liquidationsorders, Bonus) oder null
full_liquidationDetails der Auktion bei vollständiger Liquidation (Auktions-ID, Startzeit, benötigte Margin und nach Abschluss der Gewinner, Bonus und die Auflösungstransaktion) oder null

Unter Liquidation erfahren Sie, was jeder Status bedeutet.

Indexpreis-Update​

Gebündelte Spot-/Indexpreise für alle Basiswerte.

{
"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
}
FeldTypBeschreibung
pricesarrayArray von {underlying, price, timestamp}-Einträgen für jeden erfassten Basiswert
prices[].underlyingstringSymbol des Basiswerts (z. B. "BTC", "ETH")
prices[].pricestringAktueller Spot-/Indexpreis in USD
prices[].timestampintegerBeobachtungszeit der Quelle für diesen Basiswert, in Unix-Millisekunden
timestampintegerÄlteste in prices enthaltene Beobachtungszeit der Quelle, in Unix-Millisekunden

Indikative Marktdaten​

Stream für freigeschaltete Quote-Provider mit aggregiertem besten Bid/Ask registrierter Quote-Provider. Dieser Kanal ist noch nicht allgemein verfügbar. Verwenden Sie REST-Marktdaten und die authentifizierten Order-/Fill-/Portfolio-Kanäle, sofern Hypercall das Quote-Provider-Streaming für Ihre Integration nicht aktiviert hat.

{
"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
}
FeldTypBeschreibung
instrumentstringOptionssymbol
best_bidstringOptional, bester aggregierter Bid-Preis
best_askstringOptional, bester aggregierter Ask-Preis
bid_ivnumberOptional, implizite Volatilität des besten Bids
ask_ivnumberOptional, implizite Volatilität des besten Asks
indicative_bid_sizestringOptional, gesamte Bid-Größe über alle Provider
indicative_ask_sizestringOptional, gesamte Ask-Größe über alle Provider
num_providersintegerAnzahl aktiver Quote-Provider
rfq_provider_quotesarrayOptional, Quotes pro Provider: wallet, bid_price, ask_price, max_bid_size, max_ask_size, updated_at
published_atintegerZeitpunkt der Veröffentlichung dieser Zeile laut API-Uhr, in Unix-Millisekunden. Messen Sie das Alter von rfq_provider_quotes daran, nicht an Ihrer lokalen Uhr
timestampintegerZeitpunkt des letzten Provider-Quotes, in Unix-Millisekunden

Indikative Marktdaten im Batch​

Wird auf dem Kanal indicative_market_data_v2 gesendet (siehe Gebündelte Zustellung). Jedes Element von updates hat dieselben Felder wie eine IndicativeMarketData-Nachricht, ohne type.

{
"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
}
]
}
FeldTypBeschreibung
flushed_atintegerZeitpunkt des Versands des Batches laut API-Uhr, in Unix-Millisekunden. flushed_at - published_at ist die Bündelungsverzögerung einer Zeile
updatesarrayIm Fenster veröffentlichte Zeilen, älteste zuerst

RFQ-Quotes (authentifiziert)​

Quotes, die als Antwort auf Ihre RFQ-Anfrage eingehen.

{
"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-Status-Update (authentifiziert)​

Statusänderung für eine von Ihnen eingereichte RFQ.

{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}

Uhrensynchronisation​

Senden Sie ClockSync mit einem beliebigen nonce-String, um auf derselben Verbindung eine Stichprobe der API-Uhr zu erhalten, zum Beispiel um die Übertragungsverzögerung einzugrenzen:

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

server_at ist in Unix-Millisekunden angegeben. Eine Authentifizierung ist nicht erforderlich.

Fehler​

Fehlermeldung des Servers. Werten Sie code aus, sofern vorhanden, nicht message.

{
"type": "Error",
"message": "Unknown channel 'foobar'",
"code": "unknown_channel",
"channel": "foobar"
}
FeldTypBeschreibung
messagestringLesbare Beschreibung
codestringOptionaler stabiler Grund. unknown_channel: Ein Subscribe nannte einen Kanal, der nicht existiert
channelstringOptional. Der Kanal, den ein abgelehntes Subscribe nannte

Ein Subscribe auf einen Kanal, der nicht unter Verfügbare Kanäle aufgeführt ist, wird mit dem Fehler unknown_channel beantwortet, und es wird kein Abonnement angelegt. Frühere Server bestätigten jeden Namen und sendeten dann nichts.

Andere Fehler enthalten nur message. Beispiele: Authentication required for this channel, wenn Sie einen authentifizierten Kanal vor Authenticate abonnieren, Not authenticated für PlaceOrder vor Authenticate sowie Invalid wallet address: ....

Authentifizierung​

Authentifizierte Kanäle erfordern nach dem Verbindungsaufbau eine Nachricht zur Wallet-Identifizierung:

{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}

Nachrichten auf authentifizierten Kanälen werden so gefiltert, dass nur Daten Ihrer Wallet angezeigt werden. Für WebSocket-Verbindungen ist keine Signatur erforderlich.

Beispiel: Python-Client​

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())

Beispiel: TypeScript-Client​

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

Beispiel: Rust-Client​

Der WsClient des Crates hypercall-client identifiziert die Wallet, stellt Abonnements nach einem Reconnect wieder her und beantwortet Server-Pings für Sie. Er bietet standardmäßig permessage-deflate-Komprimierung an und fällt auf unkomprimierte Frames zurück, wenn der Server sie nicht akzeptiert, mit denselben JSON-Nachrichten in beiden Fällen. Rufen Sie with_permessage_deflate(false) auf, um das Angebot abzuschalten.

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(())
}