Using Webhooks

Thinkific's Webhooks can be used by your app, integration, or custom solution to receive event from your Thinkific site.

Thinkific Webhooks provide a way to receive information about events as soon as they happen in your Thinkific site. They allow developers to build apps that receive information, in near real-time, about events that happen in Thinkific and enable them to extend, customize, and integrate Thinkific with their own custom extensions or even with other applications around the web.

Webhooks are a useful tool for apps that want to execute code after a specific event happens on a site, for example, after a customer purchase a course, or a student completes a course. All of the currently available Thinkific webhook events are documented here.

We strongly recommend that any apps that currently ping our API on a regular schedule looking for new information upgrade they system and register Webhooks to listen for these events instead. This uses less API requests overall, allowing you to build more robust apps, and update your app instantly after a webhook is received.

Creating and modifying WebhooksLink

You can create and modify your webhooks in one of two ways:

  1. Automatically using the Webhooks API (Recommended)
  2. Manually using the Thinkific Admin UI.

Webhooks APILink

Using the Webhooks API is the recommended appoach for developers creating Public Apps because it can be done automatically when the app is installed on a new Thinkific Site.

Thinkific Admin UILink

When creating or editing a Webhook manually on your Thinkific Site, follow this guide:

Creating a new Webhook (from Thinkific Admin)Link

  1. In your Thinkific Site, go to Settings and select the Code & Analytics tab.

  2. Using the menus or scrolling to the bottom of the page, navigate to the Webhooks block and sleect the Webhooks button

  3. Click the New Webhook on the top right. New Webhook

  4. Input the Model, Topic and Target URL and save Creat new Webhook *Target URL is the URL you want the webhook to send the event to.

Note: The trouble with testing your webhooks through the API is that you need a publicly visible URL to handle them. Unlike client-side redirects, webhooks originate directly from the server. This means that you cannot use the following as an endpoint in your testing environment:

  • Localhost
  • "Fake" domains like www.example.com
  • Thinkific domains (i.e. thinkific.com)

There are a couple of tools that make working with webhooks during development much easier such as RequestBin, Pagekite and ngrok.

Modifying a Webhook (from Thinkific Admin)Link

Once your webhook is created, you will see it in your webhooks list. From this page, you can click the Edit button on the right to make any changes. You can also click the ellipsis (3 dot icon) to send a test event, or delete the webhook.

Modify Webhook

Viewing Webhook LogsLink

If you need to see the events that have been sent, you can click on the webhook topic itself to get payload information and to check for success messages.

Note: Webhook event record history is stored in Thinkific for 30 days before being removed.

Webhook Logs

Receiving WebhooksLink

Once you register a webhook URL with Thinkific, we will issue a HTTP POST request to the URL specified every time that event occurs. The request's POST parameters will contain JSON data relevant to the event that triggered the request.

Anatomy of a WebhookLink

When an event occurs in a Thinkific site that corresponds to a registered webhook topic, Thinkific sends a webhook notification to the specified URL. The webhook contains a payload formatted as JSON, as well applicable HTTP headers. For example, the following headers are sent as part of the order.created event.

  • X-Thinkific-Topic: orders.created
  • X-Thinkific-Hmac-Sha256: some-hex-encoded-weird-token
  • X-Thinkific-Subdomain: passion-to-profit

Some of the returned HTTP headers can be useful for your app. For example, X-Thinkific-Hmac-Sha256 is used to authenticate webhooks, and X-Thinkific-Subdomain is useful for determining the site context.

Responding to WebhooksLink

Upon receiving a webhook, your application must acknowledge that it has received the data by sending a 200 OK response. If Thinkific does not receive a response (or receives a response that is anything outside of the 200 range), we will assume that you did not successfully receive your webhook and will trigger a retry.

Webhooks that consistently fail to recieve a successfull response may be deactivated and removed in the future.

Note: Thinkific has a 5-second timeout period where we will wait for a response so your application should make an effort to respond within this time frame. We strongly recommend that your application responds to the webhook as soon as your app has successfully captured the data and prior to executing any kind of lengthy processing in your system in order to avoid the timeout.

Webhooks RetriesLink

A Webhook retry is designed to automatically resend a webhook if the target URL does not return a 200 success response for whatever reason. This is useful in the event of a Network timeout, or unforseen error that cause the event to fail to reach your application. This means that there will be multiple attempts to deliver the same webhook data over a span of time.

Note: Failed events are tracked in Thinkific and displayed in the Thinkific Webhook UI Logs)

How often will a webhook retry? Link

Single webhooks are scheduled to retry a maximum of 14 times over a span of 16 hours before it is terminated. Each retry will be scheduled with an increased delay each time it needs to be retried.

Exponential Delay Example

Retry AttemptDelay until webhook is fired (in seconds)First try0 seconds2nd try10 seconds3rd try30 seconds4th try1 minute5th try2 minutes...11th try1 hour...14th try8 hours

Verifying webhooks created through the APILink

Webhooks created through Thinkific's API can be verified by calculating a digital signature.

Each webhook request includes a hexadecimal-encoded X-Thinkific-Hmac-Sha256 header generated using one of the following:

  • Site's API Key api key

  • App Client Secret app's client secret

To verify that the request came from Thinkific, compute the HMAC digest and compare it to the value in the X-Thinkific-Hmac-Sha256 header. If they match, the Webhook was sent from Thinkific and the data has not been compromised.

ExamplesLink

In this section you will find some code samples to validate the webhook payload.

RubyLink

If you are using a Rack based framework such as Ruby on Rails or Sinatra the header you are looking for is HTTP_X_THINKIFIC_HMAC_SHA256

Below is a simple example in Ruby using the Sinatra web framework of how one might verify a webhook request.

require 'rubygems'
require 'openssl'
require 'sinatra'

# The Thinkific's api key, viewable from the Tenant's advanced settings
# If the webhooks was created by your app, you can find the App Secret at
# Partners Portal, at your app's details page
API_KEY_OR_APP_SECRET = 'my_api_key_or_my_app_secret'

helpers do
  # Compare the computed HMAC digest based on the api key and the request contents
  # to the reported HMAC in the headers
  def verify_webhook(data, hmac_header)
    calculated_hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), API_KEY_OR_APP_SECRET, data)
    ActiveSupport::SecurityUtils.secure_compare(calculated_hmac, hmac_header)
  end
end

# Respond to HTTP POST requests sent to this web service

post '/' do
  request.body.rewind
  data = request.body.read
  verified = verify_webhook(data, env["HTTP_X_THINKIFIC_HMAC_SHA256"])

  # Output 'true' or 'false'
  puts "Webhook verified: #{verified}"
end

JavascriptLink

An example using Node.JS Crypto library

import crypto from 'crypto';

const SECRET = 'secret'  // site's api key or app client secret

const validateHmac = (payload, hash) => {
  const hmac = crypto.createHmac('sha256', SECRET).update(payload).digest('hex');
  return hmac === hash;
}

Up Next: Webhooks DocumentationLink