ImageKit uses webhooks to notify your application when an event occurs in your account. Webhooks are particularly useful for asynchronous events such as video encoding and extension processing during uploads.
Steps to receive webhooks
- Configure the webhook in your ImageKit dashboard.
- Create a webhook endpoint as an HTTP endpoint (URL) on your server and listen for incoming webhook requests.
- Handle requests from ImageKit by parsing each event object and returning
2xx
response status codes. You can also verify the webhook signature to ensure the authenticity of the request. We recommend using the ImageKit SDK to handle webhook signature verification and prevent replay attacks.
Configure a Webhook
Go to the Developer options in the ImageKit dashboard. Under Webhooks, you will see the list of configured webhook endpoints.
Click the "Add new" button to create a new webhook endpoint.
Enter a valid HTTP(S) endpoint, select the events you want to receive, and click "Create."
You should now see the webhook endpoint in the list.
To update an existing endpoint, click ...
. You can change its current status (enabled or disabled) and update the list of active events.
Listen to Webhook
Use a tool like Ngrok to make your webhook endpoint publicly accessible for testing webhook implementation.
All webhook bodies are JSON-encoded. The body schema may differ based on the event type, but the following fields are standard:
Field | DataType | Description |
---|---|---|
type | string | Type of event. |
id | string | Unique identifier of the event. |
created_at | string | Timestamp of the event in ISO8601 format. |
data | JSON | Actual event payload in JSON format. |
Verify webhook signature
Webhook endpoints are publicly accessible, so filtering out malicious requests is essential. We recommend using the webhook signature to verify the authenticity of the webhook request and payload.
ImageKit follows the Standard Webhooks specification for secure webhook verification and sends webhook-id
, webhook-timestamp
, and webhook-signature
HMAC-SHA256 signature headers.
You can use the webhook secret, which starts with the whsec_
prefix, to verify the webhook payload as explained below.
We will continue to send the legacy
x-ik-signature
header as well if you are using an old SDK or old verification method.
Verify signature with ImageKit SDK
We recommend using our official libraries to verify signatures. You can perform the verification by providing the raw event payload, request headers, and the webhook secret. If verification fails, you will get an error.
For development and testing purposes, SDKs also provide methods that skip signature verification entirely - however, these should never be used in production environments as they bypass critical security measures.
We are updating our SDKs, so if you don't see a snippet for your language, refer to the manual verification process.
import ImageKit from '@imagekit/nodejs'; import express from 'express'; const client = new ImageKit({ privateKey: "your_private_key", webhookSecret: "whsec_..." // Copy from ImageKit dashboard }); const app = express(); // For mixed APIs: Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === '/webhook') { next(); // Skip JSON parsing for webhook } else { express.json()(req, res, next); } }); app.post( '/webhook', // ImageKit requires the raw body to construct the event express.raw({ type: 'application/json' }), (req, res) => { try { // Verify signature and parse webhook payload securely const event = client.webhooks.unwrap(req.body, { headers: req.headers // Optional: Use a different webhook secret for this request // key: 'whsec_different_secret' }); // Alternative: For development/testing only (NEVER use in production) // const event = client.webhooks.unsafeUnwrap(req.body); console.log('✅ Verified webhook event:', event.type); // Handle different event types with full type safety switch (event.type) { case 'video.transformation.accepted': console.log('Video transformation accepted:', event.data.asset.url); // Debugging: Track transformation requests break; case 'video.transformation.ready': console.log('Video transformation ready:', event.data.transformation.output?.url); // Update your database/CMS to show the transformed video // Example: updateVideoStatus(event.data.transformation.output.url, 'ready') break; case 'video.transformation.error': console.error('Video transformation error:', event.data.transformation.error?.reason); // Log error and check your origin/URL endpoint settings break; case 'upload.pre-transform.success': console.log('Pre-transform success:', event.data.fileId); // File uploaded and pre-transformation completed break; case 'upload.pre-transform.error': console.error('Pre-transform error:', event.data.transformation.error?.reason); break; case 'upload.post-transform.success': console.log('Post-transform success:', event.data.url); // Additional transformation completed break; case 'upload.post-transform.error': console.error('Post-transform error:', event.data.transformation.error?.reason); break; default: console.log(`Unhandled event type: ${event.type}`); } // Return a response to acknowledge receipt of the event res.json({ received: true }); } catch (error) { // On error, log and return the error message console.log(`❌ Error message: ${error.message}`); res.status(400).send(`Webhook Error: ${error.message}`); } } ); const server = app.listen(3000); console.log( `🚀 Webhook endpoint available at http://localhost:3000/webhook` );
Verify signature manually
ImageKit follows the Standard Webhooks specification for secure webhook verification. This approach provides better security and standardized implementation.
For implementation examples in Python, Node.js (use our SDK), PHP, Go, and other languages, refer to the Standard Webhooks GitHub repository. The repository contains complete examples and libraries for all supported languages.
Important: When using Standard Webhooks libraries directly, make sure to base64 encode your webhook secret before passing it to the library.
ImageKit webhook requests contain an x-ik-signature
header like this:
x-ik-signature: t=1655795539264,v1=b6bc2aa82491c32f1cbef0eb52b7ffaa51467ea65a03b5d4ccdcfb9e0941c946
The timestamp of the signature is a Unix timestamp in milliseconds, prefixed with t=
. The HMAC signature is prefixed with v1=
.
Once you have retrieved the webhook signature from the request header and raw request body, you can verify the authenticity of the webhook request in the following steps:
Step 1: Extract each item from the x-ik-signature
by splitting on the ,
separator.
items = 't=1655795539264,v1=b6bc2aa82491c32f1cbef0eb52b7ffaa51467ea65a03b5d4ccdcfb9e0941c946'.split(',') // [ 't=1655795539264', 'v1=b6bc2aa82491c32f1cbef0eb52b7ffaa51467ea65a03b5d4ccdcfb9e0941c946' ]
Step 2: Extract the timestamp.
timestamp = 't=1655795539264'.split('=')[1] // '1655795539264'
Step 3: Extract the signature encoded as a hex string.
signature = 'v1=b6bc2aa82491c32f1cbef0eb52b7ffaa51467ea65a03b5d4ccdcfb9e0941c946'.split('=')[1] // 'b6bc2aa82491c32f1cbef0eb52b7ffaa51467ea65a03b5d4ccdcfb9e0941c946'
Step 4: Compute the HMAC hash using the webhook secret, signature timestamp, and raw request body.
- The HMAC key is the webhook secret.
- The HMAC payload is formed by concatenating the timestamp (as a numeric string), the character
.
, and the raw request body (encoded as a UTF8 string). - Use the SHA256 algorithm to compute the HMAC hash.
- The HMAC hash is encoded as a hex string.
Here is an example in Node.js:
const createHmac = require("crypto").createHmac; var signature = createHmac('sha256', webhookSecret) .update(timestamp + '.' + rawRequestBody) .digest('hex');
Step 5: Compare the signature with the signature received in the x-ik-signature
header. The webhook request is valid if they are the same.
Preventing replay attacks
When an attacker intercepts a webhook request, they can replay it multiple times with a valid signature.
To mitigate this, the ImageKit webhook signature contains a timestamp. The timestamp is generated before the webhook request is sent to your server.
The verification method in the ImageKit SDK returns the timestamp and parsed event object.
If the timestamp is within the tolerance limit, the request can be considered valid, or you can reject it.
Optionally, a stronger approach is to use a nonce to prevent replay attacks. You can use the Event ID as a nonce, which is guaranteed to be unique across all events. You can find the event ID in the id
field of the event object.
List of events
Below is the list of events for which ImageKit calls your configured webhook: