Skip to main content
RapidDev - Software Development Agency
API AutomationsTwitchBearer Token

How to Automate Twitch Charity Donation Alerts using the API

Automate Twitch charity donation alerts using GET /charity/campaigns to fetch the active campaign, GET /charity/donations for real-time donor data, and EventSub channel.charity.campaign.donate subscription for push notifications. All three require the channel:read:charity scope with a User Access Token from the broadcaster — an App Access Token will not work. The 800 points/minute Helix bucket is rarely an issue since charity endpoints are low-traffic.

Need help automating? Talk to an expert
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate7 min read30-60 minutesTwitchMay 2026RapidDev Engineering Team
TL;DR

Automate Twitch charity donation alerts using GET /charity/campaigns to fetch the active campaign, GET /charity/donations for real-time donor data, and EventSub channel.charity.campaign.donate subscription for push notifications. All three require the channel:read:charity scope with a User Access Token from the broadcaster — an App Access Token will not work. The 800 points/minute Helix bucket is rarely an issue since charity endpoints are low-traffic.

API Quick Reference

Auth

User Access Token (broadcaster, channel:read:charity)

Rate limit

800 points/minute Helix bucket

Format

JSON

SDK

Available

Understanding the Twitch Charity API

The Twitch Charity API is part of Helix (base URL: https://api.twitch.tv/helix) and provides two REST endpoints: GET /charity/campaigns (returns the broadcaster's current active campaign with goal amount and currency) and GET /charity/donations (returns paginated donor entries with user name, amount, and timestamp). Both require the channel:read:charity scope in a User Access Token from the broadcaster specifically — not a moderator, not an App Access Token.

For real-time donation alerts during a stream, subscribe to the channel.charity.campaign.donate EventSub event type. This fires immediately when a donation is recorded and includes the donor name, amount, and campaign totals. EventSub WebSocket transport works well here since charity events are low-frequency and you do not need a public URL. The session_id from the WebSocket welcome message is used to create the subscription via POST /eventsub/subscriptions.

Note that Twitch charity features are only available to Partners and Affiliates running an officially approved charity campaign through Twitch. The charity API cannot be used to process payments or run external donation flows — it reads Twitch's own charity system. Full reference: https://dev.twitch.tv/docs/api/reference/#get-charity-campaign

Base URLhttps://api.twitch.tv/helix

Setting Up Twitch Charity API Authentication

The charity endpoints require a User Access Token from the broadcaster's account — not from a moderator or a separate bot account. The channel:read:charity scope must be explicitly requested during the Authorization Code OAuth flow. Refresh tokens for Confidential clients do not expire; store them securely and use them to refresh the access token before the ~60-day expiry.

  1. 1Register an app at dev.twitch.tv/console/apps if you have not already. Set Client Type to Confidential and add your redirect URI
  2. 2Build the authorization URL with the channel:read:charity scope: https://id.twitch.tv/oauth2/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&scope=channel:read:charity
  3. 3Have the broadcaster visit the URL and authorize the app — they will be redirected to your callback with a ?code= parameter
  4. 4Exchange the code for tokens: POST to https://id.twitch.tv/oauth2/token with grant_type=authorization_code
  5. 5Store the access_token and refresh_token in a secure database (encrypted)
  6. 6Also resolve the broadcaster's numeric user ID via GET /users?login=<username> and store it
  7. 7Validate the token hourly via GET https://id.twitch.tv/oauth2/validate and refresh on 401 responses
auth.py
1import os
2import requests
3
4CLIENT_ID = os.environ['TWITCH_CLIENT_ID']
5CLIENT_SECRET = os.environ['TWITCH_CLIENT_SECRET']
6ACCESS_TOKEN = os.environ['BROADCASTER_ACCESS_TOKEN'] # channel:read:charity scope
7BROADCASTER_ID = os.environ['BROADCASTER_ID']
8
9def helix_headers():
10 return {
11 'Authorization': f'Bearer {ACCESS_TOKEN}',
12 'Client-Id': CLIENT_ID
13 }
14
15def validate_token():
16 resp = requests.get(
17 'https://id.twitch.tv/oauth2/validate',
18 headers={'Authorization': f'OAuth {ACCESS_TOKEN}'}
19 )
20 if resp.status_code == 401:
21 raise Exception('Token expired — refresh needed')
22 return resp.json()
23
24def refresh_token(refresh_token_value: str) -> dict:
25 resp = requests.post(
26 'https://id.twitch.tv/oauth2/token',
27 data={
28 'grant_type': 'refresh_token',
29 'refresh_token': refresh_token_value,
30 'client_id': CLIENT_ID,
31 'client_secret': CLIENT_SECRET
32 }
33 )
34 resp.raise_for_status()
35 return resp.json()
36
37# Validate on startup
38token_info = validate_token()
39print(f'Token valid for user: {token_info.get("login")}')

Security notes

  • The broadcaster's User Access Token is sensitive — store it encrypted in a database, not in environment variables
  • Never share or log the full access token — it grants read access to the broadcaster's charity data
  • Validate the token hourly; users can revoke authorization at any time from their Twitch settings
  • Store CLIENT_ID and CLIENT_SECRET only in environment variables on your server
  • If the broadcaster revokes the app's authorization, all API calls return 401 — implement monitoring and re-authorization prompts
  • Use HTTPS for all OAuth redirect URIs — Twitch rejects HTTP redirect endpoints

Key endpoints

GET/charity/campaigns

Returns the broadcaster's currently active charity campaign including name, description, fundraising goal, current total raised, and currency. Returns an empty data array if no active campaign exists.

ParameterTypeRequiredDescription
broadcaster_idstringrequiredThe broadcaster's numeric user ID. The access token must be from this broadcaster's account.

Response

json
1{"data": [{"id": "campaign123", "broadcaster_id": "12345678", "broadcaster_name": "Ninja", "charity_name": "St. Jude Children's Research Hospital", "charity_description": "Fighting childhood cancer", "charity_logo": "https://example.com/logo.png", "charity_website": "https://stjude.org", "current_amount": {"value": 150000, "decimal_places": 2, "currency": "USD"}, "target_amount": {"value": 500000, "decimal_places": 2, "currency": "USD"}}]}
GET/charity/donations

Returns a paginated list of donations made to the active charity campaign. Each entry includes donor display name, amount, and currency. Use the cursor in response.pagination.cursor for pagination.

ParameterTypeRequiredDescription
broadcaster_idstringrequiredThe broadcaster's numeric user ID.
firstnumberoptionalNumber of results per page. Maximum 100.
afterstringoptionalPagination cursor from a previous response to get the next page.

Response

json
1{"data": [{"campaign_id": "campaign123", "user_id": "98765432", "user_name": "viewer1", "user_login": "viewer1", "amount": {"value": 500, "decimal_places": 2, "currency": "USD"}}], "pagination": {"cursor": "eyJiIjpudWxsLCJhIjp7Ik9mZnNldCI6MX19"}}
POST/eventsub/subscriptions

Creates an EventSub subscription for channel.charity.campaign.donate to receive real-time donation events. Use WebSocket transport with the session_id from the EventSub WebSocket welcome message.

ParameterTypeRequiredDescription
typestringrequiredUse 'channel.charity.campaign.donate' for individual donation events.
condition.broadcaster_user_idstringrequiredThe broadcaster's user ID whose charity donations to subscribe to.

Request

json
1{"type": "channel.charity.campaign.donate", "version": "1", "condition": {"broadcaster_user_id": "12345678"}, "transport": {"method": "websocket", "session_id": "<session_id>"}}

Response

json
1{"data": [{"id": "sub123", "status": "enabled", "type": "channel.charity.campaign.donate", "version": "1"}]}

Step-by-step automation

1

Fetch the Active Charity Campaign

Why: Before displaying donation alerts, you need the campaign ID, goal amount, and charity name to show context in your alerts and progress overlays.

Call GET /charity/campaigns?broadcaster_id=<id> with the broadcaster's User Access Token. Check that the data array is not empty — if it is, there is no active campaign. Extract the current_amount, target_amount, and charity_name for use in your alert formatting. The amount values are integers scaled by decimal_places (e.g., value=500, decimal_places=2 means $5.00).

request.sh
1curl -X GET 'https://api.twitch.tv/helix/charity/campaigns?broadcaster_id=12345678' \
2 -H 'Authorization: Bearer <broadcaster_user_access_token>' \
3 -H 'Client-Id: <client_id>'

Pro tip: The current_amount.value is an integer — divide by 10^decimal_places to get the human-readable amount. For USD, decimal_places=2, so value=500 means $5.00.

Expected result: Returns the active campaign object with charity name, goal, current total, and currency. Store the campaign_id for use in donation queries.

2

Subscribe to channel.charity.campaign.donate via EventSub

Why: Polling GET /charity/donations every few seconds is inefficient — EventSub push notifications fire immediately when a donation is recorded, giving sub-second alert latency.

Connect to the EventSub WebSocket at wss://eventsub.wss.twitch.tv/ws, capture the session_id from the welcome message, then create a channel.charity.campaign.donate subscription using POST /eventsub/subscriptions with the broadcaster's User Access Token. Each notification payload includes the donor's name, amount, and the updated campaign total.

request.sh
1# After getting session_id from WebSocket welcome message:
2curl -X POST 'https://api.twitch.tv/helix/eventsub/subscriptions' \
3 -H 'Authorization: Bearer <broadcaster_user_access_token>' \
4 -H 'Client-Id: <client_id>' \
5 -H 'Content-Type: application/json' \
6 --data '{
7 "type": "channel.charity.campaign.donate",
8 "version": "1",
9 "condition": {"broadcaster_user_id": "12345678"},
10 "transport": {
11 "method": "websocket",
12 "session_id": "<session_id_from_welcome>"
13 }
14 }'

