{"asyncapi":"2.6.0","info":{"title":"Broker WebSocket Streams API","version":"1.0.0","description":"Real-time WebSocket streams for order updates and market data.\n\nAuthentication:\n  - Keyed BLAKE2b-256 signature via HTTP headers during WebSocket Upgrade:\n    * PRE-ACCESS-KEY — broker access key identifier (unique API key)\n    * PRE-ACCESS-TIMESTAMP — RFC3339 timestamp with milliseconds (e.g., 2025-10-30T06:00:34.075Z)\n    * PRE-ACCESS-SIGNATURE — Keyed BLAKE2b-256 hex lowercase (64 chars)\n  - Signature computed over (each line ends with \\n):\n    1. \"GET\\n\"\n    2. path + query string + \"\\n\"\n    3. timestamp + \"\\n\"\n    4. \"\" (empty idempotency_key for WebSocket) + \"\\n\"\n    5. broker_id + \"\\n\"\n    6. access_key + \"\\n\"\n    7. body_digest (BLAKE2b-256 of empty body = hash of \"\")\n  - Keyed BLAKE2b-256 is computed using secret_key associated with the access_key\n  - The function returns 32 bytes, encoded as hex lowercase (64 chars) for PRE-ACCESS-SIGNATURE.\n  - Timestamp must be within clock_skew_tolerance (default 5m)\n  - Invalid signature or timestamp → HTTP 401 or WS close 4401\n\nGeneral Principles:\n  - All data frames include monotonic sequence numbers for ordering/gap detection\n  - Heartbeat frames do not advance sequence numbers\n  - Resume capability via 'since' parameter where applicable ('since' must be \u003e0; value 0 is treated as absent)\n  - Idempotent frame delivery (clients drop frames with seq \u003c= last_applied)\n"},"servers":{"production":{"url":"wss://api.example.com/v1/stream","protocol":"wss","description":"Production WebSocket endpoint"},"sandbox":{"url":"wss://sandbox.api.example.com/v1/stream","protocol":"wss","description":"Sandbox WebSocket endpoint"}},"channels":{"/orders":{"subscribe":{"summary":"Receive real-time order updates","description":"Real-time order updates stream with resume capability.\n\nQuery Parameters:\n  - since=\u0026lt;uint64\u0026gt;   Last applied seq for resume (optional; must be \u003e0; absent or 0 → start from live tail)\n  - market=\u0026lt;id\u0026gt;      Repeatable; filter by market_id\n  - account_id=\u0026lt;id\u0026gt;  Repeatable; filter by account_id\n\nResume Semantics:\n  1. Client connects with since=S (last applied seq)\n  2. Server replays frames with seq \u003e= S in order\n  3. Sends backlog_end (last_seq = current max)\n  4. Continues live streaming\n  If S \u003e current max → immediate live (no backlog)\n  If S too old (retention gap) → error frame (code=resume_too_old) then close (4009)\n\nIdempotency / Ordering:\n  - seq strictly monotonic per broker; no gaps (gap ⇒ operational incident)\n  - Client drops any frame with seq \u003c= last_applied_seq\n  - Expected next seq = last_applied_seq + 1 (else trigger reconnect + resume)\n\nHeartbeats:\n  - Sent when no order_update within configured interval\n  - Heartbeat does NOT advance seq; only order_update frames advance seq\n  - Heartbeat and backlog_end both repeat the last data seq\n\nFlow Control:\n  - Server may enforce max_pending_frames/bytes and close with code 4008 (flow_control)\n\nClose Codes:\n  1000 normal\n  1001 going_away\n  1011 internal_error\n  4008 flow_control\n  4009 resume_too_old / protocol_version\n  4401 unauthorized\n","message":{"oneOf":[{"$ref":"#/components/messages/StreamFrameOrderUpdate"},{"$ref":"#/components/messages/StreamFrameOrderReject"},{"$ref":"#/components/messages/StreamFrameHeartbeat"},{"$ref":"#/components/messages/StreamFrameBacklogEnd"},{"$ref":"#/components/messages/StreamFrameError"}]},"bindings":{"ws":{"headers":{"type":"object","required":["PRE-ACCESS-KEY","PRE-ACCESS-TIMESTAMP","PRE-ACCESS-SIGNATURE"],"properties":{"PRE-ACCESS-KEY":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,64}$","description":"Broker access key identifier"},"PRE-ACCESS-TIMESTAMP":{"type":"string","format":"date-time","description":"RFC3339 timestamp with milliseconds"},"PRE-ACCESS-SIGNATURE":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"Keyed BLAKE2b-256 signature hex lowercase"}}},"query":{"type":"object","properties":{"since":{"type":"integer","format":"int64","minimum":1,"description":"Resume from last applied seq (inclusive). Must be \u003e0. If omitted or 0, start from live tail."},"market":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by market_id. Absent → all markets accessible to broker."},"event_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by event_id. Absent → all events accessible to broker."},"account_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by account_id. Absent → all accounts of broker."}}}}}}},"/accounting":{"subscribe":{"summary":"Receive real-time accounting and ledger updates","description":"Real-time accounting updates including fills, cancellations, merges, and payouts.\nThis stream provides atomic updates for both cash and position balances.\n\nQuery Parameters:\n  - since=\u0026lt;uint64\u0026gt;   Last applied seq for resume (optional; must be \u003e0; absent or 0 → start from live tail)\n  - market=\u0026lt;id\u0026gt;      Repeatable; filter by market_id\n  - account_id=\u0026lt;id\u0026gt;  Repeatable; filter by account_id\n\nResume semantics are identical to the /orders stream.\n","message":{"oneOf":[{"$ref":"#/components/messages/StreamFrameAccountingUpdate"},{"$ref":"#/components/messages/StreamFrameAccountingPayout"},{"$ref":"#/components/messages/StreamFrameHeartbeat"},{"$ref":"#/components/messages/StreamFrameBacklogEnd"},{"$ref":"#/components/messages/StreamFrameError"}]},"bindings":{"ws":{"headers":{"type":"object","required":["PRE-ACCESS-KEY","PRE-ACCESS-TIMESTAMP","PRE-ACCESS-SIGNATURE"],"properties":{"PRE-ACCESS-KEY":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,64}$"},"PRE-ACCESS-TIMESTAMP":{"type":"string","format":"date-time"},"PRE-ACCESS-SIGNATURE":{"type":"string","pattern":"^[0-9a-f]{64}$"}}},"query":{"type":"object","properties":{"since":{"type":"integer","format":"int64","minimum":1,"description":"Resume from last applied seq (inclusive). Must be \u003e0. If omitted or 0, start from live tail."},"market":{"type":"array","items":{"type":"string"}},"account_id":{"type":"array","items":{"type":"string"}}}}}}}},"/payouts":{"deprecated":true,"subscribe":{"summary":"Receive real-time payout/settlement updates (DEPRECATED)","description":"Real-time settlement payouts stream with resume capability.\nNOTE: This stream is deprecated. Please migrate to /accounting.\n\nQuery Parameters:\n  - since=\u0026lt;uint64\u0026gt;   Last applied seq for resume (optional; must be \u003e0; absent or 0 → start from live tail)\n  - market=\u0026lt;id\u0026gt;      Repeatable; filter by market_id\n  - account_id=\u0026lt;id\u0026gt;  Repeatable; filter by account_id\n\nResume Semantics:\n  1. Client connects with since=S (last applied seq)\n  2. Server replays frames with seq \u003e= S in order\n  3. Sends backlog_end (last_seq = current max)\n  4. Continues live streaming\n  If S \u003e current max → immediate live (no backlog)\n  If S too old (retention gap) → error frame (code=resume_too_old) then close (4009)\n\nIdempotency / Ordering:\n  - seq strictly monotonic per broker (shared or separate sequence depending on implementation details, typically separate per stream type); no gaps\n  - Client drops any frame with seq \u003c= last_applied_seq\n  - Expected next seq = last_applied_seq + 1\n\nHeartbeats:\n  - Sent when no payout within configured interval\n  - Heartbeat does NOT advance seq\n  - Heartbeat and backlog_end both repeat the last data seq\n\nClose Codes:\n  Same as /orders\n","message":{"oneOf":[{"$ref":"#/components/messages/StreamFramePayout"},{"$ref":"#/components/messages/StreamFrameHeartbeat"},{"$ref":"#/components/messages/StreamFrameBacklogEnd"},{"$ref":"#/components/messages/StreamFrameError"}]},"bindings":{"ws":{"headers":{"type":"object","required":["PRE-ACCESS-KEY","PRE-ACCESS-TIMESTAMP","PRE-ACCESS-SIGNATURE"],"properties":{"PRE-ACCESS-KEY":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,64}$","description":"Broker access key identifier"},"PRE-ACCESS-TIMESTAMP":{"type":"string","format":"date-time","description":"RFC3339 timestamp with milliseconds"},"PRE-ACCESS-SIGNATURE":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"Keyed BLAKE2b-256 signature hex lowercase"}}},"query":{"type":"object","properties":{"since":{"type":"integer","format":"int64","minimum":1,"description":"Resume from last applied seq (inclusive). Must be \u003e0. If omitted or 0, start from live tail."},"market":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by market_id. Absent → all markets accessible to broker."},"event_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by event_id. Absent → all events accessible to broker."},"account_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by account_id. Absent → all accounts of broker."}}}}}}},"/market-data":{"subscribe":{"summary":"Receive real-time market data","description":"Real-time market data stream with dynamic topic subscription (order book snapshots/diffs, trades).\n\nSubscription Model (no query parameters):\n  - Connection starts with zero markets subscribed\n  - Client sends a subscribe frame (MDClientSubscribe) listing market_id values\n  - Server replies with exactly one MDBookSnapshot per NEW market, then streams MDBookDiff / MDTrade\n  - Client may send unsubscribe (MDClientUnsubscribe) to stop updates for specific markets\n  - Repeated subscription for already active market without force_snapshot is idempotent (no extra snapshot)\n\nOrdering / Monotonicity:\n  - md_seq is dense and strictly increasing per market_id ONLY on data frames (book_snapshot, book_diff, trade)\n  - heartbeat does not advance md_seq\n  - Gaps in md_seq per market indicate operational incident; client SHOULD resync (fresh snapshot + re-subscribe)\n\nInitial Snapshots:\n  - Snapshot sent only upon successful subscription (or re-subscription with force_snapshot=true)\n\nSnapshots Cadence:\n  - Periodic server-initiated book_snapshot frames limit diff chain length\n  - Clients MUST apply snapshot then contiguous diffs/trades with md_seq = snapshot.md_seq+1 … without gaps\n","message":{"oneOf":[{"$ref":"#/components/messages/MDBookSnapshot"},{"$ref":"#/components/messages/MDBookDiff"},{"$ref":"#/components/messages/MDTrade"},{"$ref":"#/components/messages/MDHeartbeat"},{"$ref":"#/components/messages/MDError"}]},"bindings":{"ws":{"headers":{"type":"object","required":["PRE-ACCESS-KEY","PRE-ACCESS-TIMESTAMP","PRE-ACCESS-SIGNATURE"],"properties":{"PRE-ACCESS-KEY":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,64}$","description":"Broker access key identifier"},"PRE-ACCESS-TIMESTAMP":{"type":"string","format":"date-time","description":"RFC3339 timestamp with milliseconds"},"PRE-ACCESS-SIGNATURE":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"Keyed BLAKE2b-256 signature hex lowercase"}}}}}},"publish":{"summary":"Send subscription control messages","message":{"oneOf":[{"$ref":"#/components/messages/MDClientSubscribe"},{"$ref":"#/components/messages/MDClientUnsubscribe"}]}}},"/events":{"subscribe":{"summary":"Receive real-time event/market lifecycle updates","description":"Real-time lifecycle events stream for events and markets with resume capability.\n\nQuery Parameters:\n  - since=\u0026lt;uint64\u0026gt;   Last applied seq for resume (optional; must be \u003e0; absent or 0 → start from live tail)\n  - event_id=\u0026lt;id\u0026gt;    Repeatable; filter by event_id (includes all markets of the event)\n  - market_id=\u0026lt;id\u0026gt;   Repeatable; filter by market_id\n  - lang=\u0026lt;code\u0026gt;      Repeatable; filter by language code (en, pt, id). Filters LocalizedText fields in payloads. If omitted, all available locales are included.\n\nResume Semantics:\n  1. Client connects with since=S (last applied seq)\n  2. Server replays frames with seq \u003e= S in order\n  3. Sends backlog_end (last_seq = current max)\n  4. Continues live streaming\n  If S \u003e current max → immediate live (no backlog)\n  If S too old (retention gap) → error frame (code=resume_too_old) then close (4009)\n\nIdempotency / Ordering:\n  - seq strictly monotonic; no gaps (gap ⇒ operational incident)\n  - Client drops any frame with seq \u003c= last_applied_seq\n  - Expected next seq = last_applied_seq + 1 (else trigger reconnect + resume)\n\nEvent Types:\n  - event.created: New event created with full definition\n  - event.status_changed: Event status changed (only status fields)\n  - event.settled: Event resolved (includes expiration_value and resolved_market_id; either may be null)\n  - event.voided: Event cancelled (includes void_reason)\n  - market.created: New market created with full definition\n  - market.status_changed: Market status changed (only status fields)\n  - market.details_changed: Market details changed (title, subtitles, floor_strike)\n  - market.settled: Market resolved (includes result, settlement_price, expiration_value)\n  - market.voided: Market cancelled\n\nMarket Details At Resolution:\n  - market.details_changed can arrive on a closed market at resolution, with a new floor_strike\n  - It always comes before market.settled and event.settled of the same event\n  - expiration_value in those two events matches the new floor_strike, and can carry more decimals than usual\n\nHeartbeats:\n  - Sent when no lifecycle_update within configured interval\n  - Heartbeat does NOT advance seq; only lifecycle_update frames advance seq\n  - Heartbeat and backlog_end both repeat the last data seq\n\nFlow Control:\n  - Server may enforce max_pending_frames/bytes and close with code 4008 (flow_control)\n\nClose Codes:\n  1000 normal\n  1001 going_away\n  1011 internal_error\n  4008 flow_control\n  4009 resume_too_old / protocol_version\n  4401 unauthorized\n","message":{"oneOf":[{"$ref":"#/components/messages/StreamFrameEventUpdate"},{"$ref":"#/components/messages/StreamFrameHeartbeat"},{"$ref":"#/components/messages/StreamFrameBacklogEnd"},{"$ref":"#/components/messages/StreamFrameError"}]},"bindings":{"ws":{"headers":{"type":"object","required":["PRE-ACCESS-KEY","PRE-ACCESS-TIMESTAMP","PRE-ACCESS-SIGNATURE"],"properties":{"PRE-ACCESS-KEY":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,64}$","description":"Broker access key identifier"},"PRE-ACCESS-TIMESTAMP":{"type":"string","format":"date-time","description":"RFC3339 timestamp with milliseconds"},"PRE-ACCESS-SIGNATURE":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"Keyed BLAKE2b-256 signature hex lowercase"}}},"query":{"type":"object","properties":{"since":{"type":"integer","format":"int64","minimum":1,"description":"Resume from last applied seq (inclusive). Must be \u003e0. If omitted or 0, start from live tail."},"event_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by event_id. Includes all markets of the event. Absent → all events accessible to broker."},"market_id":{"type":"array","items":{"type":"string"},"description":"Repeatable filter by market_id. Absent → all markets accessible to broker."},"lang":{"type":"array","items":{"type":"string","enum":["en","pt","id"]},"description":"Repeatable filter by language code. Filters localized text fields in payloads. If omitted, all available locales are included in each payload."}}}}}}}},"components":{"messages":{"StreamFrameOrderUpdate":{"name":"StreamFrameOrderUpdate","title":"Order Update Frame","summary":"Order state change notification","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameOrderUpdate"}},"StreamFrameOrderReject":{"name":"StreamFrameOrderReject","title":"Order Reject Frame","summary":"Notification of a rejected order command (Amend/Cancel)","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameOrderReject"}},"StreamFrameHeartbeat":{"name":"StreamFrameHeartbeat","title":"Heartbeat Frame","summary":"Keep-alive heartbeat (does not advance seq)","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameHeartbeat"}},"StreamFrameBacklogEnd":{"name":"StreamFrameBacklogEnd","title":"Backlog End Marker","summary":"Signals end of historical replay; live streaming begins","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameBacklogEnd"}},"StreamFrameError":{"name":"StreamFrameError","title":"Error Frame","summary":"Error notification before close","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameError"}},"StreamFramePayout":{"name":"StreamFramePayout","title":"Payout Notification Frame","summary":"Notification of a settlement payout","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFramePayout"}},"StreamFrameAccountingUpdate":{"name":"StreamFrameAccountingUpdate","title":"Accounting Update Frame","summary":"Unified atomic update of cash and position balances for an account within one engine tick.","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameAccountingUpdate"}},"StreamFrameAccountingPayout":{"name":"StreamFrameAccountingPayout","title":"Accounting Payout Frame","summary":"Final cash and position adjustment from market settlement or void","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameAccountingPayout"}},"MDBookSnapshot":{"name":"MDBookSnapshot","title":"Order Book Snapshot","summary":"Full order book snapshot for a market","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDBookSnapshot"}},"MDBookDiff":{"name":"MDBookDiff","title":"Order Book Diff","summary":"Incremental order book update (delta)","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDBookDiff"}},"MDTrade":{"name":"MDTrade","title":"Trade Event","summary":"Trade execution notification","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDTrade"}},"MDHeartbeat":{"name":"MDHeartbeat","title":"Market Data Heartbeat","summary":"Keep-alive heartbeat (does not advance md_seq)","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDHeartbeat"}},"MDError":{"name":"MDError","title":"Market Data Error","summary":"Market data stream error notification","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDError"}},"MDClientSubscribe":{"name":"MDClientSubscribe","title":"Subscribe Request","summary":"Client request to subscribe to market(s)","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDClientSubscribe"}},"MDClientUnsubscribe":{"name":"MDClientUnsubscribe","title":"Unsubscribe Request","summary":"Client request to unsubscribe from market(s)","contentType":"application/json","payload":{"$ref":"#/components/schemas/MDClientUnsubscribe"}},"StreamFrameEventUpdate":{"name":"StreamFrameEventUpdate","title":"Event/Market Lifecycle Update Frame","summary":"Event or market lifecycle state change notification","contentType":"application/json","payload":{"$ref":"#/components/schemas/StreamFrameEventUpdate"}}},"schemas":{"OrderView":{"type":"object","description":"Current state of an order.\n","required":["order_id","client_order_id","market_id","broker_id","account_id","side","type","tif","token","price","qty","volume","filled_qty","filled_volume","status","last_update_wall_time_ns","last_update_engine_seq"],"properties":{"order_id":{"type":"string","format":"uuid"},"client_order_id":{"type":"string"},"market_id":{"type":"string"},"broker_id":{"type":"string"},"account_id":{"type":"string"},"side":{"$ref":"#/components/schemas/OrderSide"},"type":{"$ref":"#/components/schemas/OrderType"},"tif":{"$ref":"#/components/schemas/OrderTIF"},"token":{"$ref":"#/components/schemas/Token"},"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"},"volume":{"$ref":"#/components/schemas/Decimal"},"filled_qty":{"$ref":"#/components/schemas/Decimal"},"filled_volume":{"$ref":"#/components/schemas/Decimal"},"filled_fee":{"description":"Total filled fees accumulated on this order (in quote currency units).","allOf":[{"$ref":"#/components/schemas/Decimal"}]},"status":{"$ref":"#/components/schemas/OrderStatus"},"status_reason":{"$ref":"#/components/schemas/OrderStatusReason"},"last_update_wall_time_ns":{"type":"integer","format":"int64"},"last_update_engine_seq":{"type":"integer","format":"int64","description":"Monotonic engine sequence number of the last applied change"},"last_cmd_id_hex":{"type":"string","description":"32 lowercase hex"}}},"PayoutView":{"type":"object","required":["market_id","account_id","qty_held_at_settlement","settlement_price","payout_amount","settled_at_wall_time_ns"],"properties":{"market_id":{"type":"string"},"account_id":{"type":"string"},"qty_held_at_settlement":{"description":"Net position at settlement. Positive (+) values indicate Long (YES) contracts held. Negative (-) values indicate Short (NO) contracts held.","allOf":[{"$ref":"#/components/schemas/Decimal"}]},"settlement_price":{"allOf":[{"$ref":"#/components/schemas/Decimal"}]},"payout_amount":{"allOf":[{"$ref":"#/components/schemas/Decimal"}]},"settled_at_wall_time_ns":{"type":"integer","format":"int64"}}},"StreamFrameOrderUpdate":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["order_update"]},"seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"payload":{"$ref":"#/components/schemas/OrderView"}}},"OrderRejectPayload":{"type":"object","required":["command_type","reason","correlation_id"],"properties":{"command_type":{"type":"string","enum":["AMEND","CANCEL"]},"order_id":{"type":"string","format":"uuid"},"client_order_id":{"type":"string"},"reason":{"type":"string"},"correlation_id":{"type":"string","format":"uuid","description":"Correlation ID from the rejected command"}}},"StreamFrameOrderReject":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["order_reject"]},"seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"payload":{"$ref":"#/components/schemas/OrderRejectPayload"}}},"StreamFramePayout":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["payout"]},"seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"payload":{"$ref":"#/components/schemas/PayoutView"}}},"AccountingPositionDelta":{"type":"object","required":["yes_qty","no_qty","yes_reserved","no_reserved"],"properties":{"yes_qty":{"$ref":"#/components/schemas/Decimal"},"no_qty":{"$ref":"#/components/schemas/Decimal"},"yes_reserved":{"$ref":"#/components/schemas/Decimal"},"no_reserved":{"$ref":"#/components/schemas/Decimal"}}},"StreamFrameAccountingUpdate":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["accounting_update"]},"seq":{"type":"integer","format":"int64"},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["account_id","market_id","ref_id","client_ref_id","deltas"],"properties":{"account_id":{"type":"string"},"market_id":{"type":"string"},"ref_id":{"type":"string","description":"System reference (order_id or cmd_id)"},"client_ref_id":{"type":"string","description":"Client reference (client_order_id or client_merge_id)"},"deltas":{"type":"object","required":["cash","position_delta","margin_release"],"properties":{"cash":{"$ref":"#/components/schemas/Decimal"},"margin_release":{"$ref":"#/components/schemas/Decimal"},"position_delta":{"$ref":"#/components/schemas/AccountingPositionDelta"}}},"merge":{"type":"object","required":["merge_id","merged_qty","pnl_realized"],"properties":{"merge_id":{"type":"string","format":"uuid"},"merged_qty":{"$ref":"#/components/schemas/Decimal"},"pnl_realized":{"$ref":"#/components/schemas/Decimal"}}}}}}},"StreamFrameAccountingPayout":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["accounting_payout"]},"seq":{"type":"integer","format":"int64"},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["account_id","market_id","payout_id","reason","cash_delta","position_delta"],"properties":{"account_id":{"type":"string"},"market_id":{"type":"string"},"payout_id":{"type":"string","format":"uuid"},"reason":{"type":"string","enum":["SETTLEMENT","VOID"]},"cash_delta":{"$ref":"#/components/schemas/Decimal"},"position_delta":{"$ref":"#/components/schemas/AccountingPositionDelta"}}}}},"StreamFrameHeartbeat":{"type":"object","required":["type","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["heartbeat"]},"seq":{"type":"integer","format":"int64","minimum":0,"description":"Repeats last delivered data seq; heartbeat does not advance global seq"},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["interval_sec"],"properties":{"interval_sec":{"type":"integer","minimum":1}}}}},"StreamFrameBacklogEnd":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["backlog_end"]},"seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["last_seq"],"properties":{"last_seq":{"type":"integer","format":"int64","minimum":0}}}}},"StreamFrameError":{"type":"object","required":["type","seq","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["error"]},"seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"MDTrade":{"type":"object","required":["type","market_id","md_seq","ts_ns","trade_id","price","qty","taker_side"],"properties":{"type":{"type":"string","enum":["trade"]},"market_id":{"type":"string"},"md_seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"trade_id":{"type":"string"},"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"},"taker_side":{"$ref":"#/components/schemas/OrderSide","description":"Side of the taker order that initiated the trade"}}},"StreamFrameEventUpdate":{"type":"object","required":["type","seq","ts_ns","event_type","payload"],"properties":{"type":{"type":"string","enum":["event_update"]},"seq":{"type":"integer","format":"int64","minimum":0,"description":"Monotonic sequence for lifecycle events"},"ts_ns":{"type":"integer","format":"int64","description":"Timestamp in nanoseconds"},"event_id":{"type":"string","nullable":true,"description":"Event ID (if applicable)"},"market_id":{"type":"string","nullable":true,"description":"Market ID (if applicable)"},"event_type":{"$ref":"#/components/schemas/LifecycleEventType"},"payload":{"oneOf":[{"$ref":"#/components/schemas/EventCreatedPayload"},{"$ref":"#/components/schemas/EventStatusChangedPayload"},{"$ref":"#/components/schemas/EventSettledPayload"},{"$ref":"#/components/schemas/EventVoidedPayload"},{"$ref":"#/components/schemas/MarketCreatedPayload"},{"$ref":"#/components/schemas/MarketStatusChangedPayload"},{"$ref":"#/components/schemas/MarketDetailsChangedPayload"},{"$ref":"#/components/schemas/MarketSettledPayload"},{"$ref":"#/components/schemas/MarketVoidedPayload"}]}}},"OrderSide":{"type":"string","enum":["BUY","SELL"]},"OrderType":{"type":"string","enum":["LIMIT","MARKET"]},"OrderTIF":{"type":"string","enum":["GTC","IOC","FOK","DAY"]},"Token":{"type":"string","enum":["YES","NO"]},"Decimal":{"type":"object","required":["units","nanos"],"properties":{"units":{"type":"integer","format":"int64"},"nanos":{"type":"integer","format":"int32","minimum":-999999999,"maximum":999999999}}},"OrderStatus":{"type":"string","enum":["NEW","ACTIVE","PARTIALLY_FILLED","FILLED","CANCELLED","EXPIRED","REJECTED"]},"OrderStatusReason":{"type":"string","description":"Machine-readable reason code for the current status","enum":["USER_REQUEST","MARKET_CLOSED","MARKET_SETTLED","MARKET_VOIDED","TIF_EXPIRATION","FOK_FAILED","IOC_PARTIAL","SELF_TRADE_PREVENTION","INSUFFICIENT_FUNDS","SYSTEM_ERROR","ORDER_ALREADY_FILLED","ORDER_ALREADY_CANCELLED","ORDER_NOT_FOUND","QTY_INVALID","QTY_BELOW_EXECUTED","NO_MATCHING_LIQUIDITY","DUPLICATE_CLIENT_ORDER_ID","EXCEEDS_MAX_ORDER_QTY","EXCEEDS_MAX_ORDER_NOTIONAL","EXCEEDS_MAX_POSITION"]},"MDBookSnapshot":{"type":"object","required":["type","market_id","md_seq","ts_ns","bids","asks"],"properties":{"type":{"type":"string","enum":["book_snapshot"]},"market_id":{"type":"string"},"md_seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"bids":{"type":"array","items":{"type":"object","required":["price","qty"],"properties":{"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"}}}},"asks":{"type":"array","items":{"type":"object","required":["price","qty"],"properties":{"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"}}}}}},"MDBookDiff":{"type":"object","required":["type","market_id","md_seq","ts_ns","bids","asks"],"properties":{"type":{"type":"string","enum":["book_diff"]},"market_id":{"type":"string"},"md_seq":{"type":"integer","format":"int64","minimum":0},"ts_ns":{"type":"integer","format":"int64"},"bids":{"description":"Price level deltas (upsert or delete if qty=0)","type":"array","items":{"type":"object","required":["price","qty"],"properties":{"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"}}}},"asks":{"description":"Price level deltas (upsert or delete if qty=0)","type":"array","items":{"type":"object","required":["price","qty"],"properties":{"price":{"$ref":"#/components/schemas/Decimal"},"qty":{"$ref":"#/components/schemas/Decimal"}}}}}},"MDHeartbeat":{"type":"object","required":["type","ts_ns"],"properties":{"type":{"type":"string","enum":["heartbeat"]},"ts_ns":{"type":"integer","format":"int64"},"market_id":{"type":"string","nullable":true,"description":"Optional; may be omitted for aggregated heartbeat across all subscribed markets"},"md_seq":{"type":"integer","format":"int64","minimum":0,"nullable":true,"description":"Repeats last data md_seq for the specific market if market_id present; absent for aggregated heartbeat"}}},"MDError":{"type":"object","required":["type","ts_ns","payload"],"properties":{"type":{"type":"string","enum":["error"]},"ts_ns":{"type":"integer","format":"int64"},"payload":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"MDClientSubscribe":{"description":"Client → Server subscription request (WebSocket text JSON)","type":"object","required":["type","markets"],"properties":{"type":{"type":"string","enum":["subscribe"]},"markets":{"type":"array","minItems":1,"items":{"type":"string"}},"force_snapshot":{"type":"boolean","default":false,"description":"If true, forces fresh snapshot even if already subscribed"}}},"MDClientUnsubscribe":{"description":"Client → Server unsubscribe request","type":"object","required":["type","markets"],"properties":{"type":{"type":"string","enum":["unsubscribe"]},"markets":{"type":"array","minItems":1,"items":{"type":"string"}}}},"LifecycleEventType":{"type":"string","enum":["event.created","event.status_changed","event.settled","event.voided","market.created","market.status_changed","market.details_changed","market.settled","market.voided"],"description":"Lifecycle event type"},"LocalizedText":{"type":"object","description":"Localized text content. When lang filter is applied, only requested locales are included.\nWhen lang filter is omitted, all available locales (en, pt, id) are included.\n","properties":{"en":{"type":"string"},"pt":{"type":"string"},"id":{"type":"string"}}},"EventSeries":{"type":"string","enum":["","1min","5min","15min","1h","4h","1d"],"description":"Event series meta tag. Empty = standalone event. Non-empty values indicate\nthe event belongs to a recurring series with the given interval.\n"},"EventStatus":{"type":"string","enum":["open","closed","settled","voided"],"description":"- open: event is open, trading on markets is open or will be open (market statuses: unopened, pre-open, active, or suspended)\n- closed: event is closed, trading stopped, markets awaiting resolution and settlement\n- settled: all markets resolved and payouts completed\n- voided: event cancelled, all markets voided, contracts refunded\n"},"SettlementSource":{"type":"object","required":["name","url"],"properties":{"name":{"type":"string"},"url":{"type":"string"},"underlying":{"type":"object","required":["base_currency","quote_currency"],"properties":{"base_currency":{"type":"string"},"quote_currency":{"type":"string"}}}}},"EventCreatedPayload":{"type":"object","required":["event_id","title","rules_primary","category","series","settlement_sources","status","created_at","opens_at","closes_at","markets"],"properties":{"event_id":{"type":"string"},"title":{"$ref":"#/components/schemas/LocalizedText"},"series_title":{"allOf":[{"$ref":"#/components/schemas/LocalizedText"}],"nullable":true,"description":"Localized title of the recurring series this event belongs to. Null when the event's template defines no series title. Absent in payloads emitted before this field was introduced."},"rules_primary":{"$ref":"#/components/schemas/LocalizedText"},"category":{"type":"string","enum":["crypto","forex"]},"image_url":{"type":"string"},"series":{"$ref":"#/components/schemas/EventSeries"},"status":{"$ref":"#/components/schemas/EventStatus"},"void_reason":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"opens_at":{"type":"string","format":"date-time"},"closes_at":{"type":"string","format":"date-time"},"settlement_sources":{"type":"array","items":{"$ref":"#/components/schemas/SettlementSource"}},"markets":{"type":"array","items":{"type":"string"},"description":"Array of market_ids belonging to this event"}}},"EventStatusChangedPayload":{"type":"object","required":["event_id","old_status","new_status"],"properties":{"event_id":{"type":"string"},"old_status":{"$ref":"#/components/schemas/EventStatus"},"new_status":{"$ref":"#/components/schemas/EventStatus"}}},"EventSettledPayload":{"type":"object","required":["event_id","resolved_at"],"properties":{"event_id":{"type":"string"},"expiration_value":{"type":"string","nullable":true,"description":"Final asset value as string. Not necessarily a price, and not always numeric: it carries whatever value the settlement source publishes for the outcome. `null` if the resolution source publishes no closing value; the outcome is then carried by `resolved_market_id`, or by the per-market `result` when that is null too."},"resolved_market_id":{"type":"string","nullable":true,"description":"Market ID of the winning market. `null` when no market won, and also when more than one won: this field carries a single winner and cannot express several. Read the per-market `result` to see the outcome of every market."},"resolved_at":{"type":"string","format":"date-time","description":"Actual resolution timestamp"}}},"EventVoidedPayload":{"type":"object","required":["event_id","void_reason"],"properties":{"event_id":{"type":"string"},"void_reason":{"type":"string","description":"Reason for voiding the event"}}},"MarketStatus":{"type":"string","enum":["unopened","pre-open","active","suspended","closed","settled","voided"],"description":"- unopened: created, not initialized in CLOB\n- pre-open: loaded in CLOB (MM can already place liquidity)\n- suspended: market open, but new orders are temporarily declined\n- active: market open for order acceptance\n- closed: closed, awaiting resolution; trading stopped, orders no longer accepted\n- settled: market resolved, payouts completed\n- voided: market cancelled, contracts refunded\n"},"MarketResult":{"type":"string","enum":["yes","no",""],"description":"Written when the event resolves, so it appears before the market reaches settled.\n- yes: YES is the winner\n- no: NO is the winner\n- empty: no result yet, or the market was voided\n"},"MarketCreatedPayload":{"type":"object","required":["market_id","event_id","market_index","title","created_at","opens_at","closes_at","expected_expiration_time","settlement_timer_seconds","status","status_revision","result","can_close_early","strike_type"],"properties":{"market_id":{"type":"string","description":"Market ID"},"event_id":{"type":"string"},"market_index":{"type":"integer","description":"Index of the market within the event"},"title":{"$ref":"#/components/schemas/LocalizedText"},"yes_sub_title":{"allOf":[{"$ref":"#/components/schemas/LocalizedText"}],"nullable":true},"no_sub_title":{"allOf":[{"$ref":"#/components/schemas/LocalizedText"}],"nullable":true},"lower_bound":{"allOf":[{"$ref":"#/components/schemas/Decimal"}],"nullable":true,"description":"Lower boundary for strike range (NULL for first market)"},"upper_bound":{"allOf":[{"$ref":"#/components/schemas/Decimal"}],"nullable":true,"description":"Upper boundary for strike range (NULL for last market)"},"lower_inclusive":{"type":"boolean","description":"Whether lower_bound is inclusive in the range"},"upper_inclusive":{"type":"boolean","description":"Whether upper_bound is inclusive in the range"},"status":{"$ref":"#/components/schemas/MarketStatus"},"status_revision":{"type":"integer","format":"int64","description":"Monotonic revision of the market status from Event Service"},"result":{"$ref":"#/components/schemas/MarketResult"},"created_at":{"type":"string","format":"date-time"},"opens_at":{"type":"string","format":"date-time"},"closes_at":{"type":"string","format":"date-time"},"expected_expiration_time":{"type":"string","format":"date-time"},"settlement_timer_seconds":{"type":"integer","format":"int32"},"can_close_early":{"type":"boolean"},"early_close_condition":{"type":"string","nullable":true},"strike_type":{"type":"string","enum":["greater","greater_or_equal","less","less_or_equal","between","custom"]},"floor_strike":{"allOf":[{"$ref":"#/components/schemas/Decimal"}],"nullable":true,"description":"Minimum expiration value that leads to a YES settlement"},"cap_strike":{"allOf":[{"$ref":"#/components/schemas/Decimal"}],"nullable":true,"description":"Maximum expiration value that leads to a YES settlement"},"custom_strike":{"type":"string","nullable":true,"description":"Expiration value that leads to a YES settlement when strike_type=custom"}}},"MarketStatusChangedPayload":{"type":"object","required":["market_id","event_id","old_status","new_status","status_revision"],"properties":{"status_revision":{"type":"integer","format":"int64","description":"Monotonic revision of the market status from Event Service"},"market_id":{"type":"string"},"event_id":{"type":"string"},"old_status":{"$ref":"#/components/schemas/MarketStatus"},"new_status":{"$ref":"#/components/schemas/MarketStatus"}}},"MarketDetailsChangedPayload":{"type":"object","required":["market_id","event_id","title","status_revision"],"properties":{"market_id":{"type":"string"},"event_id":{"type":"string"},"title":{"$ref":"#/components/schemas/LocalizedText"},"yes_sub_title":{"allOf":[{"$ref":"#/components/schemas/LocalizedText"}],"nullable":true},"no_sub_title":{"allOf":[{"$ref":"#/components/schemas/LocalizedText"}],"nullable":true},"floor_strike":{"allOf":[{"$ref":"#/components/schemas/Decimal"}],"nullable":true,"description":"Minimum expiration value that leads to a YES settlement"},"status_revision":{"type":"integer","format":"int64","description":"Monotonic revision of the market status from Event Service"}}},"MarketSettledPayload":{"type":"object","required":["market_id","event_id","result","settlement_price","status_revision"],"properties":{"market_id":{"type":"string"},"event_id":{"type":"string"},"result":{"type":"string","enum":["yes","no"],"description":"Winner (YES or NO)"},"settlement_price":{"$ref":"#/components/schemas/Decimal","description":"1.0 for YES, 0.0 for NO"},"expiration_value":{"type":"string","nullable":true,"description":"Final asset value as string. Not necessarily a price, and not always numeric: it carries whatever value the settlement source publishes for the outcome. `null` if the resolution source publishes no closing value, in which case the outcome is carried by `result`."},"status_revision":{"type":"integer","format":"int64","description":"Monotonic revision of the market status from Event Service"}}},"MarketVoidedPayload":{"type":"object","required":["market_id","event_id","void_reason","status_revision"],"properties":{"market_id":{"type":"string"},"event_id":{"type":"string"},"void_reason":{"type":"string","description":"Reason for voiding the market"},"status_revision":{"type":"integer","format":"int64","description":"Monotonic revision of the market status from Event Service"}}}}}}