I am writing a twitch chat bot to use EventSub over websockets. I have two accounts: account 1 is the streamer account (ex. DoomerCreatine) and a second account that is the bot (ex. BotAccount). The BotAccount has an app registered and I have the client id and secret for that. The BotAccount is also a moderator in the streamer account’s chat.
So far what I’ve done is:
- Navigate to user authentication url with following (url encoded):
https://id.twitch.tv/oauth2/authorize \
?response_type=token \
&client_id=<BOT CLIENT ID> \
&redirect_uri=http://localhost:3000 \
&scope=user:bot
+channel:bot
+user:read:chat
+user:write:chat
+channel:read:subscriptions \
&state=<STATE STRING>)
This is successful and returns a user token for my stream account. Per Barry’s posts, here and here, I discard this token and then request a client_credentials
token for the bot account to utilize the ‘two-legged’ approach that Barry describes, where the user first authorizes the client and then the client requests client credentials.
With this token I am able to subscribe to the channel.chat.message
EventSub and it returns a success. I am able to see chat messages and I can also send via the https://api.twitch.tv/helix/chat/messages
endpoint from the bot account.
Connected. Session_id: <SESSION ID>
{
"data": [
{
"id": "d9ab6f61-c65f-4c36-9649-65e02f1deec4",
"status": "enabled",
"type": "channel.chat.message",
"version": "1",
"condition": {
"broadcaster_user_id": <BROADCASTER ID>,
"user_id": <BOT ID>
},
"created_at": "2024-08-31T20:03:38.068156739Z",
"transport": {
"method": "websocket",
"session_id": <SESSION ID>,
"connected_at": "2024-08-31T20:03:37Z"
},
"cost": 0
}
],
"total": 7,
"max_total_cost": 10,
"total_cost": 0
}
However, if I try to subscribe with the following payload to monitor resub messages:
data = {
'type': 'channel.subscription.message',
'version': '1',
'condition': {
'broadcaster_user_id': <BROADCASTER_ID>
},
"transport": {
"method": "websocket",
"session_id": <SESSION ID>}
}
I receive the following response:
{
"error": "Forbidden",
"status": 403,
"message": "subscription missing proper authorization"
}
Both of these subscriptions use the same headers:
headers = {
"Authorization": "Bearer <CLIENT CREDENTIAL TOKEN>",
"Client-Id": <CLIENT ID>,
"Content-Type": "application/json"
}
I’ve also tried this method with the Authorization code grant flow
workflow where I obtain a code first then request a token and refresh token. This results in the same outcome: I can subscribe to messages but not subscriptions.
I appreciate any help/guidance, thanks!