@jskit-ai/connectors-catalog 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +192 -0
- package/docs/ai-upstream-notices.md +51 -0
- package/docs/ai.md +191 -0
- package/docs/airtable.md +130 -0
- package/docs/algolia.md +190 -0
- package/docs/amazon-redshift.md +229 -0
- package/docs/amplitude.md +210 -0
- package/docs/apify.md +162 -0
- package/docs/apollo-io.md +200 -0
- package/docs/asana.md +126 -0
- package/docs/ashby.md +188 -0
- package/docs/atlassian.md +224 -0
- package/docs/attention.md +162 -0
- package/docs/aws-athena.md +150 -0
- package/docs/aws-credentials.md +75 -0
- package/docs/aws-s3.md +193 -0
- package/docs/bigquery.md +146 -0
- package/docs/brevo.md +122 -0
- package/docs/calendly.md +158 -0
- package/docs/canva.md +191 -0
- package/docs/chargebee.md +192 -0
- package/docs/clay.md +194 -0
- package/docs/clickhouse.md +242 -0
- package/docs/confidence-exp.md +74 -0
- package/docs/confidence-flags.md +75 -0
- package/docs/confidence-oauth.md +137 -0
- package/docs/contentful.md +123 -0
- package/docs/databricks.md +180 -0
- package/docs/dbt-semantic-layer.md +175 -0
- package/docs/elevenlabs.md +102 -0
- package/docs/figma.md +132 -0
- package/docs/firebase-cloud-messaging.md +262 -0
- package/docs/firecrawl.md +137 -0
- package/docs/fireflies.md +95 -0
- package/docs/fireworks-ai.md +53 -0
- package/docs/gatewayapi.md +113 -0
- package/docs/gemini-enterprise.md +224 -0
- package/docs/github-api.md +133 -0
- package/docs/gitlab-api.md +138 -0
- package/docs/gmail.md +133 -0
- package/docs/gong.md +205 -0
- package/docs/google-ads.md +156 -0
- package/docs/google-analytics.md +202 -0
- package/docs/google-docs.md +105 -0
- package/docs/google-drive.md +108 -0
- package/docs/google-maps-platform.md +208 -0
- package/docs/google-oauth.md +123 -0
- package/docs/google-search-console.md +124 -0
- package/docs/google-sheets.md +94 -0
- package/docs/google-slides.md +95 -0
- package/docs/granola.md +178 -0
- package/docs/hex.md +161 -0
- package/docs/heygen.md +124 -0
- package/docs/hubspot.md +142 -0
- package/docs/incident-io.md +118 -0
- package/docs/inngest.md +178 -0
- package/docs/klipy.md +149 -0
- package/docs/lexware.md +144 -0
- package/docs/lightspeed.md +193 -0
- package/docs/linear.md +137 -0
- package/docs/linkedin.md +196 -0
- package/docs/logo-dev.md +152 -0
- package/docs/mailgun.md +153 -0
- package/docs/mapbox.md +174 -0
- package/docs/microsoft-excel.md +97 -0
- package/docs/microsoft-fabric.md +249 -0
- package/docs/microsoft-oauth.md +143 -0
- package/docs/microsoft-onedrive.md +76 -0
- package/docs/microsoft-onenote.md +75 -0
- package/docs/microsoft-outlook.md +90 -0
- package/docs/microsoft-powerpoint.md +119 -0
- package/docs/microsoft-sharepoint.md +75 -0
- package/docs/microsoft-teams.md +72 -0
- package/docs/microsoft-word.md +119 -0
- package/docs/miro.md +117 -0
- package/docs/n8n.md +169 -0
- package/docs/notion.md +137 -0
- package/docs/oura.md +161 -0
- package/docs/paddle.md +168 -0
- package/docs/perplexity.md +85 -0
- package/docs/pipedrive.md +120 -0
- package/docs/polar.md +63 -0
- package/docs/posthog.md +227 -0
- package/docs/prestashop.md +151 -0
- package/docs/replicate.md +60 -0
- package/docs/resend.md +153 -0
- package/docs/salesforce.md +234 -0
- package/docs/sanity.md +122 -0
- package/docs/semrush.md +276 -0
- package/docs/sentry.md +112 -0
- package/docs/sevdesk.md +107 -0
- package/docs/shopify.md +206 -0
- package/docs/slack.md +257 -0
- package/docs/snowflake.md +271 -0
- package/docs/storyblok.md +130 -0
- package/docs/stripe.md +77 -0
- package/docs/supabase.md +51 -0
- package/docs/tally.md +105 -0
- package/docs/telegram.md +165 -0
- package/docs/tiktok.md +201 -0
- package/docs/twilio.md +284 -0
- package/docs/twitch.md +428 -0
- package/docs/wave.md +440 -0
- package/docs/wix.md +1249 -0
- package/docs/wiz.md +177 -0
- package/docs/woocommerce.md +400 -0
- package/docs/wordpress-com.md +358 -0
- package/docs/wordpress-self-hosted.md +252 -0
- package/docs/workday.md +292 -0
- package/docs/x-twitter.md +188 -0
- package/docs/xero.md +429 -0
- package/docs/zoho-books.md +214 -0
- package/docs/zoho-crm.md +192 -0
- package/package.json +153 -0
- package/patterns/ai-connections/PATTERN.md +84 -0
- package/patterns/ai-connections/example/ai-model.js +11 -0
- package/patterns/ai-connections/example/perplexity-answer.js +29 -0
- package/patterns/api-key-connection/PATTERN.md +368 -0
- package/patterns/api-key-connection/example/connections.js +18 -0
- package/patterns/api-key-connection/example/integrations.json +19 -0
- package/patterns/assistant-mcp/PATTERN.md +110 -0
- package/patterns/assistant-mcp/example/integrations.json +13 -0
- package/patterns/assistant-mcp-oauth/PATTERN.md +235 -0
- package/patterns/assistant-mcp-oauth/example/integrations.json +102 -0
- package/patterns/aws-storage-queries/PATTERN.md +169 -0
- package/patterns/aws-storage-queries/example/formats/data-formats.js +35 -0
- package/patterns/aws-storage-queries/example/formats/package-lock.json +49 -0
- package/patterns/aws-storage-queries/example/formats/package.json +12 -0
- package/patterns/aws-storage-queries/example/formats/verify-formats.mjs +37 -0
- package/patterns/aws-storage-queries/example/integrations.json +38 -0
- package/patterns/aws-storage-queries/example/s3-transfer.js +34 -0
- package/patterns/event-delivery/PATTERN.md +151 -0
- package/patterns/event-delivery/example/integrations.json +17 -0
- package/patterns/firebase-messaging/PATTERN.md +156 -0
- package/patterns/firebase-messaging/example/server/notifications.js +23 -0
- package/patterns/google-ads-search/PATTERN.md +92 -0
- package/patterns/google-ads-search/example/ads-setup.js +25 -0
- package/patterns/oauth-connection/PATTERN.md +724 -0
- package/patterns/oauth-connection/example/integrations.json +20 -0
- package/patterns/paddle-catalogue/PATTERN.md +78 -0
- package/patterns/paddle-catalogue/example/create-products.js +38 -0
- package/patterns/public-image/PATTERN.md +84 -0
- package/patterns/public-image/example/integrations.json +13 -0
- package/patterns/public-image/example/logo-url.js +16 -0
- package/patterns/redshift-queries/PATTERN.md +150 -0
- package/patterns/redshift-queries/example/integrations.json +33 -0
- package/patterns/source-scanning/PATTERN.md +83 -0
- package/patterns/source-scanning/example/source-scanner.js +13 -0
- package/src/client/firebase-cloud-messaging.js +10 -0
- package/src/client/google-analytics.js +72 -0
- package/src/client/google-maps-platform.js +39 -0
- package/src/client/logo-dev.js +36 -0
- package/src/server/ai.js +46 -0
- package/src/server/airtable.js +67 -0
- package/src/server/algolia.js +63 -0
- package/src/server/amazon-redshift.js +96 -0
- package/src/server/amplitude.js +31 -0
- package/src/server/apify.js +68 -0
- package/src/server/apollo-io.js +85 -0
- package/src/server/asana.js +64 -0
- package/src/server/ashby.js +61 -0
- package/src/server/atlassian.js +32 -0
- package/src/server/attention.js +93 -0
- package/src/server/aws-athena.js +82 -0
- package/src/server/aws-s3.js +49 -0
- package/src/server/awsTransport.js +75 -0
- package/src/server/bigquery.js +97 -0
- package/src/server/brevo.js +97 -0
- package/src/server/calendly.js +77 -0
- package/src/server/canva.js +13 -0
- package/src/server/chargebee.js +88 -0
- package/src/server/clay.js +78 -0
- package/src/server/clickhouse.js +66 -0
- package/src/server/confidence.js +29 -0
- package/src/server/contentful.js +40 -0
- package/src/server/databricks.js +55 -0
- package/src/server/dbt-semantic-layer.js +95 -0
- package/src/server/elevenlabs.js +81 -0
- package/src/server/figma.js +24 -0
- package/src/server/firebase-cloud-messaging.js +111 -0
- package/src/server/firecrawl.js +70 -0
- package/src/server/fireflies.js +31 -0
- package/src/server/fireworks-ai.js +16 -0
- package/src/server/gatewayapi.js +48 -0
- package/src/server/gemini-enterprise.js +47 -0
- package/src/server/github-api.js +90 -0
- package/src/server/gitlab-api.js +67 -0
- package/src/server/gmail.js +60 -0
- package/src/server/gong.js +52 -0
- package/src/server/google-ads-search.js +134 -0
- package/src/server/google-ads.js +80 -0
- package/src/server/google-docs.js +36 -0
- package/src/server/google-drive.js +71 -0
- package/src/server/google-maps-platform.js +90 -0
- package/src/server/google-search-console.js +31 -0
- package/src/server/google-sheets.js +60 -0
- package/src/server/google-slides.js +36 -0
- package/src/server/google.js +61 -0
- package/src/server/granola.js +115 -0
- package/src/server/graphqlOperation.js +15 -0
- package/src/server/hex.js +29 -0
- package/src/server/heygen.js +54 -0
- package/src/server/hubspot.js +85 -0
- package/src/server/incident-io.js +68 -0
- package/src/server/inngest.js +86 -0
- package/src/server/jsonOperation.js +34 -0
- package/src/server/klipy.js +34 -0
- package/src/server/lexware.js +59 -0
- package/src/server/lightspeed.js +82 -0
- package/src/server/linear.js +52 -0
- package/src/server/linkedin.js +74 -0
- package/src/server/mailgun.js +76 -0
- package/src/server/mapbox.js +46 -0
- package/src/server/mcpRegistration.js +41 -0
- package/src/server/mcpTransport.js +60 -0
- package/src/server/microsoft-excel.js +67 -0
- package/src/server/microsoft-fabric.js +81 -0
- package/src/server/microsoft-onedrive.js +58 -0
- package/src/server/microsoft-onenote.js +52 -0
- package/src/server/microsoft-outlook.js +58 -0
- package/src/server/microsoft-powerpoint.js +5 -0
- package/src/server/microsoft-sharepoint.js +46 -0
- package/src/server/microsoft-teams.js +29 -0
- package/src/server/microsoft-word.js +5 -0
- package/src/server/microsoft.js +88 -0
- package/src/server/miro.js +29 -0
- package/src/server/n8n.js +78 -0
- package/src/server/notion.js +76 -0
- package/src/server/oura.js +48 -0
- package/src/server/paddle.js +83 -0
- package/src/server/perplexity.js +15 -0
- package/src/server/pipedrive.js +95 -0
- package/src/server/polar.js +20 -0
- package/src/server/posthog.js +44 -0
- package/src/server/prestashop.js +42 -0
- package/src/server/replicate.js +42 -0
- package/src/server/resend.js +93 -0
- package/src/server/salesforce.js +84 -0
- package/src/server/sanity.js +31 -0
- package/src/server/semrush.js +359 -0
- package/src/server/sentry.js +30 -0
- package/src/server/sevdesk.js +20 -0
- package/src/server/shopify.js +99 -0
- package/src/server/slack.js +143 -0
- package/src/server/snowflake.js +139 -0
- package/src/server/storyblok.js +49 -0
- package/src/server/stripe.js +13 -0
- package/src/server/supabase.js +13 -0
- package/src/server/tally.js +78 -0
- package/src/server/telegram.js +55 -0
- package/src/server/tiktok.js +86 -0
- package/src/server/twilio.js +90 -0
- package/src/server/twitch.js +409 -0
- package/src/server/wave.js +520 -0
- package/src/server/wix.js +1048 -0
- package/src/server/wiz.js +117 -0
- package/src/server/woocommerce.js +412 -0
- package/src/server/wordpress-com.js +236 -0
- package/src/server/wordpress-self-hosted.js +134 -0
- package/src/server/workday.js +136 -0
- package/src/server/x-twitter.js +110 -0
- package/src/server/xero.js +397 -0
- package/src/server/zoho-books.js +90 -0
- package/src/server/zoho-crm.js +89 -0
- package/src/server/zohoOAuth.js +21 -0
- package/src/shared/ai-models.json +8049 -0
- package/src/shared/ai.js +63 -0
- package/src/shared/algolia.js +29 -0
- package/src/shared/amazon-redshift.js +51 -0
- package/src/shared/amplitude.js +28 -0
- package/src/shared/atlassian.js +43 -0
- package/src/shared/aws.js +72 -0
- package/src/shared/canva.js +66 -0
- package/src/shared/chargebee.js +26 -0
- package/src/shared/clickhouse.js +38 -0
- package/src/shared/confidence.js +28 -0
- package/src/shared/databricks.js +33 -0
- package/src/shared/dbt-semantic-layer.js +32 -0
- package/src/shared/definitions.js +140 -0
- package/src/shared/figma.js +21 -0
- package/src/shared/firebase-cloud-messaging.js +45 -0
- package/src/shared/gemini-enterprise.js +33 -0
- package/src/shared/gong.js +33 -0
- package/src/shared/google-ads-search.js +31 -0
- package/src/shared/google-ads.js +28 -0
- package/src/shared/google-maps-platform.js +28 -0
- package/src/shared/google.js +133 -0
- package/src/shared/granola.js +25 -0
- package/src/shared/hex.js +28 -0
- package/src/shared/inngest.js +35 -0
- package/src/shared/lightspeed.js +75 -0
- package/src/shared/linkedin.js +27 -0
- package/src/shared/logo-dev.js +21 -0
- package/src/shared/mapbox.js +38 -0
- package/src/shared/mcp.js +92 -0
- package/src/shared/microsoft-fabric.js +47 -0
- package/src/shared/microsoft.js +231 -0
- package/src/shared/miro.js +27 -0
- package/src/shared/oura.js +23 -0
- package/src/shared/posthog.js +33 -0
- package/src/shared/prestashop.js +23 -0
- package/src/shared/salesforce.js +36 -0
- package/src/shared/semrush.js +24 -0
- package/src/shared/shopify.js +51 -0
- package/src/shared/siteUrl.js +12 -0
- package/src/shared/slack.js +88 -0
- package/src/shared/snowflake.js +55 -0
- package/src/shared/tiktok.js +22 -0
- package/src/shared/tokens.js +747 -0
- package/src/shared/twilio.js +41 -0
- package/src/shared/twitch.js +49 -0
- package/src/shared/wave.js +52 -0
- package/src/shared/wix.js +40 -0
- package/src/shared/wiz.js +41 -0
- package/src/shared/wordpress-com.js +30 -0
- package/src/shared/wordpress.js +69 -0
- package/src/shared/workday.js +50 -0
- package/src/shared/x-twitter.js +19 -0
- package/src/shared/xero.js +46 -0
- package/src/shared/zoho-books.js +39 -0
- package/src/shared/zoho-crm.js +43 -0
- package/src/shared/zoho-regions.js +12 -0
- package/test/ai.test.js +136 -0
- package/test/airtable.test.js +125 -0
- package/test/algolia.test.js +207 -0
- package/test/amazon-redshift.test.js +272 -0
- package/test/amplitude.test.js +239 -0
- package/test/apify.test.js +93 -0
- package/test/apollo-io.test.js +125 -0
- package/test/asana.test.js +99 -0
- package/test/ashby.test.js +97 -0
- package/test/atlassian.test.js +249 -0
- package/test/attention.test.js +79 -0
- package/test/aws.test.js +405 -0
- package/test/brevo.test.js +71 -0
- package/test/calendly.test.js +136 -0
- package/test/canva.test.js +258 -0
- package/test/chargebee.test.js +195 -0
- package/test/clickhouse.test.js +278 -0
- package/test/confidence.test.js +205 -0
- package/test/databricks.test.js +253 -0
- package/test/dbt-semantic-layer.test.js +221 -0
- package/test/designMcp.test.js +336 -0
- package/test/elevenlabs.test.js +52 -0
- package/test/firebase-cloud-messaging.test.js +242 -0
- package/test/firecrawl.test.js +66 -0
- package/test/gemini-enterprise.test.js +218 -0
- package/test/github-api.test.js +167 -0
- package/test/gitlab-api.test.js +160 -0
- package/test/gong.test.js +192 -0
- package/test/google-ads.test.js +350 -0
- package/test/google-maps-platform.test.js +191 -0
- package/test/google.test.js +710 -0
- package/test/granola.test.js +240 -0
- package/test/hex.test.js +253 -0
- package/test/heygen.test.js +121 -0
- package/test/hubspot.test.js +103 -0
- package/test/inngest.test.js +219 -0
- package/test/lightspeed.test.js +250 -0
- package/test/linear.test.js +146 -0
- package/test/linkedin.test.js +243 -0
- package/test/logo-dev.test.js +79 -0
- package/test/mailgun.test.js +107 -0
- package/test/mapbox.test.js +181 -0
- package/test/mcp.test.js +227 -0
- package/test/microsoft-fabric.test.js +258 -0
- package/test/microsoft.test.js +554 -0
- package/test/n8nOAuth.test.js +188 -0
- package/test/notionOAuth.test.js +183 -0
- package/test/oura.test.js +211 -0
- package/test/paddleCatalogue.test.js +51 -0
- package/test/paddlePermissions.test.js +101 -0
- package/test/perplexityComposition.test.js +39 -0
- package/test/pipedriveOAuth.test.js +140 -0
- package/test/posthog.test.js +200 -0
- package/test/prestashop.test.js +207 -0
- package/test/resend.test.js +163 -0
- package/test/salesforce.test.js +276 -0
- package/test/semrush.test.js +479 -0
- package/test/sentry.test.js +35 -0
- package/test/shopify.test.js +247 -0
- package/test/slack.test.js +320 -0
- package/test/snowflake.test.js +391 -0
- package/test/tally.test.js +75 -0
- package/test/telegram.test.js +58 -0
- package/test/tiktok.test.js +243 -0
- package/test/tokens.test.js +1079 -0
- package/test/twilio.test.js +221 -0
- package/test/twitch.test.js +573 -0
- package/test/wave.test.js +678 -0
- package/test/wix.test.js +1099 -0
- package/test/wiz.test.js +185 -0
- package/test/wordpress-com.test.js +469 -0
- package/test/wordpress.test.js +660 -0
- package/test/workday.test.js +314 -0
- package/test/x-twitter.test.js +256 -0
- package/test/xero.test.js +700 -0
- package/test/zoho-books.test.js +253 -0
- package/test/zoho-crm.test.js +223 -0
package/docs/twitch.md
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Twitch
|
|
2
|
+
|
|
3
|
+
## Delivered fragment
|
|
4
|
+
|
|
5
|
+
Import `twitchProvider` from `@jskit-ai/connectors-catalog/server/twitch`.
|
|
6
|
+
It connects a Twitch user through an own confidential OAuth registration,
|
|
7
|
+
validates that grant, reads profiles and channel data, discovers streams,
|
|
8
|
+
manages broadcasts, chat, polls, predictions, rewards and schedules, retrieves
|
|
9
|
+
analytics and clips, and manages application-owned WebSocket subscriptions.
|
|
10
|
+
Shared, individual and assistant ownership use the same application
|
|
11
|
+
policy and encrypted file store. This does not implement application login,
|
|
12
|
+
app-only tokens, EventSub webhooks or automatic registration.
|
|
13
|
+
|
|
14
|
+
The configuration form retains 23 permission choices. Its defaults are
|
|
15
|
+
`user:read:email` and `user:read:follows`. Broadcast updates additionally require
|
|
16
|
+
`channel:manage:broadcast`; public stream/channel discovery needs no extra scope
|
|
17
|
+
on the validated user token. Runtime operations are described below; their
|
|
18
|
+
checkboxes alone do not prove application-side presentation or event handling.
|
|
19
|
+
Request only permissions used by the application; Twitch explicitly requires
|
|
20
|
+
this. [Scope rules and definitions](https://dev.twitch.tv/docs/authentication/scopes/).
|
|
21
|
+
|
|
22
|
+
## Stream discovery and broadcast changes
|
|
23
|
+
|
|
24
|
+
`streams.list` returns one page of stream data. Inputs are `first` (1–100,
|
|
25
|
+
default 20), `after` (opaque cursor), optional `user_id`, `user_login`, `game_id`
|
|
26
|
+
or `language`, and `type` (`all` or `live`, default `all`). Each filter currently
|
|
27
|
+
accepts one value. Empty results are valid; an offline broadcaster will not
|
|
28
|
+
appear as a live stream. Stream lists can change between pages, so the app must
|
|
29
|
+
handle duplicate/missing records rather than treating pagination as a snapshot.
|
|
30
|
+
|
|
31
|
+
`channels.search` takes required `query`, optional `live_only` (default false),
|
|
32
|
+
`first` and `after`. `channels.read` takes one `broadcaster_id` and returns channel
|
|
33
|
+
information; a missing broadcaster produces an empty list. Neither method grants
|
|
34
|
+
the caller authority to edit the channel it discovers.
|
|
35
|
+
|
|
36
|
+
`broadcast.update` accepts one or more of `title` (nonempty, up to 140 characters),
|
|
37
|
+
`game_id` (including `0`/empty to clear), `broadcaster_language`, `tags` (up to ten
|
|
38
|
+
alphanumeric tags of 25 characters) or `is_branded_content`. The adapter derives
|
|
39
|
+
the target broadcaster from token validation, never from caller input. Missing
|
|
40
|
+
or revoked `channel:manage:broadcast` permission prevents the write. A successful
|
|
41
|
+
PATCH returns `null` (HTTP 204). The app can read that broadcaster's channel to
|
|
42
|
+
show the current values; writes are not retried automatically.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const page = await connections.invoke({ context, integrationId: "twitch",
|
|
46
|
+
operation: "channels.search", input: { query: "grooming", live_only: true } });
|
|
47
|
+
await connections.invoke({ context, integrationId: "twitch",
|
|
48
|
+
operation: "broadcast.update", input: { title: "Live grooming demonstration" } });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
These are native Helix GET `/streams`, `/search/channels`, `/channels` and PATCH
|
|
52
|
+
`/channels?broadcaster_id=...` calls. Another framework uses the same OAuth/Env
|
|
53
|
+
configuration with its own HTTP client, token validation, permission checks and
|
|
54
|
+
JSON serialization. JSKIT validates immediately before each request; validation
|
|
55
|
+
requests remain GET even when the following Helix operation is a PATCH.
|
|
56
|
+
See the [official API reference](https://dev.twitch.tv/docs/api/reference).
|
|
57
|
+
|
|
58
|
+
Controlled acceptance: source tests **20/20**, installed-package consumer tests
|
|
59
|
+
**20/20**, and expanded, medium and compact editor tests **1/1 each**. These cover
|
|
60
|
+
useful operations, authorization failures, portable configuration, inline setup
|
|
61
|
+
and the applicable connection lifecycle. The application owns the EventSub socket,
|
|
62
|
+
reconnection and event processing described below. Live Twitch interoperability
|
|
63
|
+
and generated-app execution were not exercised; no live channel was edited.
|
|
64
|
+
|
|
65
|
+
## Chat, polls and predictions
|
|
66
|
+
|
|
67
|
+
All these operations use a validated **user token**. The app supplies the same
|
|
68
|
+
project-owned OAuth registration and Env references used above. App-only bot
|
|
69
|
+
grants are not implemented. The runtime derives `sender_id` for chat and
|
|
70
|
+
`broadcaster_id` for polls/predictions from the validated user, and rejects caller
|
|
71
|
+
attempts to override those identities.
|
|
72
|
+
|
|
73
|
+
| Operation | Input and behavior | Permission |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `chat.send` | `broadcaster_id` identifies the target channel; `message` is 1–500 characters; optional `reply_parent_message_id` replies to a message. | `user:write:chat` |
|
|
76
|
+
| `polls.list` | `first` (1–20), `after`, optional one `id`; returns the user's polls with provider pagination. | `channel:read:polls` or `channel:manage:polls` |
|
|
77
|
+
| `polls.create` | `title` (1–60), 2–5 `choices: [{title}]` (1–25 each), `duration` (15–1800 seconds). Starts the poll immediately. | `channel:manage:polls` |
|
|
78
|
+
| `polls.end` | `id` and `status` (`TERMINATED` or `ARCHIVED`). | `channel:manage:polls` |
|
|
79
|
+
| `predictions.list` | `first` (1–20), `after`, optional one `id`; returns the user's predictions. | `channel:read:predictions` or `channel:manage:predictions` |
|
|
80
|
+
| `predictions.create` | `title` (1–45), 2–10 `outcomes: [{title}]` (1–25 each), `prediction_window` (30–1800 seconds). Starts immediately. | `channel:manage:predictions` |
|
|
81
|
+
| `predictions.end` | `id`, `status` (`LOCKED`, `CANCELED`, `RESOLVED`); `winning_outcome_id` is required only for `RESOLVED`. | `channel:manage:predictions` |
|
|
82
|
+
|
|
83
|
+
Inspect `chat.send`'s `data[0].is_sent` and `drop_reason`: HTTP success can report
|
|
84
|
+
that moderation dropped or held the message. Do not show it as delivered merely
|
|
85
|
+
because the request succeeded. The app authorizes channel destinations, reply
|
|
86
|
+
targets and content before invoking the connector. Twitch enforces its own chat
|
|
87
|
+
permissions and moderation rules.
|
|
88
|
+
|
|
89
|
+
The application owns poll/prediction presentation and explicit refresh, including
|
|
90
|
+
tracking the returned IDs and outcome IDs. Polls and predictions have account
|
|
91
|
+
eligibility and concurrent-activity limits; the application should surface
|
|
92
|
+
rejection rather than retry creation. Resolving a prediction determines the
|
|
93
|
+
Channel Points outcome, so require the application's deliberate broadcaster
|
|
94
|
+
action. The adapter currently creates free-vote polls; paid Channel Points poll
|
|
95
|
+
options are not yet supplied. Neither workflow is an application billing system.
|
|
96
|
+
|
|
97
|
+
Native frameworks make the corresponding Helix GET/POST/PATCH `/polls` or
|
|
98
|
+
`/predictions` requests and POST `/chat/messages` using JSON bodies. Reads carry
|
|
99
|
+
the authenticated broadcaster as a query parameter; writes carry it in JSON.
|
|
100
|
+
Use the same token validation and permission checks as the Node implementation.
|
|
101
|
+
[Poll guide](https://dev.twitch.tv/docs/api/polls),
|
|
102
|
+
[prediction guide](https://dev.twitch.tv/docs/api/predictions),
|
|
103
|
+
[Helix reference](https://dev.twitch.tv/docs/api/reference).
|
|
104
|
+
|
|
105
|
+
## Channel and moderation reads
|
|
106
|
+
|
|
107
|
+
### Event subscriptions
|
|
108
|
+
|
|
109
|
+
`events.subscribe` takes `type` and the application-owned WebSocket `session_id`.
|
|
110
|
+
Supported events are stream online/offline, channel update/subscribe/cheer,
|
|
111
|
+
poll begin/progress/end, prediction begin/progress/lock/end, and reward redemption
|
|
112
|
+
add/update. The adapter chooses the version and derives the broadcaster from
|
|
113
|
+
the validated user; permission checks precede subscription creation.
|
|
114
|
+
`events.list` accepts optional `type` and `after`. `events.delete` takes `id`.
|
|
115
|
+
Applications must retain and authorize their own session/subscription IDs.
|
|
116
|
+
|
|
117
|
+
The backend opens `wss://eventsub.wss.twitch.tv/ws` using its framework's
|
|
118
|
+
WebSocket client, receives `session_welcome`, and passes that session ID to
|
|
119
|
+
`events.subscribe` within Twitch's welcome deadline (normally ten seconds).
|
|
120
|
+
Native frameworks POST the subscription to `/helix/eventsub/subscriptions`
|
|
121
|
+
using the same user grant and `{ method: "websocket", session_id }` transport.
|
|
122
|
+
List/delete use GET/DELETE on that path. This path has no HTTP callback or
|
|
123
|
+
webhook signature; TLS authenticates the socket's server. Webhook transport
|
|
124
|
+
requires separate app-token authentication and is not implemented.
|
|
125
|
+
|
|
126
|
+
The application owns keepalive deadlines, reconnect messages, re-subscription
|
|
127
|
+
after connection loss, subscription revocations, and deduplication by message
|
|
128
|
+
ID. Never treat the request response as proof that an event handler ran.
|
|
129
|
+
Import `parseTwitchEventSubMessage` from the same server module. Pass a text frame
|
|
130
|
+
and trusted `{ broadcasterId, sessionId, subscriptionIds }`. It rejects oversized
|
|
131
|
+
frames (over 1 MiB), malformed envelopes, unexpected notification ownership and
|
|
132
|
+
reconnect URLs outside Twitch's secure EventSub host. It preserves the event and
|
|
133
|
+
message ID. It does not cryptographically authenticate arbitrary input: call it
|
|
134
|
+
only on frames received from the application's trusted Twitch socket.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
import { parseTwitchEventSubMessage } from "@jskit-ai/connectors-catalog/server/twitch";
|
|
138
|
+
// Inside the app's socket handler; these identities come from its connection state.
|
|
139
|
+
const message = parseTwitchEventSubMessage(frameText, {
|
|
140
|
+
broadcasterId, sessionId, subscriptionIds
|
|
141
|
+
});
|
|
142
|
+
if (message.metadata.message_type === "notification") {
|
|
143
|
+
// Process once under the app's durable event-ID/idempotency policy.
|
|
144
|
+
await processEventOnce(message.metadata.message_id, message.payload.event);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`processEventOnce` above is application code, not a JSKIT API. On welcome, save
|
|
149
|
+
the new session ID and subscribe within the advertised timeout. Refresh the
|
|
150
|
+
silence deadline on received messages. On reconnect, open the validated URL
|
|
151
|
+
unchanged and switch after the new welcome; preserve the transferred
|
|
152
|
+
subscriptions. After an ordinary connection loss, create a fresh session and
|
|
153
|
+
re-subscribe. On revocation, remove the affected subscription and surface its
|
|
154
|
+
reason. Close sockets and cancel timers when the app stops maintaining a
|
|
155
|
+
connection. Native WebSocket libraries handle protocol ping/pong; do not send
|
|
156
|
+
application messages to this socket.
|
|
157
|
+
|
|
158
|
+
Controlled parser fixtures cover useful notification payloads, revocation,
|
|
159
|
+
welcome, reconnect and owner/session/subscription rejection. A live socket or a
|
|
160
|
+
generated application's complete socket lifecycle has not been exercised.
|
|
161
|
+
See [EventSub management](https://dev.twitch.tv/docs/eventsub/manage-subscriptions/)
|
|
162
|
+
and [WebSocket handling](https://dev.twitch.tv/docs/eventsub/handling-websocket-events).
|
|
163
|
+
|
|
164
|
+
### Streaming schedule
|
|
165
|
+
|
|
166
|
+
`schedule.get` requires `broadcaster_id`; optional `id`, UTC `start_time`, `first`
|
|
167
|
+
(1–25) and `after` select segments. The result retains pagination and vacation
|
|
168
|
+
metadata. Twitch can return 404 when no schedule exists.
|
|
169
|
+
|
|
170
|
+
`schedule.create` requires UTC `start_time`, IANA `timezone`, integer `duration`
|
|
171
|
+
(30–1380 minutes) and explicit `is_recurring`. Optional `title` and `category_id`
|
|
172
|
+
describe the stream. `schedule.update` requires segment `id` and at least one
|
|
173
|
+
change to those fields (except recurrence), or `is_canceled`.
|
|
174
|
+
`schedule.delete` requires segment `id`. Writes require
|
|
175
|
+
`channel:manage:schedule` and derive broadcaster identity from the user token.
|
|
176
|
+
|
|
177
|
+
Native frameworks read GET `/helix/schedule` and write POST/PATCH/DELETE
|
|
178
|
+
`/helix/schedule/segment`, putting broadcaster/segment IDs in query parameters
|
|
179
|
+
and changes in JSON. The app owns calendar presentation and deliberate changes:
|
|
180
|
+
editing recurring details affects the series, deleting removes the series, and
|
|
181
|
+
cancellation targets the next occurrence. Twitch controls account eligibility.
|
|
182
|
+
iCalendar export is not provided. `schedule.vacation` takes required
|
|
183
|
+
`is_vacation_enabled`. Enabling it also requires UTC `vacation_start_time`,
|
|
184
|
+
`vacation_end_time` (strictly later), and IANA `timezone`. Disabling needs only
|
|
185
|
+
`is_vacation_enabled: false`. Native frameworks PATCH `/helix/schedule/settings`
|
|
186
|
+
with these values and the authenticated broadcaster in query parameters;
|
|
187
|
+
success returns no content. This follows the API reference's query contract,
|
|
188
|
+
despite the tutorial describing a body. See the
|
|
189
|
+
[schedule guide](https://dev.twitch.tv/docs/api/schedule).
|
|
190
|
+
|
|
191
|
+
### Channel Points rewards
|
|
192
|
+
|
|
193
|
+
`rewards.list` accepts optional `id` and `only_manageable_rewards` (default false).
|
|
194
|
+
`rewards.create` requires `title` (1–45) and positive integer `cost`; optional
|
|
195
|
+
`prompt` (up to 200), `is_enabled`, `is_user_input_required`, `background_color`
|
|
196
|
+
(`#RRGGBB`) and `should_redemptions_skip_request_queue` configure the reward.
|
|
197
|
+
`rewards.update` requires `id` plus at least one change, supports those fields
|
|
198
|
+
and `is_paused`. `rewards.delete` requires `id` and returns `null` on success.
|
|
199
|
+
Both create and update accept `is_max_per_stream_enabled`/`max_per_stream`,
|
|
200
|
+
`is_max_per_user_per_stream_enabled`/`max_per_user_per_stream`, and
|
|
201
|
+
`is_global_cooldown_enabled`/`global_cooldown_seconds`. When enabling a limit,
|
|
202
|
+
provide its positive integer amount in the same call. Cooldown is bounded to
|
|
203
|
+
604800 seconds; Twitch only displays cooldowns of at least 60 seconds in its UI.
|
|
204
|
+
Setting an enable flag to false disables that limit without requiring an amount.
|
|
205
|
+
|
|
206
|
+
`redemptions.list` requires `reward_id`, with optional redemption `id`, `status`
|
|
207
|
+
(default `UNFULFILLED`), `sort` (`OLDEST`/`NEWEST`), `first` (1–50), and `after`.
|
|
208
|
+
`redemptions.update` requires `reward_id`, redemption `id` and `status`
|
|
209
|
+
(`FULFILLED` or `CANCELED`). Cancelling refunds Twitch Channel Points. The app
|
|
210
|
+
must authorize this decision and complete its own promised work before marking
|
|
211
|
+
fulfilment. No action is automatically retried.
|
|
212
|
+
|
|
213
|
+
Reads accept `channel:read:redemptions` or `channel:manage:redemptions`; writes
|
|
214
|
+
require the latter. Broadcaster identity always comes from token validation.
|
|
215
|
+
Native frameworks use `/helix/channel_points/custom_rewards` and its
|
|
216
|
+
`/redemptions` subpath: identities belong in query parameters, mutable fields in
|
|
217
|
+
JSON. Twitch restricts management/redemption access to the creating application
|
|
218
|
+
and eligible broadcasters. Switching OAuth registrations does not transfer that
|
|
219
|
+
ownership. See [Channel Points API](https://dev.twitch.tv/docs/api/reference/#create-custom-rewards).
|
|
220
|
+
The connector does not create a separate app credit balance or rewards dashboard.
|
|
221
|
+
|
|
222
|
+
`clips.create` accepts a required `broadcaster_id` and requires `clips:edit`.
|
|
223
|
+
It returns a clip ID and Twitch edit URL. The app authorizes the target channel;
|
|
224
|
+
Twitch enforces live-stream availability and clipping permissions. Creation uses
|
|
225
|
+
POST `/helix/clips` with the broadcaster in the query, without a JSON body.
|
|
226
|
+
`clips.get` accepts one required `id` and uses GET `/helix/clips`; an empty list
|
|
227
|
+
means the clip is not currently available. The application polls explicitly and
|
|
228
|
+
must not repeat creation just because lookup is empty.
|
|
229
|
+
|
|
230
|
+
Use a bounded 60-second lookup window, following the current
|
|
231
|
+
[API reference](https://dev.twitch.tv/docs/api/reference/#create-clip), which
|
|
232
|
+
differs from the tutorial's older 15-second guidance. The adapter starts no
|
|
233
|
+
timer. Twitch's returned edit URL handles editing; the app owns presentation.
|
|
234
|
+
This fragment uses default clip duration/title and does not create VOD clips,
|
|
235
|
+
download videos, or provide a video editor.
|
|
236
|
+
|
|
237
|
+
`analytics.extensions` and `analytics.games` return CSV report links using
|
|
238
|
+
`analytics:read:extensions` and `analytics:read:games`. They accept optional
|
|
239
|
+
`extension_id` or `game_id`, `first`, `after`, and `type: "overview_v2"`.
|
|
240
|
+
Supply both `started_at` and `ended_at` as real midnight UTC dates
|
|
241
|
+
(`YYYY-MM-DDT00:00:00Z`), or omit both. End must not precede start.
|
|
242
|
+
Twitch controls report availability and the effective date range. An empty
|
|
243
|
+
report list is valid.
|
|
244
|
+
|
|
245
|
+
Another framework calls GET `/helix/analytics/extensions` or `/helix/analytics/games`
|
|
246
|
+
with these query fields and its validated user grant. Reports belong to the
|
|
247
|
+
consenting owner's games/extensions. The adapter returns HTTPS report links;
|
|
248
|
+
it does not fetch them or forward Twitch credentials to the report host.
|
|
249
|
+
Applications must authorize report access, avoid logging signed URLs, and own
|
|
250
|
+
CSV download/parsing and presentation. See the
|
|
251
|
+
[analytics API reference](https://dev.twitch.tv/docs/api/reference/#get-extension-analytics).
|
|
252
|
+
|
|
253
|
+
`bits.leaderboard` reads the authenticated broadcaster's Bits ranking using
|
|
254
|
+
`bits:read`. Inputs are `count` (1–100, default 10), `period` (`day`, `week`,
|
|
255
|
+
`month`, `year`, or default `all`), optional RFC3339 `started_at`, and optional
|
|
256
|
+
`user_id` to select that user's position and surrounding ranks. Twitch determines
|
|
257
|
+
the reporting window; retain its returned `date_range`, ranks, scores and total.
|
|
258
|
+
The user filter does not change which broadcaster owns the leaderboard.
|
|
259
|
+
Other frameworks use GET `/helix/bits/leaderboard` with these query fields and
|
|
260
|
+
the same authenticated user token. The application renders the ranking; this
|
|
261
|
+
does not purchase Bits or create an application credit balance.
|
|
262
|
+
See [Get Bits Leaderboard](https://dev.twitch.tv/docs/api/reference/#get-bits-leaderboard).
|
|
263
|
+
|
|
264
|
+
These operations return provider records without building a subscriber or
|
|
265
|
+
moderation dashboard. The application must authorize access before invocation.
|
|
266
|
+
Paginated operations accept `first` (1–100, default 20) and opaque `after`;
|
|
267
|
+
the application passes the returned cursor explicitly to fetch another page.
|
|
268
|
+
|
|
269
|
+
| Operation | Input and identity | Permission |
|
|
270
|
+
| --- | --- | --- |
|
|
271
|
+
| `subscriptions.list` | Pagination and optional `user_id` filter; broadcaster is the validated account. | `channel:read:subscriptions` |
|
|
272
|
+
| `subscriptions.check` | Required target `broadcaster_id`; subscriber is the validated account. | `user:read:subscriptions` |
|
|
273
|
+
| `vips.list` | Pagination and optional `user_id`; broadcaster is the validated account. | `channel:read:vips` |
|
|
274
|
+
| `editors.list` | No input; broadcaster is the validated account. | `channel:read:editors` |
|
|
275
|
+
| `bannedUsers.list` | Pagination and optional `user_id`; broadcaster is the validated account. | `moderation:read` |
|
|
276
|
+
| `moderators.list` | Pagination and optional `user_id`; broadcaster is the validated account. | `moderation:read` |
|
|
277
|
+
| `followers.list` | Pagination, optional `user_id` and `broadcaster_id` (defaults to the validated account). Twitch enforces access to another broadcaster's followers. | `moderator:read:followers` |
|
|
278
|
+
| `chatters.list` | Pagination and required target `broadcaster_id`; moderator identity is the validated account. | `moderator:read:chatters` |
|
|
279
|
+
| `hypeTrain.status` | No input; broadcaster is the validated account. `current: null` means no active Hype Train. | `channel:read:hype_train` |
|
|
280
|
+
|
|
281
|
+
The native Helix paths are respectively `/subscriptions`, `/subscriptions/user`,
|
|
282
|
+
`/channels/vips`, `/channels/editors`, `/moderation/banned`,
|
|
283
|
+
`/moderation/moderators`, `/channels/followers`, `/chat/chatters` and
|
|
284
|
+
`/hypetrain/status`. Other frameworks use GET with the same validated identities
|
|
285
|
+
and scope checks. User filters never replace the authenticated identity.
|
|
286
|
+
Subscription checks preserve provider errors: a not-subscribed 404 is not a
|
|
287
|
+
successful subscription record. The application decides how to present it.
|
|
288
|
+
|
|
289
|
+
Hype Train status replaces the retired Get Hype Train Events endpoint; it is
|
|
290
|
+
not an event-history feed. See the [API reference](https://dev.twitch.tv/docs/api/reference)
|
|
291
|
+
and [Twitch product lifecycle](https://dev.twitch.tv/docs/product-lifecycle/).
|
|
292
|
+
Controlled tests cover all nine reads, account binding, rejected identity
|
|
293
|
+
overrides, pagination records and malformed responses. Live eligibility and
|
|
294
|
+
moderator access have not been exercised.
|
|
295
|
+
|
|
296
|
+
## Create the provider registration
|
|
297
|
+
|
|
298
|
+
1. Sign in with the Twitch account that will own the application. Verify its
|
|
299
|
+
email and enable two-factor authentication under **Settings → Security and
|
|
300
|
+
Privacy**, then refresh the developer console if necessary.
|
|
301
|
+
2. Open the [developer console](https://dev.twitch.tv/console), choose
|
|
302
|
+
**Applications**, then **Register Your Application**.
|
|
303
|
+
3. Enter a unique application **Name**. In **OAuth Redirect URLs**, enter the
|
|
304
|
+
exact HTTPS callback served by your backend and choose **Add**. Choose the
|
|
305
|
+
application's **Category**, complete the displayed human verification and
|
|
306
|
+
choose **Create**. This backend fragment uses a **Confidential** client;
|
|
307
|
+
public/native client behavior is outside its scope.
|
|
308
|
+
4. Find the application under **Developer Applications** and choose **Manage**.
|
|
309
|
+
Copy **Client ID** into the registration configuration. Choose **New Secret**
|
|
310
|
+
and store it outside source as the environment value referenced by
|
|
311
|
+
`clientSecretRef`. Generating another secret invalidates the previous one;
|
|
312
|
+
coordinate rotation with the application's operator.
|
|
313
|
+
5. Set the callback environment value to the same complete redirect URL.
|
|
314
|
+
Configure the server's callback route before starting consent. Each consent
|
|
315
|
+
attempt must return to its initiating authenticated owner.
|
|
316
|
+
|
|
317
|
+
These navigation steps follow Twitch's
|
|
318
|
+
[registration instructions](https://dev.twitch.tv/docs/authentication/register-app/).
|
|
319
|
+
The confidential/public distinction is described in its
|
|
320
|
+
[refresh documentation](https://dev.twitch.tv/docs/authentication/refresh-tokens/).
|
|
321
|
+
A CLI uses these same packages and a callback served by its own backend/listener
|
|
322
|
+
at a provider-accepted, registered URL. No Vibe64 account is required. Do not
|
|
323
|
+
embed a confidential client secret into a distributed desktop binary.
|
|
324
|
+
|
|
325
|
+
## Portable configuration and library composition
|
|
326
|
+
|
|
327
|
+
Save this as `integrations.json`, replacing the public Client ID placeholder.
|
|
328
|
+
The editor reads and writes this same file. Each application user consents to
|
|
329
|
+
their own account when `accountMode` is `per-user`.
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"schemaVersion": 1,
|
|
334
|
+
"integrations": {
|
|
335
|
+
"twitch": {
|
|
336
|
+
"provider": "twitch",
|
|
337
|
+
"displayName": "My Twitch",
|
|
338
|
+
"accountMode": "per-user",
|
|
339
|
+
"scopes": ["user:read:email", "user:read:follows"],
|
|
340
|
+
"authentication": { "method": "oauth2", "registrationRef": "twitch" }
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"registrations": {
|
|
344
|
+
"twitch": {
|
|
345
|
+
"source": "own",
|
|
346
|
+
"clientId": "replace-with-your-client-id",
|
|
347
|
+
"clientSecretRef": "env:TWITCH_CLIENT_SECRET",
|
|
348
|
+
"callbackUrlRef": "env:TWITCH_CALLBACK_URL"
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Use the [OAuth file-connection pattern](../patterns/oauth-connection/PATTERN.md)
|
|
355
|
+
with `twitchProvider` in its provider array. It supplies the imports, parsing,
|
|
356
|
+
reference resolution, encrypted file storage and `createConnectionService`
|
|
357
|
+
composition for ordinary Node code, a JSKIT Feature or a manually wired CLI.
|
|
358
|
+
Keep the runtime files outside exported source and retain the encryption key
|
|
359
|
+
across restarts. A database is not required.
|
|
360
|
+
|
|
361
|
+
The existing host policy derives `applicationId` and `subjectId` from its trusted
|
|
362
|
+
session or operator context. Shared accounts require membership checks before
|
|
363
|
+
mapping to a stable shared subject. Never take either owner ID from public
|
|
364
|
+
request parameters. `beginAuthorization` creates the consent URL;
|
|
365
|
+
`completeAuthorization` exchanges its callback and verifies the user token.
|
|
366
|
+
Saving JSON alone does neither. Cancellation consumes the pending attempt;
|
|
367
|
+
`disconnect` removes local access without revoking unrelated provider grants.
|
|
368
|
+
|
|
369
|
+
## Operations and token lifecycle
|
|
370
|
+
|
|
371
|
+
| Operation | Input | Behavior |
|
|
372
|
+
|---|---|---|
|
|
373
|
+
| `token.validate` | None | Verifies a user token, client ID, expiry and scope response at Twitch's validation endpoint |
|
|
374
|
+
| `profile.read` | None | Reads the consenting user's profile; this fragment requires `user:read:email` |
|
|
375
|
+
| `channels.followed` | Optional `first` (integer 1–100, default 20), `after` (opaque cursor), `broadcaster_id` (numeric string) | Reads one page for the validated token's user with `user:read:follows` |
|
|
376
|
+
|
|
377
|
+
All data operations validate the token immediately before querying Helix and
|
|
378
|
+
send the matching Client-ID header. The runtime derives the followed-channel
|
|
379
|
+
`user_id` from validation; callers cannot substitute another user, API URL or
|
|
380
|
+
raw token. A profile must match that same user. An empty page is valid; the
|
|
381
|
+
caller can pass `pagination.cursor` as `after` to request another page. No
|
|
382
|
+
automatic paging or request replay occurs. These contracts follow
|
|
383
|
+
[Get Users](https://dev.twitch.tv/docs/api/reference/#get-users) and
|
|
384
|
+
[Get Followed Channels](https://dev.twitch.tv/docs/api/reference/#get-followed-channels).
|
|
385
|
+
|
|
386
|
+
Twitch requires validation at startup and at least hourly while maintaining
|
|
387
|
+
OAuth sessions, including idle sessions. Invoke `token.validate` from the host's
|
|
388
|
+
startup and scheduled-job paths for each maintained connection. Validating only
|
|
389
|
+
when a person clicks is insufficient. The package exposes the operation but
|
|
390
|
+
starts no background scheduler and does not enumerate the host's users.
|
|
391
|
+
[Validation requirements](https://dev.twitch.tv/docs/authentication/validate-tokens/).
|
|
392
|
+
|
|
393
|
+
The shared runtime refreshes expiring tokens before an invocation, under its
|
|
394
|
+
connection lock, and persists rotated credentials before a subsequent data
|
|
395
|
+
request. The adapter handles Twitch's array and string scope replies. Verified
|
|
396
|
+
scope reductions cannot be restored by refresh. A revoked token, mismatched
|
|
397
|
+
client or missing operation scope fails before the data request and requires
|
|
398
|
+
reconnection; a Helix 401 likewise requires reconnection without replay. This
|
|
399
|
+
fragment does not implement Twitch's recommended reactive refresh on 401.
|
|
400
|
+
[Refresh behavior](https://dev.twitch.tv/docs/authentication/refresh-tokens/).
|
|
401
|
+
|
|
402
|
+
## Online, public editor and automation
|
|
403
|
+
|
|
404
|
+
Twitch requires a distinct client ID for each application. Each generated app
|
|
405
|
+
owns its registration, whether created with a hosted editor, installed editor or
|
|
406
|
+
CLI. Client separation does not prove isolation from every account or service
|
|
407
|
+
limit. [Application registration restriction](https://dev.twitch.tv/docs/authentication/register-app/).
|
|
408
|
+
|
|
409
|
+
Register the application's own callback route, using its assigned public origin
|
|
410
|
+
as the starting point, and keep that exact URL in application Env. When it
|
|
411
|
+
changes, update both the app binding and the provider registration. The
|
|
412
|
+
[callback contract](../../connectors-core/docs/oauth-callbacks.md) describes
|
|
413
|
+
identity, consent and grant handling during a move. No Vibe64 callback gateway
|
|
414
|
+
participates in this flow.
|
|
415
|
+
|
|
416
|
+
The documented registration path is the console. No supported application
|
|
417
|
+
creation API was established in this review. An AI can prepare the JSON,
|
|
418
|
+
environment references, callback wiring and validation job. The owner handles
|
|
419
|
+
account verification, human verification, registration and consent; automation
|
|
420
|
+
must not invent a registration endpoint or bypass those steps. For Online,
|
|
421
|
+
operator-managed credential storage can simplify wiring after the app-specific
|
|
422
|
+
registration exists, but this fragment does not provision that service.
|
|
423
|
+
|
|
424
|
+
Twenty controlled runtime tests cover consent formats and replay, encrypted file
|
|
425
|
+
restart, refresh rotation, owner/client isolation, validation, bounded paging,
|
|
426
|
+
malformed responses, provider failures and interruption. Public-editor tests
|
|
427
|
+
cover the configuration form. No live registration, user data, consent or
|
|
428
|
+
sample application is part of this proof.
|