Creating Channel Points Redemptions Not Working

I am trying to create new redemption programmatically. I followed the API, but am having issues with the final step.

This was used to get the users Access Token

var access_token = parsedHash.get(‘access_token’);

document.getElementById(‘authorize’).setAttribute(‘href’, ‘https://id.twitch.tv/oauth2/authorize?client_id=’ +
client_id + ‘&redirect_uri=’ + encodeURIComponent(redirect) + ‘&response_type=code’ + ‘&scope=channel:manage:redemptions’)

Followed by this

fetch(
                'https://api.twitch.tv/helix/users',
                {
                    "headers": {
                        "Client-ID": client_id,
                        "Authorization": "Bearer " + access_token
                    }
                }
            )

After getting that token I used Axios to post command and get the access_token and refresh_token

axios.post(`https://id.twitch.tv/oauth2/token?client_id=${client_id}&client_secret=${client_secret}&code=${code}&grant_type=authorization_code&redirect_uri=${redirectURL}`)
                    .then(response => {
                        console.log(response.data)
                        access_token = response.data.access_token
                        refresh_token = response.data.refresh_token
                    }).catch(function (error) {
                        console.log(error);
                    })

Finally after getting the access_token and refresh_token I used Axios to post command to create the new custom redemption

axios.post(‘https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id={broadcaster_id}’, {
headers: {
“Client-ID”: client_id,
“Authorization”: "Bearer " + access_token
},
}, {
“title”: “game analysis 1v1”,
“cost”: 50000
}).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.log(error);
})

The error that I’m given is

data: {
error: ‘Unauthorized’,
status: 401,
message: ‘OAuth token is missing’
}

I don’t quite understand your code, you seem to be doing things out of order, mixing things from different OAuth flows and request libraries.

From the looks of this you’re trying to get the access token from the URL Hash, yet that’s not the OAuth flow you’re using so there wont be an access token in the URL.

You’ve got a request to the Users endpoint before you’ve even got the access token? After the user is redirected to your redirect URI you’ll only have the code at that point, not an access token.

As for your final request, to the custom rewards endpoint, your arguments are in the wrong order, you’re using axios.post(url, config, data), when it’s expecting axios.post(url, data, config), so you’re getting an OAuth token is missing error because you’re sending your data as the config object (of which none of the fields will actually do anything as there isn’t a title or cost request option.

So for the first part, I took the code from Barry Carlyon’s Github where he had created a website to get you the access_token. And simply changed the client_id, redirect url, and added a scope in order for it to work with channel point redemption. It does give me a code, but I am unsure after what you said if its the access token or just a code. When using it later to get the access token and refresh token it seems to work fine.

If you look at Barry’s code, his example uses response_type=token, which is for the Implicit Auth Flow, as shown by the docs he has also linked in the example. https://dev.twitch.tv/docs/authentication/getting-tokens-oauth#oauth-implicit-code-flow

The implicit auth flow returns an Access Token in the URL hash, and is intended for use client-side.

You’re using response_type=code, which is for the Authorization Code flow, documented here: https://dev.twitch.tv/docs/authentication/getting-tokens-oauth#oauth-authorization-code-flow

The Auth Code flow doesn’t return any URL hash, it returns a code in the querystring params, which your backend server needs to then exchange for an Access Token and Refresh token. This auth flow is for making requests server-side, as your frontend wont have access to the client secret needed to exchange that code for tokens.

Ok, I am confusing myself and you when explaining this. I want to make these requests to create new channel redemptions server side. This is why I changed it to token_type=code.
After getting this code on the client-side I manually put it in my server-side code (just for now while testing) so that I get the access token and refresh token as shown in my very first message I posted. After getting the access token and refresh token I then try to make the request for a creation of a new redemption. That is where I feel I am having issues.

Output after requesting an access and refresh token

{
access_token: ‘#####################’,
expires_in: 15552,
refresh_token: ‘###################’,
scope: [ ‘channel:manage:redemptions’ ],
token_type: ‘bearer’
}

I have changed the post request to look like this:
axios({
method: ‘post’,
url: ‘https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id={broadcaster_id}’,
data: {
“title”: “game analysis 1v1”,
“cost”: 50000
},
config: {
“Client-ID”: client_id,
“Authorization”: "Bearer " + access_token
}
}).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.log(error);
})

With still no success

data: {
error: ‘Unauthorized’,
status: 401,
message: ‘OAuth token is missing’
}

