# Table of Contents - [Twitch Developer Documentation | Twitch Developers](#twitch-developer-documentation-twitch-developers) - [Reference | Twitch Developers](#reference-twitch-developers) - [Twitch API | Twitch Developers](#twitch-api-twitch-developers) - [Twitch API Concepts | Twitch Developers](#twitch-api-concepts-twitch-developers) - [Clips | Twitch Developers](#clips-twitch-developers) - [Build Your Backend | Twitch Developers](#build-your-backend-twitch-developers) - [Configuration Service | Twitch Developers](#configuration-service-twitch-developers) - [Extension File Structure and HTML Views | Twitch Developers](#extension-file-structure-and-html-views-twitch-developers) - [JSON Web Tokens (JWT) | Twitch Developers](#json-web-tokens-jwt-twitch-developers) - [Locally Test Your Extension | Twitch Developers](#locally-test-your-extension-twitch-developers) - [Create an Extension | Twitch Developers](#create-an-extension-twitch-developers) - [Twitch Extensions Tutorials | Twitch Developers](#twitch-extensions-tutorials-twitch-developers) - [Insights & Analytics | Twitch Developers](#insights-analytics-twitch-developers) - [Mobile Deep Links | Twitch Developers](#mobile-deep-links-twitch-developers) - [Insights 및 Analytics | Twitch Developers](#insights-analytics-twitch-developers) - [資料分析與數據 | Twitch Developers](#-twitch-developers) - [Drops | Twitch Developers](#drops-twitch-developers) - [Product Lifecycle | Twitch Developers](#product-lifecycle-twitch-developers) - [Video Broadcast | Twitch Developers](#video-broadcast-twitch-developers) - [E2 SDK Guide | Twitch Developers](#e2-sdk-guide-twitch-developers) - [Drops | Twitch Developers](#drops-twitch-developers) - [드롭스 | Twitch Developers](#-twitch-developers) - [掉寶指南 | Twitch Developers](#-twitch-developers) - [Dropsキャンペーンガイド | Twitch Developers](#drops-twitch-developers) - [드롭스 캠페인 가이드 | Twitch Developers](#-twitch-developers) - [掉宝活动指南 | Twitch Developers](#-twitch-developers) - [Organizations | Twitch Developers](#organizations-twitch-developers) - [Chat | Twitch Developers](#chat-twitch-developers) - [Everything | Twitch Developers](#everything-twitch-developers) - [Video & Clips | Twitch Developers](#video-clips-twitch-developers) - [Authorization SDK Guide | Twitch Developers](#authorization-sdk-guide-twitch-developers) - [الدليل الفني لـ Drops | Twitch Developers](#-drops-twitch-developers) - [Change Log | Twitch Developers](#change-log-twitch-developers) - [Validating Tokens | Twitch Developers](#validating-tokens-twitch-developers) - [Whispers | Twitch Developers](#whispers-twitch-developers) - [Drops技術ガイド | Twitch Developers](#drops-twitch-developers) - [드롭스 기술 가이드 | Twitch Developers](#-twitch-developers) - [掉宝技术指南 | Twitch Developers](#-twitch-developers) - [EventSub Reference | Twitch Developers](#eventsub-reference-twitch-developers) - [Moderating Twitch Chatrooms | Twitch Developers](#moderating-twitch-chatrooms-twitch-developers) - [Unreal Getting Started Blueprints | Twitch Developers](#unreal-getting-started-blueprints-twitch-developers) - [Unreal Getting Started C++ | Twitch Developers](#unreal-getting-started-c-twitch-developers) - [Unreal Engine Reference | Twitch Developers](#unreal-engine-reference-twitch-developers) - [Drops | Twitch Developers](#drops-twitch-developers) - [Embedding Twitch | Twitch Developers](#embedding-twitch-twitch-developers) - [Refreshing Access Tokens | Twitch Developers](#refreshing-access-tokens-twitch-developers) - [Register Your App | Twitch Developers](#register-your-app-twitch-developers) - [Revoking Access Tokens | Twitch Developers](#revoking-access-tokens-twitch-developers) - [Example Chatbot Guide | Twitch Developers](#example-chatbot-guide-twitch-developers) - [Test webhook events | Twitch Developers](#test-webhook-events-twitch-developers) - [الدليل حملة لـ Drops | Twitch Developers](#-drops-twitch-developers) - [Unity Engine Reference | Twitch Developers](#unity-engine-reference-twitch-developers) - [Get CLI version | Twitch Developers](#get-cli-version-twitch-developers) - [Using OIDC to get OAuth Access Tokens | Twitch Developers](#using-oidc-to-get-oauth-access-tokens-twitch-developers) - [Chat & Chatbots | Twitch Developers](#chat-chatbots-twitch-developers) - [Call API endpoints | Twitch Developers](#call-api-endpoints-twitch-developers) - [Use the mock data server | Twitch Developers](#use-the-mock-data-server-twitch-developers) - [Unity Getting Started | Twitch Developers](#unity-getting-started-twitch-developers) - [Drops Campaign Guide | Twitch Developers](#drops-campaign-guide-twitch-developers) - [Handling WebSocket Events | Twitch Developers](#handling-websocket-events-twitch-developers) - [IRC Concepts | Twitch Developers](#irc-concepts-twitch-developers) - [Sending and Receiving Chat Messages | Twitch Developers](#sending-and-receiving-chat-messages-twitch-developers) - [Authentication | Twitch Developers](#authentication-twitch-developers) - [Twitch Access Token Scopes | Twitch Developers](#twitch-access-token-scopes-twitch-developers) - [Configure the Twitch CLI | Twitch Developers](#configure-the-twitch-cli-twitch-developers) - [Test WebSocket Events | Twitch Developers](#test-websocket-events-twitch-developers) - [Handling Conduit Events | Twitch Developers](#handling-conduit-events-twitch-developers) - [Markers | Twitch Developers](#markers-twitch-developers) - [Schedule | Twitch Developers](#schedule-twitch-developers) - [Getting OAuth Access Tokens | Twitch Developers](#getting-oauth-access-tokens-twitch-developers) - [Twitch CLI | Twitch Developers](#twitch-cli-twitch-developers) - [Get an access token | Twitch Developers](#get-an-access-token-twitch-developers) - [EventSub Subscription Types | Twitch Developers](#eventsub-subscription-types-twitch-developers) - [EventSub | Twitch Developers](#eventsub-twitch-developers) - [WebSocket Messages | Twitch Developers](#websocket-messages-twitch-developers) - [Creator Goals | Twitch Developers](#creator-goals-twitch-developers) - [Polls | Twitch Developers](#polls-twitch-developers) - [Videos | Twitch Developers](#videos-twitch-developers) - [Prediction | Twitch Developers](#prediction-twitch-developers) - [Handling Webhook Events | Twitch Developers](#handling-webhook-events-twitch-developers) - [Managing Subscriptions | Twitch Developers](#managing-subscriptions-twitch-developers) - [Migrating from Twitch IRC | Twitch Developers](#migrating-from-twitch-irc-twitch-developers) - [Raids | Twitch Developers](#raids-twitch-developers) - [Extensions Guidelines & Policies | Twitch Developers](#extensions-guidelines-policies-twitch-developers) - [Increase Feedback | Twitch Developers](#increase-feedback-twitch-developers) - [Load Testing Extensions | Twitch Developers](#load-testing-extensions-twitch-developers) - [Monetization Strategies | Twitch Developers](#monetization-strategies-twitch-developers) - [Using Google Analytics in Extensions | Twitch Developers](#using-google-analytics-in-extensions-twitch-developers) - [Required Technical Background | Twitch Developers](#required-technical-background-twitch-developers) - [Monetization | Twitch Developers](#monetization-twitch-developers) - [Submission Best Practices | Twitch Developers](#submission-best-practices-twitch-developers) - [Drops Technical Guide | Twitch Developers](#drops-technical-guide-twitch-developers) - [Extensions | Twitch Developers](#extensions-twitch-developers) - [Using A/B Testing in Extensions | Twitch Developers](#using-a-b-testing-in-extensions-twitch-developers) - [Designing Extensions | Twitch Developers](#designing-extensions-twitch-developers) - [Using the Twitch API in an Extension Front End | Twitch Developers](#using-the-twitch-api-in-an-extension-front-end-twitch-developers) - [Get Started | Twitch Developers](#get-started-twitch-developers) - [Extensions Reference | Twitch Developers](#extensions-reference-twitch-developers) - [Game Engine Plugins | Twitch Developers](#game-engine-plugins-twitch-developers) - [Unknown](#unknown) - [Life Cycle Management | Twitch Developers](#life-cycle-management-twitch-developers) - [Authenticating and Setting up EventSub | Twitch Developers](#authenticating-and-setting-up-eventsub-twitch-developers) - [Building Extensions | Twitch Developers](#building-extensions-twitch-developers) - [Reference | Twitch Developers](#reference-twitch-developers) --- # Twitch Developer Documentation | Twitch Developers [Contents](https://dev.twitch.tv/docs#) Twitch Developer Documentation ============================== > Reviews for chatbot verification continue to be temporarily paused while we revise our processes. Reviews for Extensions, developer organizations, and game ownership have resumed. Thank you for your patience and understanding. Welcome to the Twitch developer documentation site. Here you’ll find the information needed to develop third-party experiences with Twitch. | Products | Concepts | Informative Resources | | --- | --- | --- | | [Twitch API](https://dev.twitch.tv/docs/api)


