Sounds like some form of token issue, what user are you running as? What type of Token does the user possess? This isn't an issue I have seen.
I am in the process of creating a QES wrapper in Python (very early build below). Maybe you can see something in there that is missing or different to what you have done?
There are a couple of things I am not happy with (namely the global variables). But this is an extremely early build.
Thanks for the response and sharing your gist.
I'm using the Qlik Proxy Service to issue a ticket for authentication - I see your method does not use that API. I am also not incrementing my "id" on every request - it is "0" for all requests; the docs say this field is not required: "Identifier established by the initiator of the request. If this member is not present, the rpc call is assumed to be a notification." - but what is a "notification" in Qlik's terms?
Does your gist work right out of the box? I updated the necessary fields and wasn't about to get it to run without throwing an error (websocket._exceptions.WebSocketConnectionClosedException: socket is already closed.) - I think this my be because you are using 'wss://server.foo:4747' and I'm using 'ws://server.foo/app/' (notice wss:// vs ws:// - regardless, neither option worked for me). I've also created a gist of my code here: Python QES Test · GitHub
I have just tested this with a brand new install of Qlik Sense (on my old server, but deleted all the content). Seemed to work ok.
The below gif shows the process of a new machine. As you can see I got the socket already closed when the SSL failed (no certs).
As for your other questions, I do not believe ID is necessary, I was simply replicating what I saw in the Dev-Hub.
And yeah, I am connecting to the engine directly, so not going through the proxy, no need for a ticket to be established. The engine does this.
Honestly, the code in my Gist isn't very good, needs to be refactored completely and rethought. It does what it does, but not elegantly.
We have a 5 session limit that we enforce. I.e a user can only have 5 concurrent sessions running after that we will shut down subsequent connections. This is mainly to allow a user to run 5 sessions from 5 different devices / browsers.
So if your requests are originating from the same process it sounds like you are authenticating for every connection.
Instead you can re-use the session cookie from your first connection and then you won't run into the 5 session limit.
Here is a example, albeit not in python but for Node but I think it's pretty easy to follow: beyond5sessionlimit.js · GitHub
The other option is since it sounds like you are building a server-side component you can bypass the proxy and connecting directly against QIX instead. Typically you would establish a websocket connection to wss://server:4747/app/<appguid> and supply the service certificates that you can export from QMC and a X-Qlik-User header indicating which user you want to connect as. This will not consume tokens.
Also feel free to join us on Slack, lot's of members there have built custom clients before and are happy to help