Webhooks

Webhooks are a way for a web application to be alerted of activity on a Rewatch channel.

Natalie Pabón avatar
Written by Natalie Pabón
Updated over a week ago

Webhooks are a way for a web application to be alerted of activity on a Rewatch channel. By providing a URL to receive JSON payloads representing channel events it’s possible to take action in response to that activity.

As a prerequisite for configuring and using webhooks, be sure to generate an API token and familiarize yourself with querying the Rewatch GraphQL API.

Note: Creating and configuring webhooks may only be done by channel administrators. Webhook events will contain information about channel resources such as collections and videos regardless of their visibility on the channel.

Configuring webhooks via GraphQL

Webhooks can be created and configured using the createWebhook and updateWebhook GraphQL mutations.

Here is an example of calling the createWebhook endpoint query:

mutation ($input: CreateWebhookInput!) {
createWebhook(input: $input) {
viewer {
id
}
webhook {
id
url
description
enabled
retries
events
}
errors {
message
path
}
}
}

And an example of mutation input arguments for the query:

{
"input": {
"url": "<URL to receive the hook>",
"description": "Example hook",
"events": ["VIDEO", "COLLECTION"],
"secrets": [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccc"
],
"retries": 3
}
}

The easiest way to run the above mutation is to use a GraphQL API client application. See the article on querying the Rewatch API for an overview of using a client app with the API.

Create a webhook via GraphQL

Sending the createWebhook mutation with the example arguments creates a webhook that will receive events related to channel videos and collections once enabled.

The mutation arguments shown are:

  • url: The HTTPS URL that will receive a POST request with JSON payload when a channel event occurs.

  • description: A short text description of the webhook for the user’s reference.

  • events: A list of event types to subscribe to. See the webhook events article for more info.

  • secrets: A list of up to five secret tokens that will be used to HMAC-sign event payloads. Signatures will be included for each secret value, making it easier to rotate them as needed. Each secret must be at least 40 characters in length.

  • retries: The number of delivery re-attempts in the case that a non-success HTTP status is returned by the webhook handler. An exponential backoff strategy is employed for redelivery timing.

  • enabled: A boolean value indicating whether events should be delivered for this webhook.

Webhook payloads

Here’s an example of a raw HTTP request that could be delivered to a configured webhook endpoint:

Version: HTTP/1.1
Host: rewatch-example.ngrok.io
User-Agent: Rewatch
Webhooks Accept: application/json;
charset=utf-8
Rewatch-Hook-Delivery-Nonce: cf8540f64eb1de7f9606ecb3ad96b230b9ef8b15
Rewatch-Hook-Delivery-Signatures: 38bdef36aaba6c3ec20c0da3f17284a6,41f15ca050e3787069ea0b1199a602bf
Rewatch-Hook-Delivery-Timestamp: 2021-08-09T20:05:28Z
Rewatch-Hook-Delivery-Event: video.updated
Rewatch-Hook-Id: V2ViaG9vay0x

{
"hookId": "V2ViaG9vay0x",
"nonce": "cf8540f64eb1de7f9606ecb3ad96b230b9ef8b15",
"at": "2021-08-09T20:05:28.895Z",
"event": "video.updated",
"actor": {
"id": "VXNlci02MTcz",
"firstName": "Example",
"lastName": "User",
"email": "user@example.com",
"createdAt": "2021-07-15T04:17:22.550Z"
},
"channel": {
"url": "https://example.rewatch.com",
"name": "Example Channel",
"subdomain": "example",
"description": null,
"createdAt": "2021-07-15T04:17:22.545Z"
},
"video": {
"id": "VmlkZW8tMTE4MjA=",
"url": "https://example.rewatch.com/video/11820/snack",
"title": "My Zoom Call",
"summary": "",
"visibility": "ON_CHANNEL",
"presentedAt": "2021-07-15T00:00:00.000Z",
"duration": 60.466,
"collections": [],
"taggedUsers": [],
"createdAt": "2021-07-15T04:43:10.154Z"
},
"updates":{
"title": {
"from": "My Zoom Call",
"to": "API Design Session"
}
}
}


Each webhook delivery consists of metadata header values and a JSON payload containing information that corresponds to the channel activity that triggered the hook.

There are a few fields that are consistent across payloads:

  • The event entry in the JSON payload represents the action that triggered the webhook, with the actor field representing the user who performed that action.

  • Each payload will also include a channel field, representing your Rewatch channel.

  • For event payloads representing updates to existing records, the updates field should contain the relevant before and after values.

For a full list of event types see the webhook events help article.

Validating webhooks via HMAC

It’s strongly recommended that you validate the event payload deliveries received by your application using the comma-separated signature values included in the Rewatch-Hook-Delivery-Signatures header field.

The signatures are HMAC values that are generated using the configured secrets for the webhook as well as values distinct to the payload itself.

The simplified example code below illustrates how to validate an event payload using the HMAC signatures using the Ruby on Rails web framework:

class HookDeliveriesController < ApplicationController
SECRETS = [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccc",
].freeze

def create
signatures = headers["Rewatch-Hook-Delivery-Signatures"].to_s.split(",")

hashes = SECRETS.map do |secret|
OpenSSL::HMAC.hexdigest(
"SHA256",
secret,
[
headers["Rewatch-Hook-Id"],
headers["Rewatch-Hook-Delivery-Event"],
headers["Rewatch-Hook-Delivery-Nonce"],
headers["Rewatch-Hook-Delivery-Timestamp"],
].join(";"),
)

if (signatures & hashes).empty?
# No matching signatures, so we assume this is a spoofed payload.
# We return a successful status code hoping to fool the attacker.
head :ok and return
end

# Respond to the legitimate payload here...
head :created
end
end
end

If you choose, you may also require the delivery timestamp to fall within a certain window prior to the current time, which can help to mitigate the risk of payload replay attacks.

Testing webhooks

Webhook URLs must be configured as HTTPS endpoints, which can be a hurdle in local development environments.

Ngrok is a web service that proxies HTTP and HTTPS requests to public endpoints to local machines via a secure tunnel and is tailor-made for developing webhook handlers.

Did this answer your question?