[EventSub](https://dev.twitch.tv/docs/eventsub)


[Extensions](https://dev.twitch.tv/docs/extensions)


[Chat & Chatbots](https://dev.twitch.tv/docs/irc)


[PubSub](https://dev.twitch.tv/docs/pubsub)


[Embedding Twitch](https://dev.twitch.tv/docs/embed)


[Drops](https://dev.twitch.tv/docs/drops)


[Game Engine Plugins](https://dev.twitch.tv/docs/game-engine-plugins) | [Authentication](https://dev.twitch.tv/docs/authentication)


[Organizations](https://dev.twitch.tv/docs/companies)


[Insights & Analytics](https://dev.twitch.tv/docs/insights)


[Mobile Deep Links](https://dev.twitch.tv/docs/mobile-deeplinks)


[Video Broadcast](https://dev.twitch.tv/docs/video-broadcast) | [Changelog](https://dev.twitch.tv/docs/change-log)


[Product Lifecycle](https://dev.twitch.tv/docs/product-lifecycle) | What’s New? ----------- [IRC PRIVMSG Tags](https://dev.twitch.tv/docs/chat/irc/#privmsg-tags) has been updated to include information about the new `gif` tag, including an example of the tag in use. _See all the latest documentation updates on the [changelog](https://dev.twitch.tv/docs/change-log) ._ Recent Announcements -------------------- Feedback and Assistance ----------------------- For help using Twitch developer products, or to let us know about product or documentation improvements: * Ask questions on the [Twitch Developer Forums](https://discuss.dev.twitch.tv/) . * Chat with the community on [Discord](https://link.twitch.tv/devchat) . * Provide feedback suggestions on [UserVoice](https://twitch.uservoice.com/forums/310213-developers) . * File issues or bug reports on [GitHub](https://github.com/twitchdev/issues/issues/) . * Reach out on [Twitter](https://twitter.com/twitchdev) . Terms of Use ------------ By accessing or using the Twitch API and other developer products, you agree to comply with and be bound by the [Twitch Developer Services Agreement](https://www.twitch.tv/p/legal/developer-agreement/) . If you do not agree to be bound by the Twitch Developer Agreement, do not access or otherwise use Twitch developer products. Provide feedback for this page There's no need to go alone! ---------------------------- [Get Support](https://dev.twitch.tv/support/) [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Reference | Twitch Developers [Contents](https://dev.twitch.tv/docs/video-broadcast/reference/#) | Endpoint | Description | | --- | --- | | [Get Ingest Servers](https://dev.twitch.tv/docs/video-broadcast/reference/#get-ingest-servers) | Get Ingest Servers returns a list of endpoints for ingesting live video into Twitch. | Get Ingest Servers ------------------ [✎](cloudcannon:#content_blocks[0]) Get Ingest Servers returns a list of endpoints for ingesting live video into Twitch. ### URL `GET https://ingest.twitch.tv/ingests` ### Authentication None ### Return Values | | | | | --- | --- | --- | | Parameter | Type | Description | | `ingests` | array | Array of Ingest Server objects. | | `_id` | integer | Sequential identifier of ingest server. | | `availability` | float | Reserved for internal use. | | `default` | boolean | Reserved for internal use. | | `name` | string | Descriptive name of ingest server. | | `url_template` | string | RTMP URL template for ingest server | | `priority` | integer | Reserved for internal use. | ### Example Request curl -X GET 'https://ingest.twitch.tv/ingests' ### Example Response ​​​​​​{ "ingests": [\ {\ "_id": 0,\ "availability": 1.0,\ "default": false,\ "name": "US East: Atlanta, GA",\ "url_template": "rtmp://atl.contribute.video.net/app/{stream_key}",\ "priority": 0\ },\ {\ "_id": 1,\ "availability": 1.0,\ "default": false,\ "name": "US East: Ashburn, VA (5)",\ "url_template": "rtmp://iad05.contribute.video.net/app/{stream_key}",\ "priority": 1\ },\ {\ "_id": 2,\ "availability": 1.0,\ "default": false,\ "name": "US East: Ashburn, VA (3)",\ "url_template": "rtmp://iad03.contribute.video.net/app/{stream_key}",\ "priority": 2\ },\ {\ "_id": 3,\ "availability": 1.0,\ "default": false,\ "name": "US East: Chicago, IL (2)",\ "url_template": "rtmp://ord02.contribute.video.net/app/{stream_key}",\ "priority": 3\ },\ {\ "_id": 4,\ "availability": 1.0,\ "default": false,\ "name": "US East: Chicago, IL (3)",\ "url_template": "rtmp://ord03.contribute.video.net/app/{stream_key}",\ "priority": 4\ }\ ] } [+](cloudcannon:#content_blocks[+]) [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Twitch API | Twitch Developers [Contents](https://dev.twitch.tv/docs/api/#) Twitch API ========== The Twitch API provides the tools and data used to develop Twitch integrations. The data models and systems are designed to provide relevant data in an easy, consistent, and reliable way. For the full list of endpoints that you can use in your integration, explore the [Twitch API Reference](https://dev.twitch.tv/docs/api/reference/) . The Twitch API uses OAuth 2.0 for authentication. To learn about the different types of access tokens that the API supports, see [Authentication](https://dev.twitch.tv/docs/authentication/) . If you plan to use some of the extension-related endpoints, you’ll also need learn how to get JSON Web Tokens (JWT) (see [JSON Web Tokens](https://dev.twitch.tv/docs/extensions/required-technical-background#json-web-tokens-jwts) and [Managing Extension Secrets](https://dev.twitch.tv/docs/extensions/building#managing-extension-secrets) ). For information about using the APIs, see the following guides: * [Starting a Poll](https://dev.twitch.tv/docs/api/polls) * [Starting a Prediction](https://dev.twitch.tv/docs/api/predictions) * [Starting a Raid](https://dev.twitch.tv/docs/api/raids) * [Creating Stream Clips](https://dev.twitch.tv/docs/api/clips) * [Creating Stream Markers](https://dev.twitch.tv/docs/api/markers) * [Getting Videos](https://dev.twitch.tv/docs/api/videos) * [Scheduling Broadcasts](https://dev.twitch.tv/docs/api/schedule) * [Moderating a Broadcaster’s Chat](https://dev.twitch.tv/docs/api/moderation) * [Getting a Creator’s Goals](https://dev.twitch.tv/docs/api/goals) * [Getting an Extension Analytics Report](https://dev.twitch.tv/docs/insights#extension-developer-analytics) * [Getting a Game Analytics Report](https://dev.twitch.tv/docs/insights#game-developer-analytics) You should also become familiar with the following features: | Feature | Description | | --- | --- | | [EventSub](https://dev.twitch.tv/docs/eventsub) | The Twitch API provides APIs that you can call to poll the status of a given resource. These APIs are fine if you need a snapshot of the resource but it’s recommended that you subscribe to receive resource updates instead. For information about subscribing to events, see [EventSub](https://dev.twitch.tv/docs/eventsub)
subscriptions. | | [Command-line Interface](https://dev.twitch.tv/docs/cli) | Twitch offers a command-line interface for managing Twitch resources. You can use it to call the Twitch endpoints, get an OAuth access token, and test EventSub events. | Next steps ---------- Call your first Twitch API in minutes using [Getting started](https://dev.twitch.tv/docs/api/get-started) . Thumb through Twitch API [Concepts](https://dev.twitch.tv/docs/api/guide) to learn how Twitch [handles breaking changes](https://dev.twitch.tv/docs/api/guide#breaking-changes) , [pagination](https://dev.twitch.tv/docs/api/guide#pagination) , and [rate limits](https://dev.twitch.tv/docs/api/guide#twitch-rate-limits) . Join our [community](https://link.twitch.tv/devchat) of Twitch developers! And for other ways to connect with the community, explore our [developer support](https://dev.twitch.tv/support) page. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Twitch API Concepts | Twitch Developers [Contents](https://dev.twitch.tv/docs/api/guide/#) Twitch API Concepts =================== This topic contains concepts that you should be familiar with when working with the Twitch API. Breaking changes ---------------- In rare cases it may be necessary to introduce breaking changes to the Twitch API. Twitch will provide as much notification as possible prior to introducing a breaking change; however, there may be times when providing prior notification isn’t possible (for example, to address security or privacy issues). Twitch uses the **Announcement** section of the [Twitch Developer Forum](https://discuss.dev.twitch.tv/c/announcements/) to provide notification of a pending breaking change. To prevent disruption of your application or service, be sure to update your application as appropriate and in a timely fashion. The notification will identify all programming elements involved in the breaking change and will provide guidance on work-arounds if available. Some of the reasons why Twitch may introduce a breaking change, include but are not limited to: * Security issues * Privacy concerns * Legal concerns * A bug that prevents the API from working as intended (for example, adding or updating constraints, adding required parameters without default values, or changing the response data) * A business change that requires removal of an API or feature of an API such as removing an option to retrieve a single resource instead of the entire list ### Non-breaking changes Twitch may make the following non-breaking changes without prior notification: * Add optional query parameters or fields to a request * Add new values to the list of possible values that you can set the request’s query parameters or fields to * Add fields to the response (your code should ignore any fields that it doesn’t expect) * Change the order of the fields in the response * Add or update error message strings (your code should not take dependencies on message strings) * Change the path, query parameters, or fragment of a URL that the API returns such as image URLs (your code should not take dependencies on the URLs that the API returns except where noted) To discover non-breaking changes, review the [change log](https://dev.twitch.tv/docs/change-log) . ### Taking dependencies Your application should not take dependencies on: * Error message strings * URLs that the API returns (except where noted) * The format of strings in the API responses Twitch Rate Limits ------------------ To protect Twitch services, and to make sure there are enough resources for all partners, Twitch limits the number of requests a client ID (app) may make. If your app exceeds the limit, the request returns HTTP status code 429 (Too Many Requests). ### How it works Twitch uses a token-bucket algorithm to ensure the limits are respected. Your app is given a bucket of points. Each endpoint is assigned a points value (the default points value per request for an endpoint is 1). When your app calls the endpoint, the endpoint’s points value is subtracted from the remaining points in your bucket. If your bucket runs out of points within 1 minute, the request returns status code 429. Your app is given a bucket for app access requests and a bucket for user access requests. For requests that specify a user access token, the limits are applied per client ID per user per minute. If an endpoint uses a non-default points value, or specifies different limit values, the endpoint’s documentation identifies the differences. For details about the Extensions API rate limits, see [Extension rate limits](https://dev.twitch.tv/docs/extensions/frontend-api-usage#rate-limits) . **Note:** Some API endpoints may return HTTP 429 response codes for reasons unrelated to the general rate limit bucket. In these cases, you must parse the error message returned to determine the reason for the response. ### Keeping track of your usage The API includes the following headers with each response to help you stay within your request limits. * `Ratelimit-Limit` — The maximum rate of your bucket. * `Ratelimit-Remaining` — The number of points in your bucket. * `Ratelimit-Reset` — A Unix epoch timestamp that identifies when your bucket is reset to full. An example of these headers: Ratelimit-Limit: 800 Ratelimit-Remaining: 799 Ratelimit-Reset: 1781653392 If you receive HTTP status code 429, use the `Ratelimit-Reset` header to learn how long you must wait before making another request. Pagination ---------- The Twitch API supports cursor-based pagination for APIs that return lists of resources. List APIs like [Get Videos](https://dev.twitch.tv/docs/api/reference#get-videos) use the following query parameters to control paging: * _after_ — Use to get the next page of results * _before_ — Use to get the previous page of results * _first_ — Use to specify the number of items to include per page The _after_ and _before_ parameters are mutually exclusive; you may specify only one of them in the request. If the list API is able to return another page of results, the response includes the `pagination` field, which is a **Pagination** object that includes the `cursor` field. "pagination": { "cursor": "eyJiI..." } Use the cursor’s value to set the _after_ or _before_ query parameter depending on the direction you want to page. See [Forward pagination](https://dev.twitch.tv/docs/api/guide/#forward-pagination) and [Backward pagination](https://dev.twitch.tv/docs/api/guide/#backward-pagination) . The **Pagination** object is empty if there are no more pages to return in the direction you’re paging. "pagination": {} ### Specifying the page size List APIs return a default number of items per page. For example, the default page size for [Get Streams](https://dev.twitch.tv/docs/api/reference#get-streams) is 20 items per page. To specify a different page size, include the _first_ query parameter with each request. curl -X GET 'https://api.twitch.tv/helix/streams?first=40' \ -H 'Authorization: Bearer ' \ -H 'Client-Id: ' The API’s documentation specifies the minimum page size, maximum page size, and default page size. For example, the maximum page size for Get Streams is 100. An API may return less than the number of items requested per page, which is often the case for the last page of results. ### Forward pagination To get the first page, don’t specify the _after_ query parameter. curl -X GET 'https://api.twitch.tv/helix/streams?first=40' \ -H 'Authorization: Bearer ' \ -H 'Client-Id: ' To get the next page, and all subsequent pages, set the _after_ query parameter to the value in the `cursor` field of the response’s **Pagination** object. The cursor marks the top of the next page of results. curl -X GET 'https://api.twitch.tv/helix/streams?first=40&after=eyJiI...' \ -H 'Authorization: Bearer ' \ -H 'Client-Id: ' You’ll know you’re at the end of the list when the response contains an empty **Pagination** object. ### Backward pagination Not all APIs support paging backward. Check the documentation to confirm whether the API supports backward pagination — the API supports backward pagination if the list of query parameters includes the _before_ query parameter. To page backward through a list, set the _before_ query parameter to the value in the `cursor` field of the response’s **Pagination** object. The cursor marks the top of the previous page of results. curl -X GET 'https://api.twitch.tv/helix/streams?first=40&before=eyJiI...' \ -H 'Authorization: Bearer ' \ -H 'Client-Id: ' You’ll know you’re at the beginning of the list when the response contains an empty **Pagination** object. To page forward when you’re at the top of the list, don’t include a cursor parameter. If you page forward to the end of the list, the **Pagination** object is empty. Because of this, you must keep a copy of the previous cursor to use to page backward. ### Lists are dynamic Because lists are dynamic views of the data, it’s possible that the cursor may return an empty page (`"data":[]`) when you’re near the end of the list. It’s also possible that you might see the same data on multiple pages. For example, [Get Streams](https://dev.twitch.tv/docs/api/reference#get-streams) orders the list of streamers by the number of viewers they have. If the streamer’s viewership changes between the time you get the cursor and the the time the user pages forward or backward, it’s possible that the streamer could have moved up or down in the list and the user would see them on both pages. For the same reason, it’s also possible that if the user pages forward and then backward, the contents of the previous page may be partially or fully different depending on how volatile the data is. ### Known issues The following list contains known issues that you should consider when designing your app. 1. The [Get EventSub Subscriptions](https://dev.twitch.tv/docs/api/reference#get-eventsub-subscriptions) endpoint doesn’t let you specify the page size (the _first_ query parameter is not supported). 2. The [Get Extension Live Channels](https://dev.twitch.tv/docs/api/reference#get-extension-live-channels) endpoint doesn’t use the same **Pagination** object as the other endpoints that support paging. Instead, it contains a `pagination` field that contains either an empty string or a cursor value. Query Parameters ---------------- Things to know about endpoint query parameters and fields. ### IDs are opaque All IDs are strings and should be considered opaque, meaning its value can be anything. All POST operations that add a resource will return the resource’s ID and all GET operations include the resource’s ID. ### Required versus optional parameters All required query parameters and fields are marked as required. You should consider all other fields optional. Some endpoints such as [Get Videos](https://dev.twitch.tv/docs/api/reference#get-videos) specify required query parameters that are mutually exclusive, meany you may specify only one of the required parameters that are marked as mutually excluisve. The description for these parameters clearly will indicate that they are mutually exclusive. ### Specifying multiple query parameter values Some endpoints use query parameters to filter the data. If a query parameter lets you specify a list of values, you must specify the query parameter for each value in the list; the list is not comma delimited. For example, to specify multiple _login_ values, you’d specify them as `&login=twitch&login=twitchdev&login=twitchgaming`. ### Enumeration values If a query parameter lists a set of enumeration values, consider the list case sensitive unless stated otherwise. ### Timestamps All date and time query parameters and fields used in the Twitch API are in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) format. For example, YYYY-MM-DDT00:00:00.000Z. **NOTE** The timestamps used in all [EventSub](https://dev.twitch.tv/docs/eventsub) events are in RFC3339 format; however, the timestamps use nanoseconds instead of milliseconds. For example, YYYY-MM-DDT00:00:00.000000000Z. ### Pagination parameters Some GET endpoints that return lists of resources support pagination. For details, see [Pagination](https://dev.twitch.tv/docs/api/guide/#pagination) . cURL Examples ------------- All cURL examples shown throughout the Twitch API documentation use UNIX and Linux format. This means that the examples will not run as-is on Microsoft Windows computers. To run the examples on Windows computers, you must change the continuation marks from `\` to `^` and change the single quotes to double quotes. A UNIX formatted cURL query: curl -X POST 'https://id.twitch.tv/oauth2/token' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'client_id=&client_secret=&grant_type=client_credentials' The equivalent Windows cURL query: curl -X POST "https://id.twitch.tv/oauth2/token" ^ -H "Content-Type: application/x-www-form-urlencoded" ^ -d "client_id=&client_secret=&grant_type=client_credentials" Twitch API Health ----------------- If you receive an HTTP status code 503 (Service Unavailable) error, retry once. You may also report any issue that appears to be a bug via [GitHub Issues](https://github.com/twitchdev/issues/issues) . Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Clips | Twitch Developers [Contents](https://dev.twitch.tv/docs/api/clips/#) Clips ===== Clips lets Twitch viewers share interesting moments from broadcasts while letting broadcasters grow their channels through social sharing! [Read more](https://help.twitch.tv/s/article/how-to-use-clips) Creating Clips -------------- To create a clip from a broadcaster’s stream, use the [Create Clip](https://dev.twitch.tv/docs/api/reference#create-clip) API. It’s easy to use, just specify the ID of the broadcaster whose stream you want to create a clip from. The OAuth user access token must include the **clips:edit** scope. curl -X POST 'https://api.twitch.tv/helix/clips?broadcaster_id=123456' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' The following example shows the request’s response. { "data": [\ {\ "id": "FunPoisedGiraffeGingerPower-KDy2fwLNuUEHU",\ "edit_url": "https://clips.twitch.tv/FunPoisedGiraffeGingerPower-KDy2fwLNuUEHU/edit"\ }\ ] } Creating a clip is an asynchronous process that can take a short amount of time to complete. To determine whether the clip was successfully created, call [Get Clips](https://dev.twitch.tv/docs/api/reference#get-clips) using the clip ID that the request returned. If Get Clips returns the clip, the clip was successfully created. If, after 15 seconds, Get Clips hasn’t returned the clip, assume it failed. The API captures up to 90 seconds of the broadcaster’s stream. The 90 seconds spans the point in the stream when you called the API; about 85 seconds of the stream before the call and about 5 seconds after the call. For example, if you called the API at the 4:00 minute mark, the API captures from approximately the 3:35 mark to approximately the 4:05 minute mark. While Twitch tries its best to capture 90 seconds of the stream, the actual length may be less. For example, it may be less if you begin capturing the clip near the beginning or end of the stream. By default, Twitch publishes up to the last 30 seconds of the 90 seconds window and provides a default title for the clip. If you want control over the title and which portion of the 90 seconds window is used as the clip, use the URL in the response’s `edit_url` field. You can specify a clip that’s from 5 seconds in length to 60 seconds in length. The URL is valid for up to 24 hours or until the clip is published, whichever comes first. ### Setting optional parameters The API provides an optional _has\_delay_ query parameter. Use this parameter to capture the clip at the time the viewer requests it or after a delay. If **false**, the API captures the clip at the point in time that the viewer requests it (this is the same experience that the Twitch UX provides). If **true**, Twitch adds a delay before capturing the clip, which basically shifts the capture window to the right slightly. The default is **false**. ### Possible issues you can run into You may only capture clips: * If the broadcaster is streaming. * If the broadcaster has enabled clips (see **Clips Settings** under **Creator Dashboard**, **Settings**, **Stream**). * If the broadcaster hasn’t enabled the follower-only or subscribers-only clips settings, or if they have, you are a subscriber or a follower that has followed the broadcaster the required amount of time. Getting clips ------------- To get clips, use the [Get Clips](https://dev.twitch.tv/docs/api/reference#get-clips) API. The API lets you get [specific clips](https://dev.twitch.tv/docs/api/clips/#getting-a-specific-clip) , get [clips captured from a specific game](https://dev.twitch.tv/docs/api/clips/#getting-a-games-clips) , or get [clips captured from a specific broadcaster’s streams](https://dev.twitch.tv/docs/api/clips/#getting-a-broadcasters-clips) . You can use any valid OAuth token to get clips, such as an app access token or user access token. For example, if you’re also creating clips, just use that user access token. Depending on the broadcaster or game, it’s possible that the results may contain a large number of clips. By default, the API returns 20 clips. If the results contain more than 20 clips, the response’s `pagination` field includes a `cursor` that you use to get the next page of clips. For information about paging results, see [Pagination](https://dev.twitch.tv/docs/api/guide#pagination) . Only specify the pagination parameters (_first_, _after_, and _before_) if you specify the _game\_id_ or _broadcaster\_id_ query parameter. The following example shows what the Get Clips response looks like. The broadcaster fields identify the broadcaster whose stream the clip was captured from and the creator fields identify the viewer that captured the clip. To get the game’s title, use the [Get Games](https://dev.twitch.tv/docs/api/reference#get-games) API and set the _id_ query parameter to the ID in the `game_id` field. Use the URL in the `embed_url` field to embed the clip in your user experience (see [Embedding Video and Clips](https://dev.twitch.tv/docs/embed/video-and-clips/) ). Note that the `title` field may not contain useful information. { "data": [\ {\ "id": "AnimatedOptimisticWasabiVoteNay",\ "url": "https://clips.twitch.tv/AnimatedOptimisticWasabiVoteNay",\ "embed_url": "https://clips.twitch.tv/embed?clip=AnimatedOptimisticWasabiVoteNay",\ "broadcaster_id": "423168062",\ "broadcaster_name": "qa_vod_automation",\ "creator_id": "7036025",\ "creator_name": "Crono",\ "video_id": "704533034",\ "game_id": "27471",\ "language": "en",\ "title": "a",\ "view_count": 1198514,\ "created_at": "2020-08-10T17:04:10Z",\ "thumbnail_url": "https://clips-media-assets2.twitch.tv/100660082970470268-offset-153206-preview-480x272.jpg",\ "duration": 28,\ "vod_offset": 222,\ "is_featured": true\ },\ . . .\ ], "pagination": { "cursor": "eyJiIjpudWxsLCJhIjp7IkN1cnNvciI6Ik1qQT0ifX0" } } ### Offset to the clip in the video Clips include a `vod_offset` field, which contains the offset, in seconds, from the beginning of the video to the start of the clip. Twitch keeps videos for a minimum amount of time before deleting them and broadcasters can also delete their videos. If the video is no longer available, the `video_id` field is set to an empty string and the `vod_offset` field is set to **null**. If you get a clip that was created during the current broadcast, the `video_id` field may contain an empty string and the `vod_offset` field may contain **null**. This is because there’s a delay between when a clip is created during a broadcast and when the offset is determined. The delay is indeterminate but typically lasts minutes. If you get the clip after the delay, the `video_id` field will contain the video’s ID and the `vod_offset` field will contain the clip’s offset. ### Getting a broadcaster’s clips To get clips captured from a specific broadcaster’s streams, use the _broadcaster\_id_ query parameter. curl -X GET 'https://api.twitch.tv/helix/clips?broadcaster_id=123456' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' The clips are returned in descending order of views. Because the request could return thousands of results to page through, you could use the _first_ query parameter to get the top 10 clips with the most views. Or, to get clips captured within a specific date range, use the _started\_at_ and _ended\_at_ query parameters (see [Getting clips captured within a specific date range](https://dev.twitch.tv/docs/api/clips/#getting-clips-captured-within-a-specific-date-range) ). ### Getting a game’s clips To get clips captured from a specific game, use the _game\_id_ query parameter. The following example shows how to get all clips captured from broadcasters that were playing Minecraft. curl -X GET 'https://api.twitch.tv/helix/clips?game_id=27471' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' The clips are returned in descending order of views. Because the request could return thousands of results to page through, you could use the _first_ query parameter to get the top 10 clips with the most views. Or, to get clips captured within a specific date range, use the _started\_at_ and _ended\_at_ query parameters (see [Getting clips captured within a specific date range](https://dev.twitch.tv/docs/api/clips/#getting-clips-captured-within-a-specific-date-range) ). To get a game’s ID, use the [Search Categories](https://dev.twitch.tv/docs/api/reference#search-categories) API. ### Getting a specific clip To get specific clips, use the _id_ query parameter. Include the _id_ query parameter for each ID that you specify. You may specify a maximum of 100 IDs. curl -X GET 'https://api.twitch.tv/helix/clips?id=SpillYummyPigeonPieHuhu&id=DillDiligentTireOneHand' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' If you specify the _id_ query parameter, the API ignores the pagination query parameters and date range parameters. ### Getting clips captured within a specific date range By default, Get Clips returns all clips that were captured for the specified game or broadcaster. If you’re only interested in clips for a specific date range like the last week or yesterday, use the _started\_at_ and _ended\_at_ query parameters. Dates are UTC. The following example shows how to get clips that were captured in the last week from the specified broadcaster’s streams. curl -X GET 'https://api.twitch.tv/helix/clips?broadcaster_id=123456&started_at=2022-07-03T00:00:00Z&ended_at=2022-07-09T00:00:00Z' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' The _ended\_at_ parameter is optional. If you don’t specify it, the date range is one week from the start date. The following example shows how the above request could have been written: curl -X GET 'https://api.twitch.tv/helix/clips?broadcaster_id=123456&started_at=2022-07-03T00:00:00Z' \ -H 'Authorization: Bearer n6fyjy1qlo2hmzzt3bdjhkdgda4d' \ -H 'Client-Id: hof5gwx0su6owfnys0nyac87zr6t' Specify a date range only if you specify the _game\_id_ or _broadcaster\_id_ query parameter. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Build Your Backend | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/build-backend/#) Extension 101 tutorial series ============================= Build Your Backend ================== We will now move on to integrating a backend for your Extension. Having a backend is important if you want to a) process business logic that shouldn’t be exposed to the front end or b) establish connections and integrations into other services such as a database. Extension backends can be in any language, use any hosting, and utilize any database. In this tutorial, we will be building a backend to save the questions the viewers submitted and display them to the broadcaster via the live configuration page on the dashboard. Software used in this tutorial includes: * [MongoDB](https://www.mongodb.com/) : a simple NoSQL database * [Mongoose](https://mongoosejs.com/) : Object Data Modeling Library * [Express](https://expressjs.com/) : a Node.js framework * The following additional libraries: [body-parser](https://mongoosejs.com/) , JSONWebToken * homebrew **Note:** You can use any database service that you are familiar with. Step 1: Set up Your System -------------------------- 1. Install Node.js. Please refer to tutorial 4 for directions on how to install it. 2. Install MongoDB locally. A quick way to install MongoDB is to use homebrew. 3. We also need to install libraries we will need (Express, Mongoose, Body-Parser, and JSONWebToken) via the Node Package Manager (NPM). Open your terminal and navigate to the local project directory. Enter the following commands: npm init -yes npm install express mongoose body-parser jsonwebtoken --save **Note:** Even though we are installing the `jsonwebtoken` library here, we won’t be using it until the next section. Step 2: Understanding the Backend.js starter code ------------------------------------------------- We provided some of the basic code needed to set up Express and Mongoose in backend.js. Let’s take a second to understand what we are doing in this provided starter code. ### Importing Libraries On lines 2-4, we have imported the necessary libraries that we will use: `express`, `Mongoose`, `body-parser`, and `jsonwebtoken`. #### Express * **Create an Express App**: On lines 8-10, we create an express app. * **Start the Server**: On lines 13-15, we use [`app.listen`](https://expressjs.com/en/api.html#app.listen) to start the server and listen on the defined port of 3000. * **Use body parser**: On line 18, we use [`body-parser`](https://expressjs.com/en/resources/middleware/body-parser.html) , which helps parse incoming HTTP request bodies. We’ll see this being utilized more directly in the next step. #### Mongoose * **Connect to Mongoose**: On line 24, we connect to mongoose using the `mongoose.connect()` [method](https://mongoosejs.com/docs/connections.html) . The first argument we pass into this method is the URI Connection String, which tells Mongoose where to connect to. Specifically, we are connecting to “mongodb://localhost:27017/WYR-test,” where localhost:27017 is the default host where the `mongod` instance is running, and WYR-test is the database we want to save the information to, * **Define Mongoose Model**: In lines 26-29, we are creating a [Model](https://mongoosejs.com/docs/models.html) . Models in Mongoose are classes that define our database schema. Thus, the first argument we pass into the model method, provides the name of the collection, and the second argument is our schema that defines the properties of the documents. So in this function, we are creating a Question collection, that’s made of documents that each have properties to represent the two WYR dilemmas the users selected. The language of model, collection, and documents can be confusing but we can just view documents as a subset of collections, and collections as a subset of models! **Note:** We recommend looking at additional resources such as the [Mongoose](https://mongoosejs.com/docs/index.html) and [Express](https://expressjs.com/en/starter/hello-world.html) Getting Started tutorials for a deeper understanding of how we are building this backend. Step 3: Submitting questions to the database -------------------------------------------- Now that we’ve set up our basic Mongoose and Express backend, we will use this framework to save the questions the users submit. When a user clicks the submit button in the panel view, we need to send an [AJAX request](https://www.w3schools.com/xml/ajax_xmlhttprequest_send.asp) to the backend. Add the following function to `viewer.js`: Through this function, a [POST request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) is sent to the given URL with the specified data. Going back to the Mongoose vocabulary we defined earlier: whenever a user submits a question, we want to enter a document into the defined Question collection. Let’s see how the backend takes care of this. The AJAX request is sent to the provided URL which points to the Express `app.post()` routing method. In this routing method, we have handler function `/question` that is called when the POST request is received. Add this method to the `backend.js` file. In this method, we use the body of the request, which contains the user’s options to create the myData document, an instance of the Question model. We can easily view and parse the user’s options from the body of the request because of the body-parser package we imported. We then use the [save function](https://mongoosejs.com/docs/api/model.html#model_Model-save) to save the newly created document to the database as a JSON object. Step 4: Displaying submitted questions on Live Config Page ---------------------------------------------------------- Now that we’ve saved the user’s submitted questions, we want the broadcaster to be able to view these questions in the live configuration page. Right now, the live config page displays a button. Once the broadcaster clicks this button, they should be able to see all the submitted questions from different viewers. Add the following function to `live_config.js`. Through this function, a [GET request](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) is sent to the given URL. We want to retrieve all the documents in the defined Question collection. Once this request is handled successfully, we want to change the UI from displaying a button to displaying the submitted questions. Lines 7-13 handle this. The AJAX request is sent to the provided URL which points to the Express `app.get()` routing method. In this routing method, we have handler function `/questions` that is called when the GET request is received. Add this method to the `backend.js` file. In this method, we use the [find function](https://mongoosejs.com/docs/api.html#model_Model.find) to find all documents in the collection, and send them back in the response. **Check**: Code until this point is available on [Step 2 Branch](https://github.com/sonia145/extensions-101/tree/step-2) . Before we test it, we have to explore a very important topic of how we can keep this communication between the frontend and the backend secure! Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Configuration Service | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/config-service/#) Extension 101 tutorial series ============================= Configuration Service ===================== Now that we’ve set up the basic architecture of an Extension, let’s explore how different pages interact with each other. The first interaction we are going to look at is between the broadcaster’s configuration page and the viewer’s page. Specifically, we want to be able to save the broadcaster’s preferences for what WYR options should be shown to the viewers, and present those selected options to the viewer in the panel view. We can use the Twitch-provided Configuration Service to allow the broadcaster to customize the Extension. **Key Concept**: We can think of the Configuration Service as a key-value pair service for basic data stores. By allowing the developer to easily read and write to a store, the Configuration Service helps developers because it: * Removes the need for using a backend to store persistent per-channel and per-Extension specific information * Stores user IDs to call third-party APIs from your backend (if you have one) * Enables broadcasters to customize your Extension Step 1: Config View Logic ------------------------- In the broadcaster’s configuration page, we can use jQuery to write a function that will retrieve all the selected options in the fieldset form we say in previous tutorial and then save them as an array. We need to add the following function to `config.js`: Step 2: Set Configuration ------------------------- We now need to write the saved broadcaster’s options that we saved as an array to the configuration service. To do this, we are going to use the `twitch.configuration.set` function from the Extensions Helper Library to essentially set the Extension Configuration. **Key Concept**: An Extension configuration is made up of segments that consist of three values: type, Extension version, and configuration value. Segment types refer to who can read and write the configurations, and thus can be set to the broadcaster, developer, or global. More information on these types can be found in the documentation for the [configuration service](https://dev.twitch.tv/docs/extensions/building/#using-the-configuration-service) . For this Extension, the broadcaster is setting the configuration, for version one, and saving a value of options (needs to be saved as a string). Thus, we need to add the following function to the `config.js`. For more information on the set function, check out the [Extension Helper Library](https://dev.twitch.tv/docs/extensions/reference#helper-configuration) . Step 3: `onChanged` Configuration --------------------------------- The next thing is to render the broadcaster’s options in the viewer’s panel. We can access the configuration information that was set in the previous step through `twitch.configuration.broadcaster.content`. However, we should only access this information inside the `twitch.configuration.onChanged` function when the contents of the broadcaster variable have completely loaded. This `onChanged` function essentially is called when an Extension configuration is received, which happens only once, on extension load! Once you have the contents of your configuration, you can parse the values and update the panel view. To do this, add the following function to `config.js` and `viewer.js`. On line 11, you can see that we are calling a function called `updateOptions()`. This function is going to update the options on the viewer side. Let’s add this next! Step 4: PanelView Logic ----------------------- We want the Extension to be able to save the WYR options that the broadcaster selected in `config.html` and provide them to the viewer’s interface, `panel.html`, as selectable options in the drop down menus. To do this, we need some basic javascript logic that will be able to take an array and present each item of the array as an option in the drop down menu. Add the following function to `common.js`. Now that we’ve set up the Configuration Service, it’s time to test it. **Check**: If you want to see the completed code at this stage, its available on the Step 1 branch. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Extension File Structure and HTML Views | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/file-structure/#) Extension 101 tutorial series ============================= Extension File Structure and HTML Views ======================================= Environment Set-Up ------------------ In this section, we are going to start building the Extension. But before that, you need to download the starter code from the following Github repository using the green Clone or Download button here: [https://github.com/sonia145/Extensions-101](https://github.com/sonia145/Extensions-101) . Your Extension’s directory should look something like this: Would You Rather - config.html - panel.html - live_config.html - config.js - viewer.js - live_config.js - common.js - backend.js Save these files in a local directory. Feel free to open these files up in a text editor and follow along as we walk through the basic front-end architecture of the Extension. **Important!** This code is intentionally incomplete and there are active development steps, but if you get stuck, frustrated, bored, or are running low on time, you can instantly warp to the next step by switching branches. For example, to complete step two and skip to step three, either: * Click **step-two** on github.com and download those files if you prefer downloading, or * If you cloned the repository type `git checkout step-two` while in the directory where you cloned the workshop files, and then copy this new code to replace the files in your Extension directory. Step 1: Basic Front-end Architecture ------------------------------------ The front end is composed of HTML, JS, and CSS files. Every Extension needs to be comprised of at least two front-end pages: the viewer and configuration page. The viewer page is what the viewers will see and interact with on the broadcaster’s channel, and the configuration page is what the broadcaster sees when they are going through the Extension configuration process, which is a one-time setup when installing the Extension on their channel for the first time. There is an additional front end for the broadcaster’s live experience. In our WYR Extension, we are going to start with these three front-ends: * **Viewer Page** (panel.html): viewers will be able to build their own WYR questions from a list of options, and submit them to the broadcaster. * **Live Configuration Page** (live\_config.html): as viewers submit their WYR questions, they will be shown to the broadcaster in real-time via this page. * **Configuration Page** (config.html): the broadcaster will be able to see all the possible WYR options, and then only choose the ones that they would feel comfortable answering. ![Configuration page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-6.png) **Important**: Each page must load the Extension Helper Library, which is created and hosted by Twitch. This library provides methods for dealing with various critical services like authorization. You can see how this library is embedded in Line 43 of the config.html file. ### Further Consideration If you look in the file directory, you see that we call the viewer page, panel.html. We do this to clarify that this is specifically for the panel version of the Extension. We could also have another viewer page that supports another Extension type, such as an overlay. This allows developers to build out the same Extension in various different formats without needing to create a new Extension.On the broadcaster side, they can choose what type of extension format they want to activate on their channel. This information is sent as a [query parameter](https://dev.twitch.tv/docs/extensions/reference/#client-query-parameters) to the Extension window. This concept is called **Dynamic Anchors**. Step 2: Viewer Page ------------------- The purpose of the viewer page is for the viewers to be able to engage in a creative process of building a WYR dilemma, and then submit their question to the broadcaster. From a viewer’s perspective, they will see the following page: ![Viewer page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-7.png) In `panel.html`, we have created a form with select tags to provide two drop down lists. Through this user interface, the viewer can create their own WYR dilemma from options provided in drop down menus. Upon clicking submit, the viewer’s question will be saved. Step 3: Live Configuration Page ------------------------------- Through the live configuration page, broadcasters will be able to see the WYR questions coming in live from viewers. ![Live configuration page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-1.png) In `live_config.html`, we have a button that the broadcaster clicks on to to view the submitted questions. Once selected, a vertical table of questions will be shown to the viewer. Step 4: Configuration Page -------------------------- Through the broadcaster’s configuration page, they will be able to select options they would like viewers to be able to choose from. ![Configuration page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-8.png) In `config.html`, you will see that a basic fieldset form is already created that allows the broadcaster to select what WYR options viewers will be able to select from. All options are defaulted to checked so that it’s easier for the broadcaster to simply opt out of a certain option. ### Further Consideration As you can see from the HTML file, we are manually writing these options in as individual checkboxes. However, if we wanted to include more options without manually writing them in, we could use a backend service to save the options and just request for them to be shown on page load. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # JSON Web Tokens (JWT) | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/jwt/#) Extension 101 tutorial series ============================= JSON Web Tokens (JWT) ===================== We need to explore how to keep communications secure through JSON Web Tokens (JWTs). For more information about JWTs, look [here](https://jwt.io/) . **Concept:** A JSON Web Token (JWT) is a JSON object that is signed by Twitch, using a secret shared between Twitch and the Extension developer. The JWT contains properties such as `channelID` or `expiration_date`. To see other properties, consult the [JWT Schema](https://dev.twitch.tv/docs/extensions/reference/#jwt-schema) . Twitch Extensions specifically use two roles of JWTs: broadcaster and external. **Role 1: Broadcaster** * When the Extension is loaded into browser, a signed JWT is provided to the front-end iFrame through the Extension Helper Library’s `onAuthorized` callback function. * When the Extension’s front-end is communicating with backend, the token is sent and verified using the Extension’s shared secret. This helps prevent malicious users from directly calling the backend. **Role 2: External** * When the backend needs to call a Twitch API, it must generate, sign, and include a JWT in the header. This is known as “bearer token authentication.” By signing your own token with the shared secret, Twitch can authenticate that the API request is in fact coming from your backend. In this section, we will be demonstrating how to use a JWT to authorize the communication between the users and the Extension’s backend. Step 1: Adding Authorization Header to AJAX call ------------------------------------------------ When viewers submit a WYR question from the panel view, the JWT that was provided via onAuthorized needs to be sent in an HTTP header to the backend. Let’s go back to our AJAX `POST` call in `viewer.js` and pass in the JWT through the headers parameter by adding. Thus, our new AJAX call should look like this: Step 2: JWT Secret ------------------ Once the JWT is sent to the backend, the next step is verifying the authenticity of this token. We do this by using a **Shared Secret**. **Concept:** Each Extension maintains a shared secret that is used to sign tokens that validate the identity of users. Extension Secret is `base64` encoded and is provided to you by the Extension Manager. To retrieve the secret, lets go to the Extension Manager. To get to the Manager, go to the [console](https://dev.twitch.tv/console/extensions) , select a version of the Extension and click **Manage**. Once on this page, you will see the default status page. On the top right of the manager, click the **Extension Settings** button. You will see the following page: ![Extension settings](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-29.png) Under the **Extension Client Configuration** section, copy the key provided. We need to use this key to verify that the token provided is signed with the same secret. To use the key, we first need to save it and decode it from its `base64` encoding. Add the following lines to do this in `backend.js`: const key ="INSERT_YOUR_EXTENSION_SECRET_HERE"; const secret = Buffer.from(key, 'base64'); Step 3: Verify the JWT ---------------------- In the backend, we need to verify the JWT and save the JWT’s decoded content. We are going to create a function called verifyAndDecode in backend.js to carry out this logic: The parameter passed into this function is the header from the AJAX call that contains the token. Using this header, we extract out the token, and use the verify method from the `jsonwebtoken` library, which is just a simple Node.js Library for verifying and signing JSON Web Tokens. This method returns decoded information that the JWT contained. Now that we have created this function, let’s use it! We want to be able to call this `verifyAndDecode` method in the `app.post()` method. Remember, this method handles the response to the `POST` request. To do this, add the following line to the method: const payload = verifyAndDecode(req.headers.authorization); Thus, our routing method should now look like the following: Step 4: Testing --------------- Let’s test the extension! Since our extension is still in local testing, we can test the extension just like we did in Tutorial 4. Feel free to jump back to that section if you need to review how to test extensions in the console. With these new additions we’ve added, be sure to save your files. Navigate to your channel, and scroll down to the Panel Section to see the extension view that viewers will see if this was live: ![Panel section](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-33.png) Submit a question and you should see a **“Your Question has been submitted!”** response. Now let’s confirm that the streamer can view the question (and other viewer’s questions). To do this, you need to navigate to your creator dashboard and go to the Extensions panel. In the dropdown menu, you will see all the extensions you installed. **Click Would You Rather?**. You should then see the following screen: ![Extension panel](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-35.png) Clicking on the button should display the option you selected. Feel free to select more options and see how they will also be displayed. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Locally Test Your Extension | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/local-test/#) Extension 101 tutorial series ============================= Locally Test Your Extension =========================== To test the Extension, go to the [Extensions Developer Console](https://dev.twitch.tv/console/extensions) .​ From there, click **Manage** next to the Extension name, and you’ll be redirected to the same status page we saw in Tutorial #1. Step 1: Base URL ---------------- In Local Test, all Extension assets (files) are served from a defined testing base URI, so we need to use a local web server to host the files we’ve been working on in our local directory. Feel free to set up the local server in any way you want, and use any service. ### Local Server Setup One possible way to set up a local server is through Node.js. 1. Install [N​ode.js](https://nodejs.org/) 2. Run `n​pm install -g http-server` 3. Go into file directory and then run​ `http-server`. ​You will see something like this: ![http-server stdout](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-13.png) Once you have a server setup, click on the Asset Hosting Tab and edit the Testing Base URL to match URL from server set-up. ![Asset hosting tab](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-14.png) **Check:**​ ​Make sure when adding the URL of your local server into the section, that the URL ends with a forward slash (/). **Further Consideration:**​ During Local Test, the assets are served directly from this URI, so you can update your code without re-submitting the Extension version. In Hosted Test, you can just directly upload your files and test your Extension without a local server; however, if you want to change any of your Extension version details (_e.g._, name, description, images, etc), you must move back to Local Test. In Hosted Test, assets are hosted by Twitch are copied to the Twitch CDN (Content Delivery Network) and served from there. Step 2: Enabling the Configuration Service ------------------------------------------ Before testing the Extension, go to the Console Manager and enable the Configuration Service. Go to the **Capabilities** tab of the Extension Manager, and scroll down to the second frame, where you should see a section titled “Select how you will configure your Extension.” Select **Extension Configuration Service**​, and then save the changes. ![Enable configuration service](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-15.png) Step 3: Install, Configure, and Activate Your Extension ------------------------------------------------------- We are ready to see the Extension live on Twitch! To do so, go to the **Status** page of the Extension Manager, and scroll down to the section titled “Next Steps.” Click the ​**View on Twitch and Install**​ button. ![View on Twitch and Install](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-16.png) Clicking this button will open a new tab with the Extension Details page. ![Extension Details page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-17.png) **Installation:**​ Next, click the purple **I​nstall** ​button. When the Extension is installed, you will see a confirmation pop-up informing you that Extension installation is complete, and that if you want to activate the Extension right now, you need to configure it. !["Extension is installed" confirmation pop-up](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-18.png) **Configuration:**​ Click ​**Configure​**. Upon doing so, you will be directed to the Broadcaster Configuration Page. Here we see the page we created where the Broadcaster can select the options they want viewers to be able to choose from. Feel free to select a couple of these options and then click ​**Submit**​. After doing so, close out of this page. ![Broadcaster Configuration Page](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-19.png) Upon closing this window, we land upon the Extensions page in the Broadcaster’s Dashboard. ![Extensions page in the Broadcaster’s Dashboard](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-20.png) **Activation:​** From this dashboard, select the **W​ould You Rather…?** Extension then click the **Activate​** button. Upon doing so, you’ll see a couple of options. Select **S​et as Panel 1**​. If the activation is successful, you will see the following confirmation: ![Activation success modal](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-21.png) Step 4: Testing the Extension on Your Channel --------------------------------------------- Now it’s time to see how the Extension acts on the viewer side as a Panel. Navigate to your channel, and scroll down to the Panel Section (below the video player). You should see the following panel: ![Extension disclaimer](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-22.png) Clicking **A​ccept**​ will bring you to the Panel that viewers will see if this extension were live. ![Extension preview](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-23.png) **Check:**​ At this point, we have built a functioning Extension that utilizes the Configuration Service, and covered various concepts such as dynamic anchors, life cycle management, and Extension configuration. As you can see, the Configuration Service removes the need for a backend enables developers to build simple front-end-only Extensions that provide unique experiences for their viewers. However, in this Extension, we are going to set up a backend service to save the submitted WYR questions from the viewers, and present them live to the broadcaster. Even for Extensions like this one that require a back-end, the Config Service supports scenarios that requires the ability to persist channel specific data. Next, we are going to demonstrate how to integrate a backend service, and show the questions the viewers submitted to the broadcaster live! Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Create an Extension | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/create-extension/#) Extension 101 tutorial series ============================= Create an Extension =================== Let’s get started by setting up the Extension up via the Extensions Console. ### Two-factor Authentication 1. If you do not already have a Twitch account, go to [twitch.tv](https://twitch.tv/) in a browser and create an account using the **Sign Up** button in the top right of the page. 2. You will need to enable two-factor authentication on your account to build Extensions, so please visit your [Security and Privacy settings](https://www.twitch.tv/settings/security) to confirm it is enabled or activate it. ### Creating the Extension in the Console 1. Go to the [Extensions Developer Console](https://dev.twitch.tv/console/extensions) . From this console, you can start the process of creating a new Extension, view and clone your Extensions, and manage specific versions of your Extension(s). Login with your Twitch ID. You should see a page like this: ![Extensions developer console](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-2.png) 2. Click the **Create an Extension** button on the right side of the page. 3. Fill in the **Name Your Extension** section with any name you want, and then click **Continue**. ![Start an extension](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-3.png) 4. On this versions page, be sure to fill out respective fields * **Type of Extension** — (_Required_) Select **Panel**. * **Version Number** — (_Required_) Leave this as 0.0.1. * **Summary** — (_Optional_) This will be viewable by broadcasters and viewers. It should be 1-2 brief sentences describing what your Extension does. To provide more detail, use the Description. * **Description** — (_Optional_) More detail than the Summary about the functions of your Extension. * **Author Name** — (_Optional_) The full name of the Extension author or organization that will receive credit on the Extensions manager. * **Author Email** — (_Optional_) Contact information for the Extension creator. This is used to contact the developer with information about the Extension’s life cycle (e.g., reject/accept notifications). Twitch will never reveal this email to anyone on the site. If you provide this information, you’ll get a verification email soon after creating the Extension version. Be sure to check your email, as you need to verify ownership of the author email address. * **Support Email** — (_Optional_) Public contact information for support-related queries from broadcasters. 5. Click **Create Extension Version**. You will then see the Status page of the Extension Manager. This page essentially shows the current status (Local Test) of the Extension in the _Extension Life Cycle_, and also provides you with next steps to move the Extension through the life cycle. You should see the following page: ![Create extension version](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-4.png) ### Concept: Extension Life Cycle The Extension Life Cycle details the various development stages of an Extension. You can [find more information](https://dev.twitch.tv/docs/extensions/life-cycle/) about each of these stages in our documentation. ![]()![Extension lifecycle](https://dev.twitch.tv/docs/assets/uploads/extension-tutorial-5.png) Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Twitch Extensions Tutorials | Twitch Developers [Contents](https://dev.twitch.tv/docs/tutorials/extension-101-tutorial-series/introduction/#) Extension 101 tutorial series ============================= Twitch Extensions Tutorials: Introduction ========================================= Prerequisites ------------- Requires knowledge of: * HTML * CSS * JS Objectives ---------- * Step by step tutorials for how to build a Twitch Extension from start to finish. * Learn core concepts of Extensions via hands-on development and code walkthroughs. * At the end of these tutorials, you will have developed your first production-ready Extension! What are Extensions? -------------------- Extensions are web apps that are embedded as HTML iframes into a broadcaster’s channel. Extensions live in the broadcaster’s creator dashboard and provide more engaging, interactive experiences for both the broadcaster and the viewers. In this tutorial series, we will build a panel Extension. You can find more information about each type of Extension [here](https://dev.twitch.tv/docs/extensions/) . What are we going to build? --------------------------- Through these tutorials, we will be building an Extension that implements the “Would You Rather..?” conversation game. For those of you unfamiliar with that game, essentially the idea is that viewers will have the ability to ask questions that begin with “Would you rather…?” and select two scenarios for the broadcaster to choose from. The more similar the two choices are, the harder the dilemma. On stream, the broadcaster must choose one of the scenarios they would rather do. This Extension thus helps create a more engaging experience specifically for chat-oriented streams. While this is the basic idea of the Extension we are going to build, we will also be adding other features to emphasize how Extensions can provide a better, more engaging experience for both the broadcaster and the viewers. Awesome! Now that we know what we are going to accomplish in this tutorial, let’s start building. Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Insights & Analytics | Twitch Developers [Contents](https://dev.twitch.tv/docs/insights/#) Insights & Analytics ==================== Introduction ------------ Twitch Insights provides game and extension developers with analytics data to help developers make data-driven decisions about future development. As a developer, you can use this data to enhance the experience of broadcasters and viewers and optimize how they engage with your games and extensions on Twitch Once a data field is added to a report, it will not be deleted in future versions of the report. New data fields may be added in new versions of the report, anywhere in the sequence of fields (that is, not necessarily at the end of the CSV). ### Counting Device IDs As explained below, some unique data fields (for example, Unique Viewers) are collected based on device IDs. At a given moment, a device ID is assigned to a single hardware device. For example, if someone loads an extension or watches a game on 2 devices, that involves 2 device IDs and counts as 2 Unique Viewers. Web browsers store device IDs using cookies. The half-life of a cookie seems to be about 14 days, even if you ask the browser to store the cookie forever. So, on any given day, we can assume that a browser always provides the same device ID for a given device. But over a month, most browsers provide at least 2 device IDs for the same device, one ID initially and another after clearing and refreshing the cookie. This applies primarily to the web platform. Mobile apps and console platforms have different storage regimes, and device IDs are much more durable in those environments. How does this affect Insights data collection? On a particular day, this has very little impact, as we can expect 1 device to have only 1 device ID. Over time, though, 1 device will have multiple device IDs. As a result, there is a significant impact on Insights data fields that count device IDs over long periods of time (30 days or more). For these fields, the number of uniques is likely to be much higher than the number you get by extrapolating from shorter time periods. The major impact is on the **Last 30 Days** data fields, especially if your game or extension is used primarily from web browsers. For example, for Extensions that run only in browsers, the number of Unique Viewers Last 30 Days will be much higher than the number of Unique Viewers times 30. Extension Developer Analytics ----------------------------- To download this data:     1. On your Twitch developer console, go to the **Extensions tab**.     2. On the line for the extension for which you want data, click **Download CSV**. Data is provided as one CSV file per released extension. The file contains one row of data per day, from January 31, 2018 until the current day. Fields related to minimization are provided only as of June 22, 2018 (as noted in the following table). The file contains all data fields in the latest version of Extension analytics. Data starts being collected after the Extension is installed and viewed, subject to a one-day delay. For example, we start calculating the data for January 12 on January 14 at UTC 1:00. Typically the calculations complete within 1 hour. The report is uploaded as soon as the calculations are done. Also see the [Get Extension Analytics](https://dev.twitch.tv/docs/api/reference/#get-extension-analytics) endpoint in the Twitch API. The endpoint returns a URL that you can use to download the CSV files. The endpoint can be used to return any report type of Extension analytics data.   ### Data Fields (Overview Reports) All counts are for the corresponding day in the CSV file. If there is no data for a day, either that day is missing from the report or it is in the report with all data fields having a value of 0 (that is, no activity). Except where noted, all metrics count events from desktop browsers, mobile browsers, and the Twitch app. | Column Name | Description | | --- | --- | | Date | UTC date for the data in each row. For example, data in the row for 2018-08-01 (August 1, 2018) covers the period from 2018-08-01T00:00:00Z to 2018-08-01T23:59:59Z. | | Extension  Name | Name of the extension. Since the name can change and may take a few days to update internally, the Extension Client ID (which does not change) is preferable as an identifier. | | Extension Client ID | Alphanumeric identifier for the extension. | | Extension Details Page Visits | Number of visitor page loads of the extension’s Details page (https://www.twitch.tv/ext/. Reloading the page counts as multiple visits. | | Unique Extension Details Page Visits | Number of unique visitor page loads of the extension’s Details page. Specifically this measures unique device IDs (see Counting Device IDs). | | Installs | Number of install events of the extension. | | Uninstalls | Number of uninstall events of the extension. | | Activations | Number of activation events of the extension. | | Unique Active Channels | Number of unique broadcaster channel IDs that had at least one render while the extension is active. This can be interpreted as the number of unique broadcasters that used your extension on their channel and received at least one viewer. If a broadcaster streams with your extension but the extension has no viewers, that is not captured here. | | Unique Active Channels Last 7 Days | Number of Unique Active Channels in the past 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. | | Unique Active Channels Last 30 Days | Number of Unique Active Channels in the past 30 days. For example, if this metric is provided on July 31, it would cover July 2-31. | | Unique Identity Links | Number of unique user IDs that granted the extension access to their Twitch user IDs. Users can grant and revoke access multiple times. On any given day, only the first grant is counted. | | Unique Identity Unlinks | Number of unique users who revoked access to their Twitch user IDs. Users can grant and revoke access multiple times; on any given day, only the first revoke is counted. | | Renders | Number of user page loads, watching channels with the extension. A page refresh counts as a render. | | Unique Renderers | Number of unique users with a “renders” event. Specifically, this measures unique device IDs (see Counting Device IDs). | | Unique Renderers Last 7 Days | Number of Unique Renderers in the past 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. | | Unique Renderers Last 30 Days | Number of Unique Renderers in the past 30 days. For example, if this metric is provided on July 31, it would cover July 2-31.Note this may be unexpectedly high; see Counting Device IDs. | | Views | Number of times that 75% or more of the extension iframe was visible in any viewer’s browser. For panel extensions, this may be less than the number of renders, if the extension is rendered but the viewer does not scroll down to view it. Scrolling up and down multiple times does not count as multiple views. | | Unique Viewers | Number of different viewers who watched this extension on Twitch, based on the Views definition above. Specifically, this measures unique device IDs (see Counting Device IDs).

If your extension is shown by a given device ID in multiple ways (panel, video overlay, video component), that counts as 2 Unique Viewers (1 for the panel and 1 for the video overlay and/or component). | | Unique Viewers Last 7 Days | Number of Unique Viewers in the past 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. | | Unique Viewers Last 30 Days | Number of Unique Viewers in the past 30 days. For example, if this metric is provided on July 31, it would cover July 2-31. Note this may be unexpectedly high; see Counting Device IDs. | | Mouseenters | Number of times a mouse pointer enters (hovers over) the extension. This counts only desktop browser events. | | Unique Mouseenters | Number of unique Mouseenter events. Specifically, this measures unique device IDs (see Counting Device IDs). This counts only desktop browser events. | | Unique Mouseenters Last 7 Days | Number of Unique Mouseenters in the past 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. | | Unique Mouseenters Last 30 Days | Number of Unique Mouseenters in the past 30 days. For example, if this metric is provided on July 31, it would cover July 2-31. | | Mouseenters Per Viewer | Average number of Mouseenter events per viewer. Defined as Mouseenters / Unique Viewers | | Mouseenter Rate | Indicates the ratio of Unique Viewers who also have mouseenter events. Defined as Unique Mouseenters / Unique Viewers. | | Clicks\* | Number of click events in the extension iframe. | | Unique Interactors\* | Number of unique click events in the extension iframe. Specifically, this measures unique device IDs (see Counting Device IDs). | | Unique Interactors\* Last 7 Days | Number of Unique Interactors in the past 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. | | Unique Interactors\* Last 30 Days | Number of Unique Interactors in the past 30 days. For example, if this metric is provided on July 31, it would cover July 2-31. Note this may be unexpectedly high; see Counting Device IDs. | | Clicks Per Interactor\* | Average number of click events per interactor. Defined as: Clicks / Unique Interactors. | | Interaction Rate\* | Indicates the ratio of interactors to viewers. Defined as: Unique Interactors / Unique Viewers. | | Minimizations | Number of times a viewer minimizes (hides) the extension. This field is provided from June 22, 2018 on. | | Unique Minimizers | Number of times a viewer minimizes (hides) the extension. This field is provided from June 22, 2018 on. | | Minimization Rate | Indicates how often viewers minimize the extension. Defined as Unique Minimizers / Unique Viewers. This field is provided from June 22, 2018 on. | | Unminimizations | Number of times a viewer unhides the extension after it was minimized. Unminimizations can happen for extensions that were minimized in previous days. This field is provided from June 22, 2018 on. | | Unique Unminimizers | Number of Unique Viewers that unhide the extension after it was minimized. This field is provided from June 22, 2018 on. | | Unminimization Rate | Indicates how often viewers unhide the extension after it was minimized. Defined as Unique Unminimizers / Unique Viewers. This field is provided from June 22, 2018 on. | | Bits Revenue USD | (Bits-enabled Extensions only) Revenue share earned by the developer from Bits transactions (in US dollars): this is Bits \* 20% share \* $.01/bit conversion rate. For more information about Bits in Extensions, see the Extensions Monetization Guide. | | Bits Used | (Bits-enabled Extensions only) Number of Bits used. | | Bits Transactions | (Bits-enabled Extensions only) Number of Bits transactions. | | Bits Per Transaction | (Bits-enabled Extensions only) Average number of Bits per transaction. Defined as Bits Used / Bits Transactions. | | Unique Bits Users | (Bits-enabled Extensions only) Number of unique users who used Bits in the extension. This is measured by user IDs, not device IDs. | | Unique Bits Users Last 7 Days | (Bits-enabled Extensions only) Number of unique users who used Bits in the extension in the last 7 days. For example, if this metric is provided on July 31, it would cover July 25-31. This is measured by user IDs, not device IDs. | | Unique Bits Users Last 30 Days | (Bits-enabled Extensions only) Number of unique users who used Bits in the extension in the last 30 days. For example, if this metric is provided on July 31, it would cover July 2-31. This is measured by user IDs, not device IDs. | | Bits Used Per User | (Bits-enabled Extensions only) Average number of Bits per user. Defined as Bits Used / Unique Bits Users. | **NOTE:** Click events will include false positives, as viewers often click into the player to reveal the Extension or other player controls. This is especially true for Overlay Extensions. You are allowed to implement Google Analytics to further instrument your Extension. ### Partial Sample File For brevity, in this sample file we show data for only 10 days. Date,Extension Name,Extension Client ID,Extension Details Page Visits,Unique Extension Details Page Visits,Installs,Uninstalls,Activations,Unique Active Channels,Unique Active Channels Last 7 Days,Unique Active Channels Last 30 Days,Unique Identity Links,Unique Identity Unlinks,Renders,Unique Renderers,Unique Renderers Last 7 Days,Unique Renderers Last 30 Days,Views,Unique Viewers,Unique Viewers Last 7 Days,Unique Viewers Last 30 Days,Mouseenters,Unique Mouseenters,Unique Mouseenters Last 7 Days,Unique Mouseenters Last 30 Days,Mouseenters Per Viewer,Mouseenter Rate,Clicks,Unique Interactors,Unique Interactors Last 7 Days,Unique Interactors Last 30 Days,Clicks Per Interactor,Interaction Rate,Minimizations,Unique Minimizers,Minimization Rate,Unminimizations,Unique Unminimizers,Unminimization Rate,Bits Revenue USD,Bits Used,Bits Transactions,Bits Per Transaction,Unique Bits Users,Unique Bits Users Last 7 Days,Unique Bits Users Last 30 Days,Bits Used Per User 5/31/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz51,42,13,18,5,9,164,462,756,51,8,23954,13084,80730,168982,23954,13084,80730,168982,51796,7564,40166,79960,3.9587,0.5781,6512,1365,6848,15464,4.7707,0.1043,410,369,0.0282,12,10,0.0009,1.08,540,32,16.875,30,132,417,18 6/1/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz52,30,11,14,5,5,124,434,714,37,5,17286,9308,79066,163978,17286,9308,79066,163978,40010,5462,39166,77026,4.2985,0.5868,4412,1182,6926,14972,3.7327,0.127,292,273,0.0293,10,8,0.0011,0.87,435,38,11.4474,15,117,402,29 6/2/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz53,21,8,14,5,5,128,440,694,15,2,7930,5220,84282,163124,7930,5220,84282,163124,10516,2208,42176,75940,2.0146,0.423,1700,411,7636,14716,4.1363,0.0787,60,51,0.0098,4,4,0.0008,0.06,30,4,7.5,6,117,396,5 6/3/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz54,30,11,11,6,5,132,438,678,27,2,28412,21270,87358,165508,28412,21270,87358,165508,33464,7638,44426,76154,1.5733,0.3591,5356,1290,8760,14664,4.1519,0.0606,250,312,0.0147,4,4,0.0002,0.69,345,8,43.125,9,129,405,38.3333 6/4/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz55,31,10,16,4,8,184,442,654,51,6.5,31360,18238,80720,152212,31360,18238,80720,152212,62222,9678,44510,72208,3.4117,0.5307,7754,1986,10142,14124,3.9043,0.1089,466,477,0.0262,18,18,0.001,1.14,570,36,15.8333,33,162,408,17.2727 6/5/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz56,29,11,19,4,7,130,412,616,31,3.5,25562,14628,75620,147288,25562,14628,75620,147288,53390,7916,41896,69244,3.6498,0.5412,6670,1620,9414,13428,4.1173,0.1107,410,405,0.0277,2,2,0.0001,1.08,540,12,45,9,153,405,60 6/6/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz57,35,12,15,4,7,162,388,592,39,5,29130,18574,72038,144320,29130,18574,72038,144320,59696,10256,39912,66560,3.214,0.5522,7512,1884,8876,12836,3.9873,0.1014,458,507,0.0273,26,16,0.0014,1.32,660,58,11.3793,30,165,420,22 6/7/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz58,26,8,12,3,5,124,348,554,31,5,24184,14830,62452,138678,24184,14830,62452,138678,50960,7926,34506,61998,3.4363,0.5345,8434,1860,8056,12108,4.5344,0.1254,552,504,0.034,30,18,0.002,0.72,360,10,36,12,144,411,30 6/8/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz59,20,7,12,4,6,120,330,542,43,6.5,19732,12308,58580,133930,19732,12308,58580,133930,39890,6588,31670,59152,3.241,0.5353,7256,1560,7294,11356,4.6513,0.1267,436,468,0.038,14,14,0.0011,0.81,405,28,14.4643,18,150,411,22.5 6/9/2018,test extension,hs5z3fh5dxhshfhazhk4hq38g9hz60,24,8,12,3,7,134,324,538,41,6.5,30622,17092,56124,129834,30622,17092,56124,129834,63590,9626,29608,56998,3.7205,0.5632,11176,2493,6692,10768,4.483,0.1459,726,624,0.0365,16,14,0.0009,1.89,945,14,67.5,15,141,429,63 Game Developer Analytics ------------------------ Game Developer Analytics provides a full spectrum of your game’s performance on Twitch, including aggregate hours watched and number of concurrent streamers. It is available only to users who have registered an organization and claimed their game via the Twitch Developer Console. See [Organization Management](https://dev.twitch.tv/docs/companies/) for more information. To download this data: 1. On your Twitch developer console, navigate to your organization console using the top navigation drop down. Then, click on the **Games** tab. 2. Under the game for which you want data, click **Export Daily CSV**. If the button does not appear, the game does not meet the minutes-watched threshold for report generation. A report is available only if the game was broadcast for at least 300 minutes (5 hours) over the time period covered by the report. Data is provided as one CSV file per game. The file contains one row of data per day, for the past 365 days. The file contains all data fields in the latest version of game analytics. Data starts being collected after the game is broadcast and viewed, subject to a one-day delay. For example, we start calculating the data for January 12 on January 14 at UTC 0:00. Typically the calculations complete within 4 hours. The report is uploaded as soon as the calculations are done. Also see the [Get Game Analytics](https://dev.twitch.tv/docs/api/reference/#get-game-analytics) endpoint in the Twitch API. The endpoint returns a URL that you can use to download the CSV files. ### Terminology | Term | Definition | | --- | --- | | Live | Live broadcast or premiere. | | Not-Live | Rerun or VOD. | | Rerun | Subsequent (not live) streaming of any past broadcast. | | VOD | Video on Demand. VODs are asynchronous pieces of content that viewers can watch whenever they like. A VOD may be a past broadcast, a highlight of a past broadcast, an uploaded video, or a clip (short, non-live streams created by viewers).

_Clips are not included in the developer analytics data described in this document._ Clips data is available via the [Get Videos](https://dev.twitch.tv/docs/api/reference#get-videos)
API endpoint. | | Vodcast | An old term, which at Twitch comprises what are now known as premieres and reruns. | ### Data Fields (Overview Reports) Note that all counts are for the corresponding day in the CSV file. If there is no data for a day, either that day is missing from the report or it is in the report with all data fields having a value of 0 (i.e., no activity). | Column Name | Description | | --- | --- | | Date | UTC date for the data in each row. For example, data in the row for 2018-08-01 (August 1, 2018) covers the period from 2018-08-01T00:00:00Z to 2018-08-01T23:59:59Z. | | Game | Name of the game. | | Game ID | ID of the game. | | Total Views | Sum of Live Views + Not-Live Views. | | Live Views | Number of times any stream of this game was viewed on Twitch, live. This includes live streams and Premieres. If someone watches a game 5 separate times in a day, that counts as 5 views here. | | Not-Live Views | Number of times any stream of this game was viewed on Twitch, not live. This includes Reruns and VODs. | | Total Unique Viewers | Number of different viewers who watched this game on Twitch live or not-live. Specifically this measures unique device IDs (see [Counting Device IDs](https://dev.twitch.tv/docs/insights/#counting-device-ids)
). | | Live Unique Viewers | Number of Unique Viewers who watched this game live on Twitch. Specifically this measures unique device IDs (see [Counting Device IDs](https://dev.twitch.tv/docs/insights/#counting-device-ids)
). | | Not-Live Unique Viewers | Number of Unique Viewers who watched this game not-live on Twitch. As above, this measures unique device IDs (see [Counting Device IDs)](https://dev.twitch.tv/docs/insights/#counting-device-ids)
. | | Average Concurrent Viewers | Average number of concurrent CCUs of this game, across Twitch. | | Peak Concurrent Viewers | Peak number of concurrent viewers of this game, across Twitch. | | Peak Time - Concurrent Viewers | UTC timestamp that corresponds to Peak Concurrent Viewers. | | Total Hours Watched | Sum of Live Hours Watched + Not-Live Hours Watched. | | Live Hours Watched | Number of hours this game was watched live on Twitch. | | Not-Live Hours Watched | Number of hours this game was watched not-live on Twitch. | | Unique Broadcasters | Number of unique broadcasters who live-streamed this game on Twitch. Specifically, this measures unique channel IDs. | | Hours Broadcast | Number of hours of this game that were broadcast on Twitch live. | | Average Concurrent Broadcasters | Average number of broadcasters simultaneously streaming this game. | | Peak Concurrent Broadcasters | Peak number of broadcasters simultaneously streaming this game. | | Peak Time - Concurrent Broadcasters | UTC timestamp that corresponds to Peak Concurrent Broadcasters. | | Live Unique Chat Participants | Number of live unique chat participants for this game, across Twitch. | | Total Live Chat Messages Sent | Number of chat messages for this game, across Twitch. | | Unique Active Channels with Extensions | Number of unique broadcaster channel IDs streaming your game, which had at least one render while an extension was active. This can be interpreted as the number of unique broadcasters that used an extension on their channel and received at least one render while streaming your game. If a broadcaster streams with an extension but the extension does not render for any viewers, that is not captured here. | | Unique Active Extensions | Number of unique extensions related to Unique Active Channels with Extensions. Note that while the report is game-specific, some of the extensions may not be specific to the game. | | Clips Created | Number of Clips created from this game. | | Clip Views | Number of times any Clips of this game were watched. | | Top Clip URL | URL of the most-watched clip of this game. | | Top Clip URL Embed | URL of the most-watched clip of this game, which you can embed in your site or blog. This is the same clip as for Top Clip URL, but the URL here contains additional parameters relevant to embedding clips (see [Non-Interactive Frames for Clips](https://dev.twitch.tv/docs/embed/video-and-clips/#non-interactive-iframes-for-clips)
). (Note: This URL contains a `tt_medium`parameter. Ignore this; it is used only internally by Twitch.) | ### Sample File (Partial) For brevity, in this sample file we show data for only 10 days. Date,Game,Game ID,Total Views,Live Views,Not-Live Views,Total Unique Viewers,Live Unique Viewers,Not-Live Unique Viewers,Average Concurrent Viewers,Peak Concurrent Viewers,Peak Time - Concurrent Viewers,Total Hours Watched,Live Hours Watched,Not-Live Hours Watched,Unique Broadcasters,Hours Broadcast,Average Concurrent Broadcasters,Peak Concurrent Broadcasters,Peak Time - Concurrent Broadcasters,Live Unique Chat Participants,Total Live Chat Messages Sent,Unique Active Channels with Extensions,Unique Active Extensions,Clips Created,Clip Views,Top Clip URL,Top Clip URL Embed 1/1/18,TestGame,123456,30000,10000,20000,25893,19990,25550,12345,5103,6:41 AM,23234.09,1000.01,2000.04,100,213.18,23,12,12:00 AM,1675,10000,54,20,149,1000,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/2/18,TestGame,123456,30001,10001,20000,24239,19991,25551,14932,6018,12:00 AM,21093.45,1000.02,2012.34,92,199.34,45,21,12:00 AM,2345,10001,79,54,200,2000,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/3/18,TestGame,123456,30002,10002,20000,25552,19992,25552,13467,8012,12:00 AM,23234.09,1000.03,2024.64,40,220.09,10,34,12:00 AM,1321,10010,23,19,145,2001,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/4/18,TestGame,123456,30003,10003,20000,26789,19993,25553,12345,4521,12:00 AM,21093.45,1000.04,2036.94,55,79.08,23,12,12:00 AM,1234,10090,234,167,233,2010,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/5/18,TestGame,123456,30004,10004,20000,28908,19994,25554,14932,5103,12:00 AM,23234.09,1000.05,2049.24,65,213.18,45,21,12:00 AM,990,10000,54,20,50,2098,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/6/18,TestGame,123456,30005,10005,20000,28992,19995,25555,13467,6018,12:00 AM,21093.45,1000.06,2061.54,110,199.34,10,34,12:00 AM,1675,10001,79,54,149,1999,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/7/18,TestGame,123456,30006,10006,20000,24239,19996,25556,12345,8012,12:00 AM,23234.09,1000.07,2073.84,89,220.09,23,12,12:00 AM,2345,10010,23,19,200,1000,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/8/18,TestGame,123456,30007,10007,20000,25552,19997,25557,14932,5103,12:00 AM,21093.45,1000.08,2086.14,77,213.18,45,21,12:00 AM,1321,10090,234,167,145,2000,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/9/18,TestGame,123456,30008,10008,20000,26789,19998,25558,13467,6018,12:00 AM,23234.09,1000.09,2098.44,100,199.34,10,34,12:00 AM,1234,10000,54,40,233,2001,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights 1/10/18,TestGame,123456,30009,10009,20000,28908,19999,25559,12345,8012,12:00 AM,21093.45,1000.1,2110.74,130,220.09,21,12,12:00 AM,990,10001,79,56,50,2010,https://clips.twitch.tv/dummyvideo?tt_medium=dx_insights,https://clips.twitch.tv/embed?clip=dummyvideodonotclick&tt_medium=dx_insights ... Provide feedback for this page [Docs](https://dev.twitch.tv/docs) [Support](https://dev.twitch.tv/support) [Showcase](https://dev.twitch.tv/showcase) [Blog](https://blog.twitch.tv/en/tags/developers/) [](https://twitter.com/twitchdev) [](https://github.com/twitchdev) [](https://blog.twitch.tv/en/tags/developers/) [](https://twitch.tv/twitchdev) --- # Mobile Deep Links | Twitch Developers [Contents](https://dev.twitch.tv/docs/mobile-deeplinks/#) Mobile Deep Links ================= Introduction ------------ Deep links allow third party mobile apps and mobile web sites to bring users to a specific place within a Twitch app. This guide explains how to check whether the Twitch App is installed and describes deep link formats. Deep links are important because they allow tighter integration with Twitch on mobile apps. For example, an app that helps a broadcaster manage their channel could link directly to the user’s dashboard within the Twitch App (as opposed to just launching the app and leaving the user on the “Following” tab). You can find more information about deep links [here](https://en.wikipedia.org/wiki/Mobile_deep_linking) . For support, visit the [Twitch Developer Forums](https://discuss.dev.twitch.tv/) . Checking Whether the Twitch App is Installed -------------------------------------------- You can check whether the Twitch App is already installed on a mobile device as follows: ### On iOS Objective C NSURL *twitchURL = [NSURL URLWithString:@"twitch://open"]; if ([[UIApplication sharedApplication] canOpenURL:twitchURL]) { // The Twitch app is installed, do whatever logic you need, and call -openURL: } else { // The Twitch app is not installed. Prompt the user to install it! } ### On iOS Swift let twitchURL = NSURL(string: "twitch://open") if (UIApplication.sharedApplication().canOpenURL(twitchURL!)) { // The Twitch app is installed, do whatever logic you need, and call -openURL: } else { // The Twitch app is not installed. Prompt the user to install it! } Note: On both iOS platforms, you also must change your app’s `Info.plist` file to declare that your app is allowed to query the twitch scheme. See the [Apple documentation](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl) for detailed information.  ### On Android // Where "packagename" is the package name of the Twitch app: private boolean isPackageInstalled(String packagename, Context context) { PackageManager pm = context.getPackageManager(); try { pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES); return true; } catch (NameNotFoundException e) { return false; } } Deep Link Formats ----------------- To launch the Twitch App, use `twitch://open`. | To launch the Twitch App and… | Use this URL | | --- | --- | | Navigate to a specific channel | `twitch://stream/`
– OR –
`twitch://open?stream=` | | Open a specific game directory | `twitch://game/`
– OR –
`twitch://open?game=` | | Open a specific VOD | `twitch://video/