EventSub
Introduction
Long-term our plan is to provide a single product, EventSub, that allows developers to subscribe to events and receive notifications over many different transports: webhooks, websockets, etc..
All events and payloads have been designed to be transport agnostic. Choosing webhooks over websockets (or vice-versa) won’t change the events available to you or how those events behave. If a new event type is added to EventSub, it is added to all transports simultaneously.
Subscriptions
Subscriptions enable your application to listen for events that happen on Twitch. When an event occurs for one of your subscriptions, Twitch sends you a notification. For example, you might choose to receive a notification when:
- A stream has gone online.
- A broadcaster has a new follower.
- A broadcaster has a new subscriber.
- A user has cheered in a channel.
- A user has redeemed channel points.
For a complete list of the available subscription types and their requirements, see EventSub Subscription Types.
Authorization
You must include an app access token in all API requests. You do not need to include a user access token, even for subscriptions that require user authorization. This is because Twitch checks authorization throughout the lifetime of your subscription by calling Twitch’s internal authorization systems directly.
Secret
When creating a subscription, you must specify a secret for purposes of verification, described below in “Verify a signature”.
The secret is a string between 10 and 100 characters that your application will define and send to Twitch in the subscription creation process. As a result, this secret should not be your Client Secret or Extension secret.
Create a subscription
To create a subscription:
-
Call the
POST https://api.twitch.tv/helix/eventsub/subscriptions
endpoint with the subscription details in the request body. The URL provided in thecallback
field MUST use HTTPS and port 443. For local development consider using a product like ngrok to easily create an HTTPS endpoint.POST https://api.twitch.tv/helix/eventsub/subscriptions ---- Client-ID: crq72vsaoijkc83xx42hz6i37 Authorization: Bearer C0BIYxs4JvnBWqvAmBvjfFc Content-Type: application/json ---- { "type": "channel.follow", "version": "1", "condition": { "broadcaster_user_id": "12826" }, "transport": { "method": "webhook", "callback": "https://example.com/webhooks/callback", "secret": "s3cRe7" } }
-
Twitch responds indicating the subscription request’s status is
webhook_callback_verification_pending
. This is because Twitch needs to verify that you own thecallback
you specified.{ "data": [{ "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", "status": "webhook_callback_verification_pending", "type": "channel.follow", "version": "1", "condition": { "broadcaster_user_id": "12826" }, "transport": { "method": "webhook", "callback": "https://example.com/webhooks/callback" }, "created_at": "2019-11-16T10:11:12.123Z" }], "total": 1, "limit": 10000 }
-
Twitch sends a callback verification request to your server using the callback URL provided in your request.
POST https://example.com/webhooks/callback ---- Twitch-Eventsub-Message-Id: e76c6bd4-55c9-4987-8304-da1588d8988b Twitch-Eventsub-Message-Retry: 0 Twitch-Eventsub-Message-Type: webhook_callback_verification Twitch-Eventsub-Message-Signature: sha256=f56bf6ce06a1adf46fa27831d7d15d Twitch-Eventsub-Message-Timestamp: 2019-11-16T10:11:12.123Z Twitch-Eventsub-Subscription-Type: channel.follow Twitch-Eventsub-Subscription-Version: 1 ---- { "challenge": "pogchamp-kappa-360noscope-vohiyo", "subscription": { "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", "status": "webhook_callback_verification_pending", "type": "channel.follow", "version": "1", "condition": { "broadcaster_user_id": "12826" }, "transport": { "method": "webhook", "callback": "https://example.com/webhooks/callback" }, "created_at": "2019-11-16T10:11:12.123Z" } }
- Verify the
Twitch-Eventsub-Message-Signature
header in the callback verification request to make sure the payload came from Twitch. See Verify a signature for more details. -
Respond to the callback verification request by returning the value of
challenge
. Your response must be a raw string. If your server is using a web framework, be careful that your web framework isn’t modifying the response in an incompatible way. For example, some web frameworks default to converting responses into JSON objects.pogchamp-kappa-360noscope-vohiyo
- Your subscription is now active!
Receive a notification
When an event triggers your subscription, Twitch will send a notification to your callback.
To test receiving a notification:
- Create a subscription for when channel
12826
receives a new follower. - Go to Twitch and follow that channel.
-
You’ll receive a
notification
request to your subscription’s callback:POST https://example.com/webhooks/callback ---- Twitch-Eventsub-Message-Id: befa7b53-d79d-478f-86b9-120f112b044e Twitch-Eventsub-Message-Retry: 0 Twitch-Eventsub-Message-Type: notification Twitch-Eventsub-Message-Signature: sha256=d66824350041dce130e3478f5a7 Twitch-Eventsub-Message-Timestamp: 2019-11-16T10:11:12.123Z Twitch-Eventsub-Subscription-Type: channel.follow Twitch-Eventsub-Subscription-Version: 1 ---- { "subscription": { "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4", "status": "enabled", "type": "channel.follow", "version": "1", "condition": { "broadcaster_user_id": "12826" }, "transport": { "method": "webhook", "callback": "https://example.com/webhooks/callback" }, "created_at": "2019-11-16T10:11:12.123Z" }, "event": { "user_id": "1337", "user_login": "awesome_user", "user_name": "Awesome_User", "broadcaster_user_id": "12826", "broadcaster_user_login": "twitch", "broadcaster_user_name": "Twitch" } }
- Verify the request signature to make sure it came from Twitch.
- Acknowledge the notification by returning a 2XX status code.
It is expected that you’ll respond to the notification
request within a few seconds. If your server takes too long to respond, the request will time out. If your server can’t process a notification
request quickly enough, consider writing the payload to temporary storage, responding with a 2XX, then processing the notification
afterwards.
Twitch’s subscriptions are designed as an at-least-once system. This means that if Twitch is ever unsure whether you received a notification, it’ll retry. Under some circumstances this means you may receive a notification twice. If this is problematic for your use case, review the handling duplicates section for information on how to handle this reliably.
List your subscriptions
To view your current subscriptions, call the GET https://api.twitch.tv/helix/eventsub/subscriptions
endpoint. This endpoint will return a paginated list of all your subscriptions, including subscriptions that are disabled. This API endpoint is a great debugging tool if you aren’t receiving notifications for a subscription you believe should exist.
Request
GET https://api.twitch.tv/helix/eventsub/subscriptions
----
Client-ID: crq72vsaoijkc83xx42hz6i37
Authorization: Bearer deadbeefdeadbeef
Response
{
"data": [
{
"id": "26b1c993-bfcf-44d9-b876-379dacafe75a",
"status": "enabled",
"type": "streams.online",
"version": "1",
"condition": {
"broadcaster_user_id": "1234"
},
"created_at": "2020-11-10T20:08:33Z",
"transport": {
"method": "webhook",
"callback": "https://this-is-a-callback.com"
}
},
{
"id": "35016908-41ff-33ce-7879-61b8dfc2ee16",
"status": "webhook_callback_verification_pending",
"type": "users.update",
"version": "1",
"condition": {
"user_id": "1234"
},
"created_at": "2020-11-10T20:31:52Z",
"transport": {
"method": "webhook",
"callback": "https://this-is-a-callback.com"
}
}
],
"total": 2,
"limit": 10000,
"pagination": {}
}
Note that the total
field contains an approximate number of subscriptions. After creating or deleting a subscription, it may take a few seconds for total
to update.
You can also filter by subscriptions status by including the status
query parameter in the request. For example, if you want only enabled subscriptions call GET https://api.twitch.tv/helix/eventsub/subscriptions?status=enabled
.
All possible statuses are:
enabled
: designates that the subscription is in an operable state and is valid.webhook_callback_verification_pending
: webhook is pending verification of thecallback
specified in the subscription creation request.webhook_callback_verification_failed
: webhook failed verification of thecallback
specified in the subscription creation request.notification_failures_exceeded
: notification delivery failure rate was too high.authorization_revoked
: authorization for user(s) in thecondition
was revoked.user_removed
: a user in thecondition
of the subscription was removed.
Delete a subscription
To delete a subscription call the DELETE https://api.twitch.tv/helix/eventsub/subscriptions
endpoint and specify the id
for the subscription to delete.
DELETE https://api.twitch.tv/helix/eventsub/subscriptions?id=f1c2a387-161a-49f9-a165-0f21d7a4e1c4
----
Client-ID: crq72vsaoijkc83xx42hz6i37
Authorization: Bearer deadbeefdeadbeef
Verify a signature
Whenever you receive a request from Twitch, a signature will be included in the Twitch-Eventsub-Message-Signature
header. To verify that a request is authentic you must verify its signature.
The signature uses HMAC-SHA256
. The HMAC key is your subscription’s secret
. The HMAC message is the concatenation of the Twitch-Eventsub-Message-Id
header, the Twitch-Eventsub-Message-Timestamp
header, and the raw bytes of the request body.
If the signature in the Twitch-Eventsub-Message-Signature
doesn’t match the signature you computed, return a 4XX status code.
Pseudocode
hmac_message = headers['Twitch-Eventsub-Message-Id'] + headers['Twitch-Eventsub-Message-Timestamp'] + request.body
signature = hmac_sha256(webhook_secret, hmac_message)
expected_signature_header = 'sha256=' + signature.hex()
if headers['Twitch-Eventsub-Message-Signature'] != expected_signature_header:
return 403
Note: Request header names are case-insensitive. Some languages, like JavaScript, convert header names to lowercase regardless of how they were sent. If your language does this, use .toLowerCase()
before checking headers.
If your use case requires resiliency against replay attacks, do the following:
- Make sure the value of the
Twitch-Eventsub-Message-Timestamp
header isn’t older than 10 minutes. - Make sure the value of the
Twitch-Eventsub-Message-Id
header hasn’t been seen before.
Handling duplicates
Twitch’s subscriptions are designed as an at-least-once system. This means that if Twitch is ever unsure whether you received a message, it’ll retry. Under some circumstances this means you may receive a message twice.
Every message includes a Twitch-Eventsub-Message-Id
header. If a message is retried, the value of the Twitch-Eventsub-Message-Id
header will stay the same.
If you need to deduplicate messages, keep track of the values of Twitch-Eventsub-Message-Id
you’ve seen. If you receive a message that contains a Twitch-Eventsub-Message-Id
you’ve already seen, immediately return a 2XX status code.
Subscription revocation
Twitch reserves the right to revoke a subscription at any time. The most common reasons for revocation are:
- The subscription depends on events for a user id that no longer exists.
- The subscription depends on an authorization token that was revoked by the user.
- The subscription callback failed its notifications over an extended period of time.
When a subscription is revoked, you’ll receive a revocation
request to that subscription’s callback:
POST https://example.com/webhooks/callback
----
Twitch-Eventsub-Message-Id: 84c1e79a-2a4b-4c13-ba0b-4312293e9308
Twitch-Eventsub-Message-Retry: 0
Twitch-Eventsub-Message-Type: revocation
Twitch-Eventsub-Message-Signature: sha256=c1f92c51dab9888b0d6fb5f7e8e758
Twitch-Eventsub-Message-Timestamp: 2019-11-16T10:11:12.123Z
Twitch-Eventsub-Subscription-Type: channel.follow
Twitch-Eventsub-Subscription-Version: 1
----
{
"subscription": {
"id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4",
"status": "authorization_revoked",
"type": "channel.follow",
"version": "1",
"condition": {
"broadcaster_user_id": "12826"
},
"transport": {
"method": "webhook",
"callback": "https://example.com/webhooks/callback"
},
"created_at": "2019-11-16T10:11:12.123Z"
}
}
To handle a subscription revocation request:
- Verify the request signature to make sure it came from Twitch.
- Return a 2XX status code.
Limits
Twitch enforces limits on the subscriptions you create:
- There is a limit of 10,000 total subscriptions.
- There is a limit of 3 subscriptions with the same
type
andcondition
values.