Webhooks

Receive real-time notifications on job completion

If you have set a webhook URL while making the create job request, Murf Dub Automation API will send a webhook response to the specified URL when the job is completed, failed, or partially completed. The request to the webhook will contain the following information:

Headers

X-Signature-Timestamp
string

The timestamp of when the request was sent to the webhook URL.

X-HMAC-Signature
string

The HMAC signature of the payload.

Response

eventName
string

The name of the event associated with the webhook response. This will be “DUB_JOB” for dubbing job endpoints.

data
object

The data payload of the webhook response. The response structure will be similar to the response received from Job Status API endpoint.

Webhook Authentication and Validation

To ensure secure communication, all webhook requests sent by Murf Dub Automation API should be authenticated. The webhook payload includes an HMAC signature and a timestamp header that you can use to validate the request.

Validating the Webhook

Use the following steps to validate the webhook:

  1. Extract the X-Signature-Timestamp and X-HMAC-Signature headers from the request.
  2. Concatenate the payload and the timestamp to form the data to be signed.
  3. Compute the HMAC using the secret you included while sending the create job request and compare it with the X-HMAC-Signature header.
  4. Ensure the timestamp is within an acceptable tolerance window to prevent replay attacks.

If validation fails, reject the webhook request and log the incident for further investigation.

This is how you can validate the webhook request using Murf Python SDK:

1from murf.utils import validate_hmac
2import json
3
4response_headers = {
5 "X-Signature-Timestamp": "1744269464453",
6 "X-HMAC-Signature": "the_hmac_signature_header_value"
7}
8response_data = {
9 "eventName": "DUB_JOB",
10 "data": {
11 "project_id": None,
12 "job_id": "THE_JOB_ID",
13 "status": "COMPLETED",
14 "download_details": [
15 {
16 "locale": "fr_FR",
17 "status": "COMPLETED",
18 "error_message": None,
19 "download_url": "URL_TO_DOWNLOAD",
20 "download_srt_url": "URL_TO_DOWNLOAD_SRT",
21 }
22 ],
23 "credits_used": 1,
24 "credits_remaining": 99,
25 "failure_reason": None,
26 "failure_code": None
27 }
28}
29
30response_data_str = json.dumps(payload, separators=(',', ':'))
31
32is_valid = validate_hmac(
33 secret="the_secret_that_you_sent_in_create_job_request",
34 payload=response_data_str,
35 timestamp_header=response_headers["X-Signature-Timestamp"],
36 hmac_signature=response_headers["X-HMAC-Signature"],
37 tolerance_seconds=300
38)
39print(is_valid)

If you’re not using python SDK, you can use the following python function to validate the webhook:

1import hmac
2import hashlib
3import time
4
5def validate_hmac(secret, payload, timestamp_header, hmac_signature, tolerance_seconds):
6 try:
7 received_timestamp = int(timestamp_header)
8 current_timestamp = int(time.time()) * 1000
9
10 if (abs(current_timestamp - received_timestamp) / 1000) > tolerance_seconds:
11 print("Timestamp is outside the allowed tolerance window.")
12 return False
13
14 data_to_sign = f"{payload}.{timestamp_header}"
15 calculated_hmac = hmac.new(
16 secret.encode('utf-8'),
17 data_to_sign.encode('utf-8'),
18 hashlib.sha256
19 ).hexdigest()
20
21 return hmac.compare_digest(calculated_hmac, hmac_signature)
22 except Exception as e:
23 print(f"Error validating HMAC: {e}")
24 return False