That is not the correct format for axios config. GitHub - axios/axios: Promise based HTTP client for the browser and node.js

The options being passed should be

{
  headers: {
    "Client-ID": client_id,
    "Authorization": "Bearer " + access_token
  }
}

You were right about the misformat on the Axios library. But it brings a new issue.

data: {
error: ‘Unauthorized’,
status: 401,
message: ‘incorrect user authorization’
}

On every request for an access and refresh token, it always says that manage channel redemptions is within my scope. So unsure why it is saying incorrect user authorization.

Ex:
{
access_token: ‘#######################’,
expires_in: 15294,
refresh_token: ‘######################’,
scope: [ ‘channel:manage:redemptions’ ],
token_type: ‘bearer’
}

First, don’t EVER share access tokens or refresh tokens. they are to be treated as confidential tokens and as such to share them is a violation of the developer agreement. Because you’ve leaked the token I’ve just revoked it so that it can’t be misused.

Secondly, just to check, does the user going through the OAuth flow match that of the channel you’re trying to use the channel points endpoints for? eg, if you go through the OAuth flow, you can only use that OAuth token with your broadcaster id.

If I understand you yes, I created an app in the dev console. Got the client id and client secret. Client-side when I make the request for the code I use the client id I got from the app and use the redirect uri from the same app. Server-side I use the same client id and client secret from the app to complete everything. The only issue I may see is my Broadcaster_id is incorrect. It is the same id that I use when using the twitch pubsub, but there its called the “channel_id” in the documentation. Are those two different things?

user/channel/broadcaster id are all the same thing, they are just named differently depending on context.

If you’re sure the id is correct, then the only other thing I can suggest is you double check your URL that you’re posting to.

I’m not sure if the code you pasted here lost some syntax or formatting in pasting, but url: ‘https://api.twitch.tv/helix/channel_points/custom_rewards?broadcaster_id={broadcaster_id}’ will send the post to that exact URL, you need to add your id to the broadcaster_id param, because based on what you’ve pasted you’re literally sending the text {broadcaster_id}, rather than 123456 or whatever your id is.

Idk why it lost the $ when pasting, I actually have it written as so
broadcaster_id=${broadcaster_id}
So it definitely does replace it with the proper number.

I am entirely unsure why it is giving me that error. I get an access token, refresh token, all while using the same broadcaster id, client id, and client secret.

Most likely the forum is removing it as you are just pasting code in and not telling the forum it’s code, so it does some odd stuff when you paste code and don’t tell it it’s not code. Sometimes you do this correctly and sometimes you don’t

So, to see where we are now can you post your current code that you are using? And correctly format it

Paste it in, select it all and hit

image

Or start every code line with (at least) four spaces (and a new line above/below the code block

I actually found out that I was wrongly logged into the incorrect twitch login when testing, resulting in the Auth token not working properly. It works perfectly now. The issue I am having now though is when creating new redemptions the images are not showing up.

{
    title: 'Test',
    cost: 50,
    background_color: "#00E5CB",
    prompt: "You bought something",
    image: {
        url_1x: 'https://static-cdn.jtvnw.net/custom-reward-images/69905566/08fd74e8-7e1e-4861-b4d4-1ff2dd938c9a/61f01a02-3833-4f32-8a29-a97760ebedbc/custom-1.png',
        url_2x: 'https://static-cdn.jtvnw.net/custom-reward-images/69905566/08fd74e8-7e1e-4861-b4d4-1ff2dd938c9a/61f01a02-3833-4f32-8a29-a97760ebedbc/custom-2.png',
        url_4x: 'https://static-cdn.jtvnw.net/custom-reward-images/69905566/08fd74e8-7e1e-4861-b4d4-1ff2dd938c9a/61f01a02-3833-4f32-8a29-a97760ebedbc/custom-4.png'
    },
    background_color: '#1F69FF',
},

You cannot set the image via the API

There is a uservoice for this functionality here

thats what i was looking for :slight_smile: ty…i just could not figure out were to go to make some challenges for games i play but now that i do i can :slight_smile: :slight_smile:

Is there a list of things you can and cannot change? For example it doesn’t seem like I can change the background_color of the redemption.

Background color works, I’ve done it. Make sure your hex code is all capitals. I think that was a gotcha for a bunch of people.

Yes refer to the documentation:

It lists the currently supported fields

This was raised as a docs bug and instead fixed to support aNyCaSe

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.