Broker API HubMenu

cTrader Open API Python quickstart

cTrader Open API in Python: register an app, get a token by OAuth or the Playground, install OpenApiPy and list your accounts on the demo host.

Independent and unofficialChecked Code not yet run on a demo account

Risk warning: CFDs and spread bets are complex instruments and come with a high risk of losing money rapidly due to leverage. You can lose money on these products, and each provider publishes its own loss figure under FCA rules. You should consider whether you understand how they work and whether you can afford to take the high risk of losing your money. Automated and API trading can amplify losses through bugs, connectivity failures and runaway orders.

Demo accounts only. Credentials are read from environment variables on your own machine. No field on this site asks for a key, a username or a password.

Steps

  1. Register an app

    Register at the cTrader Open API Portal (openapi.ctrader.com) with a cTID. Describe your use case in detail and give a valid redirect URL. Spotware reviews new apps and you need its approval before you start coding.

    help.ctrader.comchecked

  2. Get a test token from the Playground

    Once approved, the Playground button on your Applications page gives an access token for your own cTID, so you can skip building the OAuth flow while you test.

    help.ctrader.comchecked

  3. Or run the OAuth flow

    Send the user to id.ctrader.com with client_id, redirect_uri, scope and product=web. Ask for scope accounts (view only), not trading. The code lasts one minute; exchange it at openapi.ctrader.com/apps/token for an access token (about 30 days) and a refresh token that does not expire but works once.

    Python
    import os
    from ctrader_open_api import Auth
    
    # App credentials from openapi.ctrader.com, kept in environment variables
    auth = Auth(os.environ["CTRADER_CLIENT_ID"],
                os.environ["CTRADER_CLIENT_SECRET"],
                os.environ["CTRADER_REDIRECT_URI"])
    print("Open this URL and approve the accounts scope:")
    print(auth.getAuthUri())
    # After approval, copy the code from the redirect within one minute, then:
    # token = auth.getToken(os.environ["CTRADER_AUTH_CODE"])
    # Store token values in your own secret store, not in code.
    
    JavaScript
    // Node 18 or later. Builds the authorisation URL; the user approves in a browser.
    const params = new URLSearchParams({
      client_id: process.env.CTRADER_CLIENT_ID,
      redirect_uri: process.env.CTRADER_REDIRECT_URI,
      scope: "accounts",  // view only; do not request trading yet
      product: "web"
    });
    console.log(`https://id.ctrader.com/my/settings/openapi/grantingaccess/?${params}`);
    
    curl
    # Exchange the one minute authorisation code for tokens (values from env vars)
    curl -X GET "https://openapi.ctrader.com/apps/token?grant_type=authorization_code&code=$CTRADER_AUTH_CODE&redirect_uri=$CTRADER_REDIRECT_URI&client_id=$CTRADER_CLIENT_ID&client_secret=$CTRADER_CLIENT_SECRET"
    

    help.ctrader.comchecked

  4. Install OpenApiPy

    Spotware's Python package is ctrader-open-api on PyPI, version 0.9.2 from 26 Jun 2024, for Python 3.8 or later. It is asynchronous, built on Twisted, and methods return Twisted deferreds. MIT licence.

    Python
    pip install ctrader-open-api
    
    JavaScript
    // The Open API runs over TCP or WebSocket with Protobuf or JSON messages,
    // not REST. Use the Python tab (OpenApiPy) or Spotware's C# package.
    
    curl
    # The Open API is not a REST API, so there is no curl call for this step.
    # Use the Python tab.
    

    pypi.orgchecked

  5. Connect to demo

    Demo is demo.ctraderapi.com and live is live.ctraderapi.com, port 5035 for Protobuf and 5036 for JSON. The environments are fully separated: demo accounts cannot be used on the live host.

    help.ctrader.comchecked

  6. First call: list your accounts

    Authorise the app with ProtoOAApplicationAuthReq (client ID and secret), then send ProtoOAGetAccountListByAccessTokenReq with the access token. Each account comes back with ctidTraderAccountId, isLive and brokerTitleShort. ProtoOAAccountAuthReq comes next, before any account data.

    Python
    import os
    from twisted.internet import reactor
    from ctrader_open_api import Client, Protobuf, TcpProtocol, EndPoints
    from ctrader_open_api.messages.OpenApiMessages_pb2 import (
        ProtoOAApplicationAuthReq, ProtoOAGetAccountListByAccessTokenReq)
    
    # Demo host only. Read only: no order messages in this script.
    client = Client(EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
    
    def on_accounts(message):
        res = Protobuf.extract(message)
        for acc in res.ctidTraderAccount:
            print(acc.ctidTraderAccountId, "live" if acc.isLive else "demo", acc.brokerTitleShort)
        reactor.stop()
    
    def on_app_auth(_):
        req = ProtoOAGetAccountListByAccessTokenReq()
        req.accessToken = os.environ["CTRADER_ACCESS_TOKEN"]
        client.send(req).addCallbacks(on_accounts, on_error)
    
    def on_error(failure):
        print("Error:", failure)
        reactor.stop()
    
    def connected(_):
        req = ProtoOAApplicationAuthReq()
        req.clientId = os.environ["CTRADER_CLIENT_ID"]
        req.clientSecret = os.environ["CTRADER_CLIENT_SECRET"]
        client.send(req).addCallbacks(on_app_auth, on_error)
    
    client.setConnectedCallback(connected)
    client.startService()
    reactor.run()
    
    JavaScript
    // The Open API runs over TCP or WebSocket with Protobuf or JSON messages,
    // not REST. Use the Python tab (OpenApiPy) or Spotware's C# package.
    
    curl
    # The Open API is not a REST API, so there is no curl call for this step.
    # Use the Python tab.
    

    help.ctrader.comchecked

  7. Stay under the limits

    Spotware allows 50 requests per second per connection, and 5 per second for historical data. Going over returns REQUEST_FREQUENCY_EXCEEDED (108).

    help.ctrader.comchecked

cTrader Open API limits to pace against

LimitValueScopeSource
Requests a second, not historical data50Per connection, requests that are not for historical datahelp.ctrader.comchecked
Requests a second, historical data5Per connection, historical data requests onlyhelp.ctrader.comchecked

Sources

Sections