Webhooks
We added webhooks to notify you about the status of a process initiated using one of our tools. This helps you automate workflows using our API.
Quick Start
Creating a new webhook endpoint is easy.
- Open the API page in your profile and navigate to "Webhooks".
- Click the "Create Webhook" button at the top.
- Enter a Name and the URL of your endpoint.
- Click "Test & Create"
- A first test will then be executed. Copy the
secret
for your endpoint script.
The first part is done. Now it's time to create the endpoint on your server. You can edit the URL or name of the endpoint at any time.
Whenever a process finishes or fails, a request will be sent to your server.
Tools
The following tools use webhooks to notify you about finished or failed processes:
- Subtitle Translator
- Subtitle Converter (Batch Processing)
- Loudness Radar & Normalizer
- Scene Cut Detection
- Stills from Video
Webhook Payload Details
Each webhook request will include a JSON payload with the following fields:
event
(string): The type of event that triggered the webhook. Currently, only"process"
events are supported.status
(string): The current status of the process. Possible values are:"finished"
: The process completed successfully."failed"
: The process encountered an error and could not be completed.
processId
(string): A unique identifier for the initiated process. This ID can be used with the "Get Process Details" endpoint to retrieve more information or download files.
Webhook Payload Example (Finished)
When a process is successfully completed, it sends a request with the following content:
{
"event": "process",
"status": "finished",
"processId": "#ABC123"
}
Webhook Payload Example (Failed)
If a process fails, it will generate a request similar to the following:
{
"event": "process",
"status": "failed",
"processId": "#ABC123"
}
Signature Verification
To ensure the authenticity and integrity of the webhooks you receive, it's crucial to verify the signature included in the HTTP_EDITINGTOOLS_SIGNATURE
header. This header contains a timestamp and a signature, separated by commas.
The signature is generated using an HMAC-SHA256 hash of the webhook payload and your unique endpoint secret. Verifying this signature protects your endpoint from unauthorized requests and ensures the data hasn't been tampered with.
How Signature Verification Works
- Extract Information: From the
HTTP_EDITINGTOOLS_SIGNATURE
header, extract thet
(timestamp) andv1
(signature) values. - Prepare the Signed Payload: Concatenate the timestamp (as a string) with a dot (
.
) and the raw JSON payload body. For example:t.payload_body
. - Compute Expected Signature: Calculate the HMAC-SHA256 hash of the signed payload using your endpoint secret as the key.
- Compare Signatures: Compare your computed signature with the
v1
signature received in the header. If they match, the webhook is valid.
Webhook Endpoint Best Practices
To ensure reliable and secure webhook processing, consider the following best practices for your endpoint:
- Respond Quickly: Your webhook endpoint should process the incoming request as quickly as possible and return an HTTP 200 OK response. Avoid performing long-running tasks directly within the webhook handler. Instead, queue these tasks for asynchronous processing.
- Expected HTTP Responses:
- HTTP 200 OK: Return a
200 OK
status code if you successfully received and processed the webhook. - HTTP 4xx/5xx: If your endpoint encounters an error (e.g., invalid signature, server error), return an appropriate
4xx
(client error) or5xx
(server error) status code.
- HTTP 200 OK: Return a
- Webhook Retries: If your endpoint does not return a
200 OK
status code, we will not automatically retry the delivery of the webhook. - Logging: Implement robust logging for all incoming webhook requests, including the full request body and headers. This will be invaluable for debugging any issues.
Receive a webhook (example)
You can receive a webhook by creating a script similar to this PHP example. Make sure to replace the endpoint_secret
.
// webhook.php
header('Content-Type: application/json');
$endpoint_secret = 'whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$payload = @file_get_contents('php://input');
$signature_header = $_SERVER['HTTP_EDITINGTOOLS_SIGNATURE'];
$timestamp = null;
$signature = null;
if (!$signature_header) {
http_response_code(400);
echo json_encode(['message' => 'Missing signature']);
exit();
}
// Parse Stripe-style signature header
foreach (explode(',', $signature_header) as $pair) {
list($k, $v) = explode('=', $pair, 2);
if ($k === 't') $timestamp = $v;
if ($k === 'v1') $signature = $v;
}
$expected_signature = hash_hmac('sha256', $timestamp . '.' . $payload, $endpoint_secret);
if (!hash_equals($expected_signature, $signature)) {
http_response_code(400);
echo json_encode(['message' => 'Invalid signature']);
exit;
}
$data = json_decode($payload, true);
// Process webhook data (customize to your event)
//file_put_contents('webhook_log.txt', print_r($data, true), FILE_APPEND);
// or enter it into your database...
http_response_code(200);
echo json_encode(['message' => 'Webhook received']);
Send a Test Request
To generate a test request, click the three dots on your webhook endpoint and select "Test Endpoint."
Get Processed Files
To receive and download the processed files, use the "Get Process Details" endpoint.
Authentication
This API requires Basic Authentication. The "Authorization" header should be set with the Base64 encoded string of "apikey:YOUR_API_KEY".
Authorization: Basic <base64Encoded(apikey:YOUR_API_KEY)>
Data Handling
Request parameters must be UTF-8 encoded. Results are returned as UTF-8-encoded JSON. By default, datasets will be inside the data tag.
Error Handling
This API service uses standard HTTP response codes to indicate whether a method was completed successfully. HTTP response codes in the 2XX range indicate success. Responses in the 4XX range indicate some sort of failure, while responses in the 5XX range indicate an internal system error that cannot be resolved by the user. The following error codes are used by the API:
Code | Description |
---|---|
200 | OK. The request was successful. |
201 | Created. The entity was created. |
202 | Accepted. The request was accepted. |
400 | Bad request. Please check error message. |
401 | Unauthorized: Username or Api Key is not valid. |
402 | Upgrade Required: This feature requires an active Pro subscription. |
403 | Forbidden: The request is understood, but it has been refused or access is not allowed. |
404 | Not found: The URI requested is invalid or the resource does not exist. |
422 | Unprocessable Entity. A process failed. |
429 | Too Many Requests. Try again in some seconds. |
500 | Internal Server Error. Something is broken. |
502 | Bad Gateway. API is down. |
503 | Service Unavailable. API is up but overloaded with requests. |
504 | Gateway Timeout: API is up but requests reached timout. |
Rate Limits
To prevent abuse and spam, the API has limits at various levels. If you receive error code 429 (Too Many Requests)
, it means you have reached a rate limit.
If you receive a rate limit error, you should stop making requests temporarily. If the retry-after
response header is present, you should not retry your request until after that many seconds has elapsed. To prevent rate-errors, we recommend to wait 300 ms
to 800 ms
between requests to the same endpoint.
Also there is a general limit to the api and all requests made:
Limit | Requests |
---|---|
General limit per minute | 50 |
General limit per hour | 1000 |
Recommended wait time between requests | > 200 ms |
Recommended wait time between requests to one endpoint | > 600 ms |
The general limits per minute and per hour can be changed upon request.
Upload Limits
The maximum upload size for any single request — including file uploads — is 100 MB
. This is a hard limit and applies regardless of your API plan or usage level.
If your request exceeds this size, it will be rejected before reaching our servers. To ensure successful uploads:
- Make sure uploaded files are under 100 MB.
- For larger media, consider splitting files before upload.
- Requests close to the limit may still fail due to encoding or header overhead.
Timezone
This API endpoint returns the time as an ISO 8601 timestamp
in the UTC time zone. These timestamps look like 2025-01-10T15:05:06Z
.
Localization and Languages
This API supports multiple languages. For instance, it can display the text of a status message in a different language.
Accept-Language: LANGUAGE
Example
To set the preferred response language to Spanish, add this header:
Accept-Language: es
cURL Example
To apply the language in a cURL request, add the following header:
-H "Accept-Language: es"
Available Languages
The following list contains all the currently available languages. Note that setting a language header does not guarantee a translated response, as not all texts are translated. If no language is set or a translation is unavailable, the default response will be in English.
Code | Language |
---|---|
en | English |
de | German |
fr | French |
es | Spanish |
ru | Russian |
it | Italian |
el | Greek |
pl | Polish |
pt | Portuguese |
lt | Lithuanian |
ko | Korean |
ja | Japanese |
zh | Chinese |
id | Indonesian |
tr | Turkish |
nl | Dutch |
ro | Romanian |
fi | Finnish |
cs | Czech |
hu | Hungarian |
ar | Arabic |
nb | Norwegian Bokmål |
sk | Slovak |
sl | Slovenian |
sv | Swedish |
lv | Latvian |
et | Estonian |
bg | Bulgarian |
uk | Ukrainian |
da | Danish |