Why is custom_reward.id exposed in frontend GQL but blocked in Helix API? (Inconsistency report)

Hi everyone,

I’ve come across an inconsistency in the way Twitch handles Channel Points Custom Rewards across its frontend and backend APIs.


:puzzle_piece: The issue

As developers, we can observe that:

  • When visiting a Twitch channel (not our own), the custom_reward.id values are exposed in the GraphQL responses.
  • These IDs are required if you want to reference a specific reward in any system.
  • However, calling the Helix endpoint /helix/channel_points/custom_rewards?broadcaster_id=XXX results in a 403 Forbidden unless the token belongs to the broadcaster.

This is confusing because:

  • The ID is not sensitive.
  • The data is already visible in the frontend to anyone using DevTools.
  • There’s no security gain from blocking it at the Helix level.

:link: Full issue report here:

:backhand_index_pointing_right: GitHub Issue #1080


:red_question_mark: My question

Why is this inconsistency present?
Was it intentional to restrict reward ID visibility in Helix despite exposing it in GQL?
If so, could the rationale be documented?

It’s hard to build useful tools (like overlays, bots, analytics) around Channel Points when critical identifiers are public in UI but blocked in API.

Would love to hear thoughts from other devs or from the Twitch API team. :folded_hands:

What the front end does/doesn’t do compared to the supported third party api is irrelevant

I can get the ID’s for rewards from helix fine after getting permissions from the broadcaster to operate on the broadcasters data.

This isn’t a bug.

You are supposed to get permission from the broadcaster to operate on the broadcasters data.

Not just as this allows the user to unlink and then you can monitor and remove data you should not longer be storing.

But allows you to use authorised resources on behalf of the broadcaster, and use other products such as eventsub to recieve data.

Get permission from the broadcaster, let alone you need permission if you are the one creating the rewards and/or managing the redeems.

To build useful tools you need to be getting relevant permissions from the broadcaster, even if doing so is a pure a thing as being legally allowed to retain the broadcasters data wrt to relevant privacy laws and/or have a point of contact with users in the event something goes wrong and they need to be contacted, again wrt to relevant privacy laws.

1 Like

Thanks for the detailed response, Barry.

However, I’d like to clarify that my original concern isn’t about whether the Helix endpoint is behaving as currently documented or if proper permissions are required under the current implementation.

The issue I’m pointing out is more fundamental — it concerns a violation of architectural consistency in how Twitch handles data visibility across layers of its platform.

Specifically:

  • The custom_reward.id is publicly exposed via unauthenticated GraphQL queries in the frontend UI, even when viewed by users who are not the broadcaster.
  • The same ID is then considered protected when accessed via the Helix API, resulting in a 403 Forbidden unless the request includes a broadcaster-scoped token.

This creates a contradiction in the system’s access control boundaries. If a piece of data is exposed in the frontend without restriction, the system is implicitly treating it as public. Treating it as private in Helix — while still showing it in the UI — results in an inconsistency that weakens the platform’s architectural integrity.

This is not a matter of whether permissions are required. It’s a matter of the data exposure model being self-contradictory.

In a well-aligned architecture:

  • If a field is considered public, it should be safely accessible from all official APIs, at least in a read-only context.
  • If a field is considered private, it should not be exposed in unauthenticated frontend GraphQL responses.

The current behavior suggests the frontend and API were designed or evolved independently, leading to this divergence.

This isn’t about “working as intended” — it’s about “designing with coherent intent.”

As developers building tools like overlays, bots, and analytics, we rely on clarity and consistency between the platform’s behavior and its APIs. Discrepancies like this force us into unofficial workarounds, which ultimately benefit neither Twitch nor the developer ecosystem.

I would encourage the team to consider whether this is simply a missed alignment between frontend and backend responsibility boundaries — and whether it might be worth updating either the frontend to restrict this exposure, or Helix to permit it in a safe, read-only fashion.

Thanks again for the discussion.

It has to be visible on the Front end becuase the front end has the “shop” that allows people to “obtain” the redeem.

There is no way via third party API’s to “obtain” the redeem on behalf of a viewer.

It’s a different use case, to power something that third parties can’t do.

Again, if you are operating on broadcaster data here, you should be getting broadcaster permission to operate on the broadcasters data.

So I don’t see a problem here as the described use case should be getting broadcaster permission.

1 Like

Thanks for the clarification — and I absolutely understand the permission model.

But to be clear, I’m not debating whether broadcaster permission is required for operations.
I’m pointing out that the architectural boundary for visibility is currently broken.

In proper software architecture, data access control should be layered consistently:

  • If a field is private, it should be protected across all layers — frontend, GraphQL, API.
  • If a field is public, it should be accessible consistently, even if read-only.

The problem is not about “should 3rd parties be allowed to redeem rewards.”
It’s that reward IDs are exposed via public GraphQL, yet Helix treats them as protected.
That’s not a policy problem — that’s a leaky abstraction, and it’s an architectural concern.

Systems should not conditionally expose identifiers based on how someone happens to reach them (frontend vs API).
That’s not permission handling — that’s architectural inconsistency.

I appreciate the explanation, but unless that design inconsistency is addressed or acknowledged, it remains a structural issue, not a use case misunderstanding.

Why does it matter what is done via GQL? That’s 1st party and not something you should be directly interacting with in any way, how it works and what it does is entirely beyond the scope of 3rd parties (and these forums for the 3rd party community).

How Twitch choose to engineer their 1st party services is entirely separate from how they might engineer their 3rd party services. They could match perfectly, they could be entirely inconsistent, as a developer that shouldn’t impact you because the 3rd party API is all you should be working with and not trying to use GQL.

1 Like

To clarify — this is not just about what I want as a developer.

It’s about what any developer should reasonably expect from a well-architected platform.

When a value like custom_reward.id is publicly exposed in unauthenticated frontend responses (via GQL), but hidden in the official 3rd-party API (Helix), that reveals an inconsistency in access layer design.

This is not about gaining privileged access, but about aligning the system’s public-facing layers with consistent and predictable access semantics.

Whether you’re a 1st-party or 3rd-party developer, predictable API behavior matters.

The concern here is architectural — and correcting it benefits not just me, but the entire ecosystem.

Thanks again for engaging in this discussion.

Just a quick update:

I’ve updated the UserVoice suggestion to reflect the core architectural concern more clearly.
Here’s the new link:

https://twitch.uservoice.com/forums/310213-developers/suggestions/49996068-restore-consistency-for-custom-reward-id-visible

The intention remains the same — to highlight the inconsistency in how custom_reward.id is handled across frontend GQL vs Helix API.

Thanks again for the feedback so far, and I hope this revised post helps refocus the discussion on consistency and access model clarity.

These responses read like AI slop…