Pro tip: Subscribe to channel.charity.campaign.progress as well — this fires when the campaign total updates and lets you show a live progress bar without polling GET /charity/campaigns.

Expected result: Your app receives a notification for every charity donation in real time. The event payload includes user_name, amount (with decimal_places), currency, campaign_id, and the updated campaign total.

3

Format and Display the Donation Alert

Why: Donation alerts need to show the donor name, formatted amount, campaign progress, and a link for viewers to donate — all within 2-3 seconds of the donation being received.

When a channel.charity.campaign.donate notification arrives, extract user_name, amount.value, amount.decimal_places, and the campaign total from the event payload. Convert the amount to a human-readable currency string. Post the formatted alert to Discord via an embed or to Slack via chat.postMessage. For an OBS stream overlay, emit it via a WebSocket connection to your overlay frontend.

request.sh
1# Post formatted donation alert to Discord webhook
2curl -X POST 'https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN' \
3 -H 'Content-Type: application/json' \
4 --data '{
5 "embeds": [{
6 "title": ":heart: Charity Donation!",
7 "description": "**viewer1** just donated **$5.00** to St. Jude!\n\nTotal raised: **$1,500.00 / $5,000.00**",
8 "color": 16711680,
9 "footer": {"text": "Donate at twitch.tv/ninja"}
10 }]
11 }'

