Getting Started (version 2.0)
We provide accurate and reliable forex data via easy-to-use delivery methods. We use WSS and WebSockets which make it easier to receive data. Authentication is over a secure WSS protocol and responses are in JSON Format.
Following are a few simple steps to start receiving market data.
-
Sign up for the API: Sign Up
-
Start your Socket trial: Start Trial.
-
Get your Streaming API key: Get your Streaming Data key.
-
Start getting data : Connect to WebSocket V2
Quick Start Guide
We have created several of tutorials to help you get started with our Forex Websocket API. Our tutorials cover various topics, such as Golang, Python, NodeJS, C#.
See our quick start tutorials on getting started : How to start a WebSocket Trial
Authentication
You need to include your Forex API key with the initial request when you start your connection. You can find your API key under your account once you log in.
Our streaming data API documentation is extensive, and you can see below all the available routes and currencies to help you integrate our data within your applications. If you are new to WebSockets and SocketIO, visit our Tutorial page that explains sockets in greater detail.
TraderMade WebSocket Tester
Test TraderMade WebSocket Stream API connections and subscriptions
wss://stream.tradermade.com/feedadv
Multiple symbols can be entered separated by commas
Available Currencies For WebSockets
We support over 4000+ currency pairs on our Websockets. To access a list of currencies available, visit our websocket currencies list page.
See the complete list of global Market CFDs we provide via WebSockets. You need to add USD at the end of each CFD code for Websockets. For example. TSLA should be TSLAUSD:QUOTE.
Websocket
WebSocket is a bidirectional protocol to get real-time data to help you build applications that require low-latency data. The TraderMade WebSocket API provides a simple implementation with easy setup in minutes.
Connection And Protocol Overview
| Item | Details |
|---|---|
| Endpoint | wss://stream.tradermade.com/feedAdv |
| First message | Must be login |
| Client actions | login, subscribe, unsubscribe |
| Server messages | login_ok, login_reject, sub_ack, unsub_ack, logout, error, QUOTE, LAST_QUOTE |
| Market data format | Controlled by fmt: JSON, CSV, SSV |
| Control messages | Always JSON |
| Reconnect behavior | Reconnect and login again; subscriptions are not persisted |
Use the following WebSocket endpoint for all v2 streaming requests:
| URL | Protocol | Description |
|---|---|---|
| stream.tradermade.com/feedAdv | wss | Connect using the url and once open send a JSON login action including your streaming API key (key) and the response format (fmt) to log in. After login_ok, send subscribe / unsubscribe actions on the same connection (as shown below). Use SYMBOL:QUOTE form in your symbols arrays so they match the ack strings byte for byte. |
Authentication Events
Use these events to open the connection and authenticate with your streaming API key.
| Event | Type | Description |
|---|---|---|
| On open | Connection Event / Send | Send a login action with your streaming API key (key) and the format (fmt) in JSON - example: {"action":"login","key":"{{api_key}}","fmt":"JSON"} If you want to receive CSV or SSV format just change fmt in above json to get that format - example: {"action":"login","key":"{{api_key}}","fmt":"CSV"} |
| On login_ok | Connection Event / Receive | Will receive a login_ok JSON confirming the format and your account capabilities - symbol_limit (max simultaneous subscriptions), cfds (true if CFD symbols are enabled), trader_ladder (true if depth/ladder data is enabled). |
| On login_reject | Connection Event / Receive | Will receive a login_reject JSON if the API key is not recognised. The reason field tells you why (e.g. unknown_key). |
SEND LOGIN ON OPEN
{"action":"login","key":"{{api_key}}","fmt":"JSON"}
RESPONSE JSON ON SUCCESSFUL LOGIN
{"type":"login_ok","key":"{{api_key}}","fmt":"JSON","symbol_limit":54,"cfds":true,"trader_ladder":false}
RESPONSE JSON ON FAILED LOGIN (INVALID KEY)
{"type":"login_reject","key":"INVALID_KEY","reason":"unknown_key"}
SEND LOGIN ON OPEN (TO RECV CSV)
{"action":"login","key":"{{api_key}}","fmt":"CSV"}
SEND LOGIN ON OPEN (TO RECV SSV)
{"action":"login","key":"{{api_key}}","fmt":"SSV"}
Subscription Events
Use these events to subscribe and unsubscribe symbols after a successful login.
| Event | Type | Description |
|---|---|---|
| On subscribe | Method Action / Send | Send a subscribe action with an array of symbols (use SYMBOL:QUOTE form so the request and the ack strings match) - example: {"action":"subscribe","symbols":["EURUSD:QUOTE","GBPUSD:QUOTE"]} To also receive one cached LAST_QUOTE tick per symbol immediately on subscribe, add send_last - example: {"action":"subscribe","send_last":true,"symbols":["EURUSD:QUOTE"]} |
| On sub_ack | Method Response / Receive | Will receive a sub_ack JSON listing accepted (now subscribed), denied (with a denied_reasons map - e.g. limit_reached, cfds_not_allowed) and invalid (symbols the server does not recognise). The rest of the batch still subscribes successfully even when some entries are denied or invalid. |
| On unsubscribe | Method Action / Send | Send an unsubscribe action to remove symbols without dropping the connection - example: {"action":"unsubscribe","symbols":["GBPUSD:QUOTE"]} Remaining symbols keep streaming uninterrupted. |
| On unsub_ack | Method Response / Receive | Will receive an unsub_ack JSON listing removed (now unsubscribed) and invalid (symbols you were not subscribed to). |
SEND SUBSCRIBE (TO RECV JSON QUOTES)
{"action":"subscribe","symbols":["EURUSD:QUOTE","GBPUSD:QUOTE"]}
RECV SUB_ACK ON MESSAGE
{"accepted":["EURUSD:QUOTE","GBPUSD:QUOTE"],"denied":[],"denied_reasons":{},"invalid":[],"type":"sub_ack"}
SEND SUBSCRIBE WITH send_last (TO RECV LAST_QUOTE FIRST)
{"action":"subscribe","send_last":true,"symbols":["EURUSD:QUOTE"]}
RECV SUB_ACK ON MESSAGE
{"accepted":["EURUSD:QUOTE"],"denied":[],"denied_reasons":{},"invalid":[],"type":"sub_ack"}
SEND SUBSCRIBE WITH INVALID SYMBOL
{"action":"subscribe","symbols":["EURUSD:QUOTE","XXXYYY:QUOTE"]}
RECV SUB_ACK WITH invalid LIST ON MESSAGE
{"accepted":["EURUSD:QUOTE"],"denied":[],"denied_reasons":{},"invalid":["XXXYYY:QUOTE"],"type":"sub_ack"}
SEND SUBSCRIBE OVER symbol_limit
{"action":"subscribe","symbols":["EURGBP:QUOTE","EURJPY:QUOTE","...","NZDEUR:QUOTE","NZDGBP:QUOTE","NZDJPY:QUOTE"]}
RECV SUB_ACK WITH limit_reached ON MESSAGE
{"type":"sub_ack","accepted":["EURGBP:QUOTE","EURJPY:QUOTE","..."],"denied":["NZDEUR:QUOTE","NZDGBP:QUOTE","NZDJPY:QUOTE"],"denied_reasons":{"NZDEUR:QUOTE":"limit_reached","NZDGBP:QUOTE":"limit_reached","NZDJPY:QUOTE":"limit_reached"},"invalid":[]}
SEND UNSUBSCRIBE
{"action":"unsubscribe","symbols":["GBPUSD:QUOTE"]}
RECV UNSUB_ACK ON MESSAGE
{"type":"unsub_ack","removed":["GBPUSD:QUOTE"],"invalid":[]}
Error And Connection Events
Use these events to handle failed messages and closed connections.
| Event | Type | Description |
|---|---|---|
| On error | Method Response / Receive | Will receive an error JSON with a reason if a message cannot be processed (e.g. invalid_json, unknown_action). |
| On logout | Connection Event / Receive | Will receive a logout JSON when the server forces the session off, such as when the same API key logs in from another connection. |
| On disconnect | Connection Event | On disconnect, no message is sent. Reconnect with backoff and restart from the login step. Subscriptions are not persisted across connections - resend your subscribe action after login_ok. |
RECV LOGOUT ON DUPLICATE LOGIN
{"type":"logout","key":"{{api_key}}","reason":"duplicate_login"}
RECV ERROR ON UNKNOWN_ACTION
{"type":"error","reason":"unknown_action","action":"ping"}
RECV ERROR ON INVALID_JSON
{"type":"error","reason":"invalid_json"}
Other Events
After a successful sub_ack, accepted symbols stream market data payloads on the same connection. JSON payloads use the t field to identify the message type.
QUOTE
Live quote updates are sent with t set to QUOTE.
{"a":"1.162720000","av":"100000","b":"1.162700000","bv":"100000","s":"EURUSD","t":"QUOTE","ts":"20260515-12:36:35.588"}
LAST_QUOTE
If send_last is set to true on subscribe, the first tick per symbol is sent with t set to LAST_QUOTE.
{"a":"1.1621","b":"1.16207","m":"1.162085","s":"EURUSD","t":"LAST_QUOTE","ts":"20260515-12:39:21.783"}
Payload Fields
| Field | Applies To | Description |
|---|---|---|
t |
QUOTE, LAST_QUOTE |
Message type |
s |
QUOTE, LAST_QUOTE |
Symbol |
b |
QUOTE, LAST_QUOTE |
Bid price |
a |
QUOTE, LAST_QUOTE |
Ask price |
m |
LAST_QUOTE |
Mid price |
bv |
QUOTE |
Bid volume |
av |
QUOTE |
Ask volume |
ts |
QUOTE, LAST_QUOTE |
Server timestamp |
RECV CSV ON MESSAGE
QUOTE,EURUSD,20260515-12:36:35.588,1.16270,1.16272,100000,100000
QUOTE,GBPUSD,20260515-12:36:35.621,1.33495,1.33499,100000,100000
RECV SSV ON MESSAGE
QUOTE EURUSD 20260515-12:36:35.588 1.16270 1.16272 100000 100000
QUOTE GBPUSD 20260515-12:36:35.621 1.33495 1.33499 100000 100000
Examples
Your Streaming API Key is included in all the sample codes when logged in. So you can use any example right away. Only you can see this key.
Select Language
WebSocket v2 Example
import websocket
import time
try:
import thread
except ImportError:
import _thread as thread
f = open("webSocketTester.log", "a")
def on_message(ws, message):
print(message)
f.write(message + "\n" )
f.flush()
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
def run(*args):
ws.send("{\"action\":\"login\",\"key\":\"{{api_key}}\",\"fmt\":\"JSON\"}")
ws.send("{\"action\":\"subscribe\",\"symbols\":[\"GBPUSD:QUOTE\"]}")
thread.start_new_thread(run, ())
if __name__ == "__main__":
ws = websocket.WebSocketApp("wss://stream.tradermade.com/feedAdv",
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()