Overview

Webhooks provide a way to receive real-time notifications when specific events occur within the system. By configuring webhooks, you can automate workflows and integrate seamlessly with external systems.

Key Features

  • Enable/Disable: Webhooks can be toggled on or off as needed. This allows for flexible control without requiring deletion or reconfiguration.
  • Multiple Webhooks: You can create multiple webhooks to handle different events or integrate with various external systems.
  • Event-Driven Notifications: Webhooks send HTTP POST requests to a specified URL whenever a defined event is triggered.
  • Scoped Events: Each webhook can be configured with an optional scope to filter which events trigger notifications, providing precise control over its behavior.
  • Signed Requests: Each request includes a signature generated using the signing secret, derived from the request's timestamp and body. This ensures the security and authenticity of the data.

Events

EventItem Sent
entitlement-createdEntitlement
vod-media-createdVOD Media
vod-media-encode-completedVOD Media
vod-media-encode-cancelledVOD Media
vod-media-encode-failedVOD Media

Request Structure

All webhook notifications are sent as HTTP POST requests. Each request includes two headers to provide important metadata and ensure security:

  • Timestamp: Indicates when the request was generated. This value is also used as part of the signature calculation for verifying the authenticity of the request.
  • Signature: header contains a cryptographic signature, allowing you to verify both the authenticity of the request and the integrity of its body. The signature is generated using the signing secret and the request body.

Here’s an example of the header included in a webhook request:

Timestamp: 2025-01-30T12:00:00Z
Signature: sha256=abcd1234efgh5678ijkl...

Body

The request body is sent as JSON and contains details about the event and its associated data. Below is an example of the JSON payload:

{
  "version": "1.0",
  "event": "entitlement-created",
  "data": {}
}

Key Fields:

  • version: Specifies the version of the payload structure. The current version is 1.0. It is important to check this field, as future updates may increment the version number, potentially introducing breaking changes.
  • event: Identifies the type of event that triggered the webhook. Refer to the Events section for a complete list of possible values.
  • data: Contains the item or resource associated with the event. The structure of this object varies depending on the event type. Refer to the API Documentation for details about the data structure.

Security

Webhook signatures protect webhook requests by ensuring they are authentic, untampered, and timely. This is achieved through the use of HMAC signatures and a timestamp, providing integrity, authenticity, and protection against replay attacks.

Integrity

HMAC signatures ensure the payload has not been tampered with. The timestamp header and raw body of the webhook is signed using a shared secret key, and any modifications to the payload will invalidate the signature, making it impossible for attackers to alter the data undetected.

Authenticity

The shared secret key, known only to the sender and receiver, ensures that only the legitimate sender can generate a valid signature. This guarantees that the webhook request is authentic and not forged by unauthorized third parties.

Replay Attack Protection

A timestamp included in the body prevents replay attacks by ensuring the request is valid only for a limited time. The receiver verifies that the timestamp is within an acceptable time window (e.g. 5 minutes). Requests with stale or invalid timestamps are rejected, stopping attackers from reusing intercepted webhook requests.


Validating Signatures

To ensure the security of incoming webhook requests, the signature must be validated by the receiver. This process verifies that the request is authentic, untampered, and timely. Below is a step-by-step guide to validating the signature:

Extract the Required Information

Raw Body: Obtain the raw body of the webhook request. Do not parse or modify it before validation, as even minor changes (e.g., formatting) can invalidate the signature.
Signature: Extract the signature sent in the Signature HTTP header.
Timestamp: Extract the signature sent in the Timestamp HTTP header.

Recompute the HMAC Signature

The signature is computed on the concatenation of the timestamp and the raw payload, separated by a period (.). The process follows the Scala implementation:

  1. Concatenate the timestamp and raw payload:
    data_to_sign = timestamp + "." + raw_payload
  2. Compute HMAC using SHA-256 and a shared secret key:
    mac = HMAC-SHA256(secret_key, data_to_sign)
  3. Base64 encode the result:
    computed_signature = Base64.encode(mac.doFinal(data_to_sign.getBytes))

Compare Signatures

Compare the computed_signature with the Signatureheader provided in the webhook request. To prevent timing attacks, use a constant-time comparison function:

Validation Check:
If the computed and provided signatures match, the request is authentic.
If they do not match, reject the request as potentially tampered or forged.

Validate the Timestamp

To prevent replay attacks, check whether the timestamp is within an acceptable time window.

  1. Parse the Timestamp
  2. Compare with Current Time:
    • Get the current server time.
    • Calculate the difference between the current time and the provided timestamp.
  3. Reject Stale Requests: If the time difference exceeds the allowed threshold (e.g. 1 minute), reject the request.

Reject Invalid Requests

Reject the webhook request if any of the following checks fail:

  • The signatures do not match.
  • The timestamp is missing, invalid, or outside the allowed time window.