Pro tip: The channel.charity.campaign.donate event payload already includes the updated campaign total amounts (campaign_current_amount and campaign_target_amount) — you do not need to call GET /charity/campaigns separately after each donation.

Expected result: A formatted Discord embed or console message displays the donor name, donation amount, and running campaign total within seconds of the donation being made.

Complete working code

This complete script connects to EventSub WebSocket for real-time charity donation events, formats each donation with the donor name and amount, posts an alert to Discord, and logs all donations to a local JSON file for post-stream reporting.

automate_charity_alerts.py
1import asyncio
2import json
3import os
4import time
5import logging
6import requests
7import websockets
8
9logging.basicConfig(level=logging.INFO)
10logger = logging.getLogger(__name__)
11
12CLIENT_ID = os.environ['TWITCH_CLIENT_ID']
13ACCESS_TOKEN = os.environ['BROADCASTER_ACCESS_TOKEN']
14BROADCASTER_ID = os.environ['BROADCASTER_ID']
15DISCORD_WEBHOOK_URL = os.environ.get('DISCORD_WEBHOOK_URL', '')
16LOG_FILE = 'charity_donations.json'
17
18def hdrs(json_content=False):
19 h = {'Authorization': f'Bearer {ACCESS_TOKEN}', 'Client-Id': CLIENT_ID}
20 if json_content:
21 h['Content-Type'] = 'application/json'
22 return h
23
24def fmt_amount(value, decimal_places, currency):
25 return f'{currency} {value / (10 ** decimal_places):,.2f}'
26
27def log_donation(donation):
28 donations = []
29 try:
30 with open(LOG_FILE, 'r') as f:
31 donations = json.load(f)
32 except FileNotFoundError:
33 pass
34 donations.append({'timestamp': time.time(), **donation})
35 with open(LOG_FILE, 'w') as f:
36 json.dump(donations, f, indent=2)
37
38def get_campaign():
39 resp = requests.get('https://api.twitch.tv/helix/charity/campaigns',
40 headers=hdrs(), params={'broadcaster_id': BROADCASTER_ID})
41 resp.raise_for_status()
42 data = resp.json()['data']
43 return data[0] if data else None
44
45async def on_donation(donation):
46 donor = donation.get('user_name') or 'Anonymous'
47 amount_str = fmt_amount(donation['amount']['value'],
48 donation['amount']['decimal_places'],
49 donation['amount']['currency'])
50 current_str = fmt_amount(donation['campaign_current_amount']['value'],
51 donation['campaign_current_amount']['decimal_places'],
52 donation['campaign_current_amount']['currency'])
53 target_str = fmt_amount(donation['campaign_target_amount']['value'],
54 donation['campaign_target_amount']['decimal_places'],
55 donation['campaign_target_amount']['currency'])
56 charity = donation.get('charity_name', 'the charity')
57 broadcaster = donation.get('broadcaster_user_name', '')
58 desc = (f'**{donor}** donated **{amount_str}** to {charity}!\n'
59 f'Total raised: **{current_str} / {target_str}**')
60 logger.info(f'Donation: {desc}')
61 log_donation(donation)
62 if DISCORD_WEBHOOK_URL:
63 requests.post(DISCORD_WEBHOOK_URL, json={'embeds': [{
64 'title': ':heart: Charity Donation!',
65 'description': desc,
66 'color': 16711680,
67 'footer': {'text': f'Donate at twitch.tv/{broadcaster.lower()}'}
68 }]})
69
70async def run():
71 campaign = get_campaign()
72 if not campaign:
73 logger.warning('No active charity campaign — waiting for one to start')
74 else:
75 logger.info(f'Campaign: {campaign["charity_name"]}')
76 while True:
77 try:
78 async with websockets.connect('wss://eventsub.wss.twitch.tv/ws') as ws:
79 welcome = json.loads(await ws.recv())
80 session_id = welcome['payload']['session']['id']
81 requests.post(
82 'https://api.twitch.tv/helix/eventsub/subscriptions',
83 headers=hdrs(True),
84 json={'type': 'channel.charity.campaign.donate', 'version': '1',
85 'condition': {'broadcaster_user_id': BROADCASTER_ID},
86 'transport': {'method': 'websocket', 'session_id': session_id}}
87 ).raise_for_status()
88 logger.info('Listening for charity donations...')
89 async for raw in ws:
90 ev = json.loads(raw)
91 if ev.get('metadata', {}).get('message_type') == 'notification':
92 d = ev['payload']['event']
93 await on_donation(d)
94 except Exception as e:
95 logger.error(f'Connection error: {e}. Reconnecting in 5s')
96 await asyncio.sleep(5)
97
98asyncio.run(run())

