Cannot connect to my account through Python package

Created at 25 Dec 2024, 14:08
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
AH

ahmdee

Joined 10.11.2024

Cannot connect to my account through Python package
25 Dec 2024, 14:08


I have a question
I'm trying to connect to my cTrader account through ctrader-open-api python package,
I ran all example codes that I could find, for example the ones in the "OpenApiPy" repo, or example codes in documentations,

All of them encounter an error when trying to authenticate my account, I mean when sending a ProtoOAApplicationAuthReq() request, it always comes back with a TimeoutError, I even increased responseTimeoutInSeconds when I was sending the request like client.send(request, ...) to 180 seconds wait, but did not change the outcome

That left me to believe that there's something wrong with the credentials used for authentication, so I even repeated the process of reading the docs and getting the credentials several times, so I'm sure from that side as well

I didn't know whether my cTrader desktop app should be open or closed before running the scripts so I even tried both ways and still the same issue

I just don't know what else to try.
I would appreciate any help on this matter...

————————————————————————————————

Since the only thing left for me to believe is that there is something wrong with the credentials, I wil explain the steps of getting the credentials in the following:

Part 1: Getting "Client ID" and "Client Secret"
1.  go this page https://openapi.ctrader.com/apps
2.  log-in if not already logged-in
3.  click "= Add new App"
   3.1.  fill in the mandatory fields: "Application name" and "Description"
   3.2  click "+ Add redirect URL"  once, (this is the default and cannot be used in code)
   3.3  click "+ Add redirect URL"  another time and provide a url
4.   click "Save"
5.  now must wait for Status of created entry to change from "Submitted" to "Active",
6.  now we have a "Client ID" and a "Client Secret"


Part 2:  Getting Authorization Code, and then the "AccessToken" and "RefreshToken"
1. must open below URL in browser:
   https://id.ctrader.com/my/settings/openapi/grantingaccess/
with below query parameters:
   redirect_uri=    from Part 1 step 3.3
   client_id=          from Part 1 step 6
   client_secret=  from Part 1 step 6

2. in opened page click "Allow access"

3. after clicking "Allow access", you will be redirected to a url that has a query parameter named "code", save its value

4. send a curl request like the following in under 60 seconds of previous step

   REDIRECT_URI=    same as before
   CLIENT_ID=            same as before
   CLIENT_SECRET=  same as before
   CODE=                     from previous step (Part 2 step 3)

curl -X GET "https://openapi.ctrader.com/apps/token?grant_type=authorization_code&code=%CODE%&redirect_uri=%REDIRECT_URI%&client_id=%CLIENT_ID%&client_secret=%CLIENT_SECRET%" -H "Accept: application/json" -H "Content-Type: application/json"

5. now you have the "AccessToken" and "RefreshToken"

done


@ahmdee
Replies

ahmdee
27 Dec 2024, 12:27 ( Updated at: 30 Dec 2024, 07:15 )

Here is the actual code that I'm running and the results of running it
from ctrader_open_api import Client, Protobuf, TcpProtocol, Auth, EndPoints
from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *
from ctrader_open_api.messages.OpenApiMessages_pb2 import *
from ctrader_open_api.messages.OpenApiModelMessages_pb2 import *
from twisted.internet import reactor
import json

credentialsFile = open('credentials.json')
credentials = json.load(credentialsFile)

client = Client('live.ctraderapi.com', 5035, TcpProtocol)

def onMessageReceived(client, message):
	print('msg', message)
def applicationAuthResponseCallback(result):
	print('app authenticated')
def onError(failure):
	print('err msg: ', repr(failure.value))
def disconnected(client, reason):
	print('Disconnected: ', reason.getErrorMessage())

def connected(client):
	print('Connected')
	request = ProtoOAApplicationAuthReq()
	request.clientId = credentials['ClientId']
	request.clientSecret = credentials['ClientSecret']
	deferred = client.send(request, responseTimeoutInSeconds=30)
	print('Sent request:  ProtoOAApplicationAuthReq')
	deferred.addCallbacks(applicationAuthResponseCallback, onError)

client.setConnectedCallback(connected)
client.setDisconnectedCallback(disconnected)
client.setMessageReceivedCallback(onMessageReceived)
client.startService()
reactor.run()


@ahmdee