Always
"rfq".256 bytes of
BroadcastRfqRequest, encoded as standard base64 without
padding.Message Loop
Once Authentication returns asession_token, attach a
message loop to the same WebSocket and send a subscribe message for the RFQ
categories this connection should receive. Authenticated connections receive no
RFQs until they subscribe. Subscribe messages are additive for the connection:
sending another subscribe message adds filters, and all filters are dropped
when the socket disconnects. The loop also needs to reply to server ping
heartbeats to keep the session alive. A successful subscribe returns a
subscribed frame.
decode_rfq is defined in Decode Example below.
{ "kind": "mention" } for RFQs with mention-market legs, or
{ "kind": "price", "asset": "BTC" } for RFQs with a price leg for one asset.
Price assets use the normal ticker symbols: BTC, ETH, SOL, XRP, HYPE.
BroadcastRfqRequest
Decoded data is a 256-byte struct. All integer fields are little-endian; UUID
fields are raw 16-byte UUIDs.
| Offset | B | Field | Type | Meaning |
|---|---|---|---|---|
| 0 | 16 | request_id | uuid | RFQ UUID |
| 16 | 8 | wager_micros | uint64 LE | user wager in USDC micros |
| 24 | 8 | expires_at_ms | uint64 LE | RFQ expiry as Unix milliseconds |
| 32 | 24 | taker_metadata | struct | optional taker tier and wallet |
| 56 | 1 | order_type | uint8 | 1=IOC, 2=FOK |
| 57 | 1 | leg_count | uint8 | number of active legs (1..8) |
| 58 | 6 | reserved | — | zero padding |
| 64 | 192 | legs | struct[8] | eight 24-byte RfqLeg slots |
leg_count leg slots are active; the rest are zeroed.
taker_metadata (24 bytes)
| Offset | B | Field | Type | Meaning |
|---|---|---|---|---|
| 0 | 1 | option | uint8 | 0 = absent; non-zero = present |
| 1 | 1 | tier | uint8 | 0=Standard, 1=Silver, 2=Gold, 3=Platinum, 4=VIP |
| 2 | 2 | reserved | — | zero padding |
| 4 | 20 | address | bytes20 | raw EVM taker wallet address |
RfqLeg (24 bytes)
| Offset | B | Field | Type | Meaning |
|---|---|---|---|---|
| 0 | 8 | market_id | uint64 LE | Longshot market id |
| 8 | 8 | start_at_ms | uint64 LE | canonical market start time (Unix ms) |
| 16 | 1 | market_kind | uint8 | 0=Price, 1=Mention |
| 17 | 1 | direction | uint8 | 0=UP, 1=DOWN |
| 18 | 1 | leg_index | uint8 | leg position in the parlay |
| 19 | 1 | price_asset | uint8 | 0=BTC, 1=ETH, 2=SOL, 3=XRP, 4=HYPE; 0 on mention legs |
| 20 | 4 | price_duration_secs | uint32 LE | supported: 60, 300, 900, 3600, 14400, 86400; 0 on mention legs |
market_kind = 0) populate price_asset and price_duration_secs
with the underlying asset code and duration. Mention legs (market_kind = 1)
reference externally-sourced markets and leave both fields zero; the leg’s
identity is fully determined by market_id.
Decode Example
decode_rfq turns the base64-no-padding data field into a typed
BroadcastRfqRequest matching the byte layout above.
Example RFQ
A 3-leg BTC UP / UP / UP parlay across three consecutive 5-minute windows.
On the wire
The server broadcasts anrfq envelope; data is the 256-byte
BroadcastRfqRequest encoded as standard base64 with no padding
(⌈256 × 4 / 3⌉ → 342 characters).
Decoded BroadcastRfqRequest
Running the decode example on data yields:
Legs at a glance
| # | Asset | Direction | Window | start_at_ms (UTC) | market_id |
|---|---|---|---|---|---|
| 0 | BTC | UP | 5 min | 1712322300000 — 2024-04-05 13:05:00Z | 1001 |
| 1 | BTC | UP | 5 min | 1712322600000 — 2024-04-05 13:10:00Z | 1002 |
| 2 | BTC | UP | 5 min | 1712322900000 — 2024-04-05 13:15:00Z | 1003 |
wager_micros = 10_000_000) and the order is FOK (order_type = 2).
Error Codes
Session-level failures arrive as anerror frame on the WebSocket:
Action column.
| Code | Meaning | Action |
|---|---|---|
AUTH_EXPIRED | Session is older than 1 hour. | Reconnect and re-auth. |
HEARTBEAT_TIMEOUT | Server missed 3 consecutive pongs; connection will close. | Reconnect and re-auth; pong within 15s of each ping. |
AUTH_TIMEOUT | Did not complete the auth handshake within 10 seconds of connecting. | Reconnect; finish handshake faster. |
NOT_AUTHENTICATED | Sent a non-auth message before . | Complete auth first. |
ALREADY_AUTHENTICATED | Sent auth or auth_response after already authenticating. | Stop re-authing on the same connection. |
AUTH_BANNED | Your IP address was temporarily banned after repeated failed auth attempts. Ban is tracked per IP in the gateway (not per wallet) and expires after a TTL. | Wait for the ban TTL to lift; reconnecting from a different IP also works. |
AUTH_UNAVAILABLE | Auth backend is temporarily unavailable. | Back off and retry. |
MM_CONNECTION_LIMIT | Too many authenticated WebSocket connections for this market maker. | Close an existing connection or reduce parallel sockets before retrying. |
UNKNOWN_MM | Quote rate-limiter could not find the authenticated MM in the registry (e.g. removed mid-session). Note: an unregistered wallet at the auth handshake fails earlier as , not this frame. | Reconnect and re-auth; if it persists, contact Longshot ops to provision the wallet. |
MALFORMED_JSON | A message you sent failed JSON parsing. | Fix the message; no reconnect required. |
BINARY_NOT_SUPPORTED | Server received a binary WebSocket frame. | Send JSON text frames only. |
RATE_LIMITED | Too many control messages (e.g. subscribe, repeated auth). Quote throttling uses the rate_limit frame instead — see Rate Limits. | Back off; respect the operational limits on Authentication. |
CONNECTION_LIMIT | Global WebSocket connection cap reached. | Reduce concurrent connections; retry later. |
UNAUTH_LIMIT | Too many unauthenticated connections pending. | Retry after authenticating existing connections. |
IP_LIMIT | Too many connections from your IP. | Reduce per-IP concurrency. |