Error handling

401{"status": 401, "message": "Invalid OAuth token"}
Cause

The broadcaster's User Access Token has expired (~60 days) or they revoked the app's authorization from their Twitch settings.

Fix

Use the stored refresh token to get a new access token via POST https://id.twitch.tv/oauth2/token with grant_type=refresh_token. If refresh also returns 401, the broadcaster needs to re-authorize via the OAuth flow.

Retry strategy

Refresh the token immediately on 401. If refresh fails, send an alert to the broadcaster to re-authorize.

403{"status": 403, "message": "Missing scope channel:read:charity"}
Cause

The access token does not include the channel:read:charity scope. This happens if the broadcaster authorized the app before channel:read:charity was added to the scope list.

Fix

Ask the broadcaster to re-authorize the app. Build a new authorization URL that includes channel:read:charity in the scope parameter and have them visit it.

Retry strategy

Not retryable until the broadcaster re-authorizes with the correct scope.

404{"status": 404, "message": "No active charity campaign found"}
Cause

The broadcaster does not currently have an active Twitch charity campaign. GET /charity/campaigns returns an empty data array, not a 404, but EventSub subscriptions to channel.charity.campaign.donate may return 404 if there is no campaign.

Fix

Check for an empty data array before proceeding. Run GET /charity/campaigns before subscribing to EventSub to verify a campaign is active.

Retry strategy

Poll GET /charity/campaigns every 5 minutes until a campaign becomes active.

400{"status": 400, "message": "The broadcaster_user_id must be the same as the authenticated user"}
Cause

Attempting to access charity endpoints for a different broadcaster than the one who authorized the token. The channel:read:charity scope is broadcaster-specific.

