Skip to content

WebSocket

A WebSocket connection is provided to stream brokerage prices as executable quotes through our Request-For-Stream (RFS) service

The WebSocket API provides real-time streaming prices and instant order execution through Zodia Markets’ Request for Stream (RFS) service. Unlike REST API’s request-response pattern, WebSocket maintains a persistent connection for continuous price updates.

With the WebSocket API, you can:

  • Stream live prices for multiple currency pairs simultaneously
  • Execute trades instantly on displayed prices
  • Subscribe/unsubscribe to price streams dynamically
  • Specify beneficiary on subscription For quotes on delivering crypto to third party wallets

Connect to the appropriate environment for your integration stage:

Sandbox:

Sandbox
wss://trade-uk.sandbox.zodiamarkets.com

Production:

Production
wss://trade-uk.zodiamarkets.com

WebSocket connections require token-based authentication:

First, request a WebSocket authentication token via REST API:

Python
token_response = make_api_request('POST', 'api/3/zm/rest/auth/token', {})
ws_token = token_response['token']

The token is single-use and short-lived. It is consumed the moment it is presented, so a reconnection needs a freshly requested token, and it expires seconds after issue — 30 seconds in the shipped configuration (auth.token.expiration-time, a deployment setting). Request it immediately before you connect, and do not cache or reuse it.

Use the token to establish your WebSocket connection. token is the only required query parameter — the URL below is complete as it stands. The one optional addition is sessionId, in Step 3.

Websocket
wss://trade-uk.sandbox.zodiamarkets.com/zm/ws/ws-client?token={token}

Add a sessionId to bind order outcomes to a session rather than to this connection, so an outcome survives a dropped connection and is redelivered when you reconnect.

Websocket
wss://trade-uk.sandbox.zodiamarkets.com/zm/ws/ws-client?token={token}&sessionId={sessionId}

Supply it if you place orders with autoSubscribe: true; omit it otherwise. A malformed value refuses the connection, and reconnecting under a sessionId that is already live for your account closes the earlier connection — see Order Sessions and Recovery →.


The RFS WebSocket service operates during:

Monday to Friday: 04:00 GMT to 22:00 GMT, including public holidays

For trading outside these hours, contact the Zodia Markets OTC Brokerage desk:

Scheduled maintenance is announced in advance on the Status Page. Typical maintenance windows:

  • Daily: 21:00 GMT - 21:15 GMT

Lifecycle
1. Obtain Token (REST API)
↓
2. Connect to WebSocket
↓
3. Authenticate with Token
↓
4. Subscribe to Price Streams
↓
5. Receive Price Updates
↓
6. Execute Orders (Optional)
↓
7. Disconnect or Token Expires


WebSocket connections can disconnect for various reasons. Implement automatic reconnection:

Python
import time
def connect_with_retry(ws_url, max_retries=5):
"""Connect with exponential backoff retry"""
for attempt in range(max_retries):
try:
# Get fresh token
token_response = make_api_request('POST', 'api/3/zm/rest/auth/token', {})
ws_token = token_response['token']
# Connect and authenticate
ws = create_connection(ws_url)
authenticate(ws, ws_token)
return ws
except Exception as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt
print(f"Connection failed. Retrying in {wait_time}s...")
time.sleep(wait_time)
else:
raise

WebSocket tokens expire after a set period. Monitor for expiry and refresh:

Python
def monitor_connection(ws):
"""Monitor connection and handle token expiry"""
while True:
try:
message = json.loads(ws.recv())
if message.get('error') == 'expired token':
print("Token expired. Reconnecting...")
ws.close()
ws = connect_with_retry(ws_url)
resubscribe_to_streams(ws)
else:
handle_message(message)
except Exception as e:
print(f"Connection error: {e}")
ws = connect_with_retry(ws_url)
resubscribe_to_streams(ws)