Skip to main content

Exchanging Messages

Once we established a connection, we can send a message to the server. You might be wondering what we mean by a message and how are we going to send it.

WebSocket Basics

In order to better understand the mechanism of sending messages, let's forget about the cTrader OpenAPI server for the moment and connect to another server.

The endpoint that we're going to connect to is 'wss://echo.websocket.org'. This is what's called an echo server, meaning, whatever message the client sends, it will send the exact same message back to the client.

Once the connection is open, we start sending the messages. Notice that we're now "listening" for messages that server is sending back.

const ws = new WebSocket('wss://echo.websocket.org');
const { log } = console;

ws.onopen = function () {
log('connected to server');

let msg = 'hello';
ws.send(msg);
log('client sent a message:', msg);

msg = 'hi';
ws.send(msg);
log('client sent a message:', msg);
};

ws.onmessage = function (event) {
const serverMsg = event.data;
log(`server sent a message: ${serverMsg}`);
};

Results from running the code:

connected to server
client sent a message: hello
client sent a message: hi
server sent a message: hello
server sent a message: hi

Underlying Type of Messages

Let's focus for a moment to the type of messages that are being exchanged, i.e. the messages sent by client to server or vice versa.

Let's only change some parts of previous code example and run it again.

ws.onopen = function () {
console.log('connected to server');
ws.send('hello');
ws.send(2573);
ws.send(true);
};

ws.onmessage = function (event) {
const serverMsg = event.data;
const msgType = typeof serverMsg;
console.log(`server sent a message: ${serverMsg} (${msgType})`);
};

Results from running the code:

connected to server
server sent a message: hello (string)
server sent a message: 2573 (string)
server sent a message: true (string)

As you see, even when we're sending a message with the type of number or int, what the server sends back is always string or str. This is notewortyh because it demonstrates that messages being exchanged between client and server are (usually) strings. Techincally, there are other types of messages that can be transmitted over the network, but in our case of cTrader OpenAPI server, we deal only with strings.

Format of Messages

So far, we established what a message is, and how to send one. Now let's shift our focus back to the cTrader OpenAPI server and go back to the endpoint we were using earlier, and let's listen again for incomeing server messages.

Now let's send a message to the cTrader OpenAPI server, and see wha happens:

const ws = new WebSocket('wss://live.ctraderapi.com:5036');
const { log } = console;

ws.onopen = function () {
log('connected to server');
ws.send('hello');
};

ws.onmessage = function (event) {
const serverMsg = event.data;
log(`server sent a message: ${serverMsg}`);
};

ws.onclose = function () {
log('connection closed');
};

Results:

connected to server
server sent a message: {"payloadType":2142,"payload":{"errorCode":
"INVALID_REQUEST","description":"Malformed JSON message
at 1:6"}}
connection closed

You can see that server did respond to our message, but it sent a long text that seems to have a format. That format is JSON. When we want to send a message to the server, we cannot just send any string like 'hello'. Our messages must have a format and a structure to them, exactly like how server responded to us. So we established that our meessages need to be in JSON format, but what's the structure then?

The message must be a JSON object with some fields. One of these fields is payloadType, which is an integer number, and is a neccessary field that must be present in all message. Another common (but not present in all messages) is payload, which is another JSON object with its own fields.

The server only understands a pre-defined set of messages, so by specifing the payloadType field, your're telling the server which message you're trying to send. Now we're able to select a specific message to send, but how would we send extra information that a message may need to convey? That's what's the payload field is for. What field(s) should the payload object have depends on what payloadType is being send.

Sending the First Message

The first message a client sends to server is a payloadType of 2100, which is called "Requesting application authentication". This message must have a payload with two required fields, one is clientId, and the other is clientSecret, and both fields must have string values which are part of the credentials you must acquire to be able to identify yourself to the server. So lets' send our firt proper message to the server.

const ws = new WebSocket('wss://live.ctraderapi.com:5036');
const { log } = console;

ws.onopen = function () {
log('connected to server');
const clientMsg = {
payloadType: 2100,
payload: {
clientId: '127f2f93c5c36feeed22a97174ce1f03bee9a71892caf6efca447415',
clientSecret: '32186df996aee51ab620852086f160ee67e36c7c673bd312b2',
},
};
ws.send(clientMsg);
};

ws.onmessage = function (event) {
const serverMsg = event.data;
log(`server sent a message: ${serverMsg}`);
};

ws.onclose = function () {
log('connection closed');
};

Results from running the code:

connected to server
server sent a message: {"payloadType":2101}

As you see from the results, the server repsonds with a payloadType of 2101, which means success. We will cover this in more detail later, but for now you should know that a payloadType that is one number greater than the one we send means success, and a payloadType of 2142 means failure.