Fix

Ensure the broadcaster_id in your query parameters matches the user ID of the account that authorized the app. Use GET /users (with the same token) to verify the authenticated user ID.

Retry strategy

Not retryable. Use the correct broadcaster's token and ID.

Rate Limits for Twitch Charity API

ScopeLimitWindow
Helix REST (per user access token)800 pointsper minute
EventSub WebSocket per client_id+user_idmax_total_cost 10across all WebSocket connections
retry-handler.ts
1import time
2import requests
3
4def helix_request_with_retry(method, url, headers, params=None, json=None, max_retries=3):
5 for attempt in range(max_retries):
6 resp = requests.request(method, url, headers=headers, params=params, json=json)
7 if resp.status_code == 429:
8 reset_ts = int(resp.headers.get('Ratelimit-Reset', time.time() + 30))
9 wait = max(reset_ts - int(time.time()), 1)
10 print(f'Rate limited. Waiting {wait}s')
11 time.sleep(wait)
12 continue
13 if resp.status_code == 401:
14 raise Exception('Token expired — refresh needed')
15 return resp
16 raise Exception('Max retries exceeded')
  • Charity endpoints are low-traffic — rate limits are rarely an issue, but still read Ratelimit-Remaining on every response to monitor your budget
  • Use EventSub for real-time donation events instead of polling GET /charity/donations every few seconds — EventSub is push-based and consumes no Helix quota while idle
  • The donation event payload includes the updated campaign totals — no need to call GET /charity/campaigns separately after each donation

Security checklist

  • Store the broadcaster's User Access Token in an encrypted database — it grants read access to their charity campaign data and should be treated as a secret
  • Store CLIENT_ID and CLIENT_SECRET only in server-side environment variables
  • Validate the token hourly via GET https://id.twitch.tv/oauth2/validate; implement monitoring so you know immediately if the broadcaster revokes authorization
  • Request only the channel:read:charity scope — do not request broader scopes than needed for this automation
  • Use HTTPS for all OAuth redirect URIs — Twitch enforces this
  • Log all donation alert deliveries for audit purposes in case of disputes or data discrepancies

Automation use cases

OBS Stream Overlay with Live Progress Bar

intermediate

Display a browser source overlay in OBS showing the charity goal progress bar, most recent donor, and running total — all updating in real time via WebSocket-to-frontend event emission.

Post-Stream Charity Report

beginner

After the stream ends, aggregate all donation events from the log file, compute top donors, average donation size, and total raised, then post a formatted report to Discord.

Milestone Celebration Triggers

intermediate

Subscribe to campaign progress events and trigger a special alert (sound effect, overlay animation, Discord @everyone) when the campaign crosses 25%, 50%, 75%, and 100% of the goal.

No-code alternatives

Don't want to write code? These platforms can automate the same workflows visually.

Zapier

Free tier (100 tasks/month); Starter from $19.99/month

Zapier's Twitch integration can trigger on certain channel events, but as of 2026 it does not natively support charity donation events — you would need to use a Catch Hook to receive EventSub notifications forwarded from your server.

Pros
  • + Easy to route charity alerts to 7,000+ apps once the trigger is set up
  • + No code needed for the routing and formatting logic
  • + Free tier for low-volume streams
Cons
  • - No native Twitch charity donation trigger — requires a custom webhook receiver to forward EventSub events
  • - Not truly no-code if you still need a server to handle EventSub verification
  • - Limited formatting customization on free/starter plans

Make

Free tier (1,000 ops/month); Core from $9/month

Make can receive EventSub webhook notifications for charity donations via its HTTP webhook module and route them to Discord, Slack, Google Sheets for donation logging, or any other app.

Pros
  • + 1,000 free operations/month
  • + Can handle HTTP webhook verification manually with an HTTP module response
  • + Google Sheets module for donation logging without a database
Cons
  • - Webhook EventSub transport requires a public URL — Make provides this, but configuration is complex
  • - Still requires webhook challenge verification logic in the HTTP module
  • - Not suited for OBS overlay use cases

n8n

Self-hosted free; Cloud Starter from €20/month

n8n can receive EventSub webhooks and process charity donation events, route them to Discord or Slack, and log them to a database — all without writing code.

Pros
  • + Native webhook node with custom response capability for EventSub challenge verification
  • + Discord and Slack nodes for zero-code alert delivery
  • + Self-hosted option with no per-execution cost
Cons
  • - Webhook EventSub transport requires a public URL for the n8n instance
  • - Setting up EventSub webhook challenge verification in n8n requires careful response configuration
  • - WebSocket EventSub transport is not natively supported in n8n

Best practices

  • Verify that a charity campaign is active via GET /charity/campaigns before subscribing to EventSub events — subscriptions to non-existent campaign events may fail silently
  • Store donation events in a database or JSON file during the stream so you can generate a post-stream report even if your alert delivery fails mid-stream
  • The donation event payload includes campaign_current_amount and campaign_target_amount — use these directly rather than making an extra API call to GET /charity/campaigns per donation
  • Convert integer amount values to human-readable currency using the decimal_places field (e.g., value=500, decimal_places=2 means $5.00) before displaying them
  • Implement WebSocket reconnection logic — if your process crashes during the stream, reconnect and resubscribe automatically
  • Validate the broadcaster's User Access Token at startup and hourly — a revoked token will silently stop delivering donation events

Ask AI to help

Copy one of these prompts to get a personalized, working implementation.

ChatGPT / Claude Prompt

I'm building a Twitch charity donation alert system using the Helix API. I have a broadcaster User Access Token with channel:read:charity scope. I'm subscribing to channel.charity.campaign.donate via EventSub WebSocket. Issue: [describe your problem — e.g., 'GET /charity/campaigns returns empty data array', 'donation amounts are displaying incorrectly', 'EventSub subscription returns 403']. My broadcaster_id: [ID]. Token scopes verified: channel:read:charity. What is wrong with my charity API setup?

Lovable / V0 Prompt

Build a Twitch charity donation alert overlay for OBS Browser Source. The overlay should show a card at the bottom of the screen whenever a donation comes in, displaying the donor name, amount, and a brief thank-you message. The card should animate in from the right, stay for 5 seconds, then fade out. Also show a persistent progress bar at the bottom showing current raised / goal amount as a percentage. Connect to a local WebSocket at ws://localhost:8765 that emits JSON events with {type: 'donation', donor, amount, currency, current_total, target_amount} and {type: 'progress', current, target, percentage}. Style it to look like a Twitch-branded overlay (purple accent color #9147FF).

Frequently asked questions

Why do I get 401 when calling GET /charity/campaigns?

This endpoint requires a User Access Token from the broadcaster's account — not an App Access Token from Client Credentials. Make sure the broadcaster authorized your app with the channel:read:charity scope. If they did authorize but you're still getting 401, the token may have expired (~60 days) or been revoked. Use your stored refresh token to get a new access token.

Why does GET /charity/campaigns return an empty data array?

The broadcaster does not have an active Twitch charity campaign. Charity campaigns must be approved and started through Twitch's official charity program, available to Partners and Affiliates. An empty data array (not a 404) is the expected response when no campaign is running.

Can I use this API to accept donations outside of Twitch's charity system?

No. The Twitch charity API only reads data from Twitch's own charity campaign feature — it cannot process external donations, connect to third-party fundraising platforms, or access Streamlabs/StreamElements charity integrations. For custom donation systems, you would use those platforms' own APIs.

How do I convert the donation amount to a dollar amount?

Twitch returns amounts as integers scaled by decimal_places. Divide value by 10^decimal_places to get the human-readable amount. For example, value=500 with decimal_places=2 equals $5.00. Always use the decimal_places field from the response rather than assuming a fixed divisor — different currencies may have different decimal place conventions.

Can I subscribe to charity donation events for a channel I don't own?

No. The channel:read:charity scope must be granted by the broadcaster themselves — you cannot access another broadcaster's charity data with your own token. The broadcaster needs to authorize your app via the OAuth flow.

Is the Twitch charity API free?

Yes, the Twitch Helix API including charity endpoints is free with no per-request charges. Twitch's charity campaign feature itself requires Partner or Affiliate status and approval from Twitch. There are no API fees.

Can RapidDev help build a custom charity stream overlay and alert system?

Yes. RapidDev has built 600+ apps including stream overlay systems, real-time donation displays, and Twitch integrations. Book a free consultation at rapidevelopers.com.

RapidDev

Need this automated?

Our team has built 600+ apps with API automations. We can build this for you.

Book a free consultation

Skip the coding — we'll build it for you

Our experts have built 600+ API automations. From prototype to production in days, not weeks.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.