When building apps with user-generated content (UGC), moderating content is essential to create a safe digital space and protect brand integrity. However, moderation latency can be frustrating for users who expect to see their content uploaded instantly.
With Cloudinary webhooks, you can defer moderation to happen asynchronously in the background, so users can still see their images instantly. In this blog post, we’ll walk you through implementing Cloudinary webhooks to keep your moderation process efficient and scalable.
Webhooks are HTTP callbacks that allow Cloudinary to notify your server when certain events occur, such as the completion of image moderation. Instead of your app waiting for moderation to complete during upload, Cloudinary sends the moderation result to a URL you specify, letting your app handle it asynchronously.
This approach is practical for apps that handle frequent image uploads, like social media platforms, marketplaces, or e-commerce stores.
First, you need a server endpoint to handle notifications from Cloudinary. This endpoint will receive POST requests with details about the uploaded image, including a moderation property indicating the moderation status.
For example, if you’re using Node.js, your webhook might look like this:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhook/moderation', (req, res) => {
const { public_id, moderation, notification_type } = req.body;
if (notification_type === 'moderation' && moderation[0].status === 'approved') {
console.log(`Image ${public_id} was approved.`);
// Handle approved image (e.g., make it visible on the platform).
} else if (notification_type === 'moderation') {
console.log(`Image ${public_id} was rejected.`);
// Handle rejected image (e.g., notify the uploader or take corrective action).
}
res.sendStatus(200); // Acknowledge receipt of the webhook.
});
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Code language: JavaScript (javascript)
Here’s an example of what the POST request payload might look like:
{
"asset_id": "dfe8cbdc8f5d4c5e9b5e8f5d4c5e9b5e",
"public_id": "sample_image",
"version": 1625247600,
"version_id": "1a2b3c4d5e6f7g8h9i0j",
"signature": "abcdef1234567890abcdef1234567890abcdef12",
"width": 800,
"height": 600,
"format": "jpg",
"resource_type": "image",
"created_at": "2023-07-02T12:00:00Z",
"tags": [],
"pages": 1,
"bytes": 350000,
"type": "upload",
"etag": "12345abcde",
"placeholder": false,
"url": "http://res.cloudinary.com/demo/image/upload/v1625247600/sample_image.jpg",
"secure_url": "https://res.cloudinary.com/demo/image/upload/v1625247600/sample_image.jpg",
"access_mode": "public",
"moderation": [
{
"kind": "manual",
"status": "approved"
}
],
"notification_type": "moderation"
}
Code language: JSON / JSON with Comments (json)
You can set the webhook URL in two ways:
- Globally in the Cloudinary Dashboard. Go to Settings > Webhook Notifications in your Cloudinary account, click Add Notification URL and add your webhook endpoint (e.g., https://yourdomain.com/webhook/moderation), and select Moderation as the Notification type. This applies to all uploads by default.
- Per Upload Request. Use the notification_url parameter in the body of your API call to override the global setting for specific uploads.
To defer immediate moderation, include the moderation and notification_url
parameters when uploading images. Here’s an example using cURL
:
curl https://api.cloudinary.com/v1_1/your_cloud_name/image/upload \
-X POST \
--data 'file=your_image.jpg&moderation=manual¬ification_url=https://yourdomain.com/webhook/moderation&api_key=YOUR_API_KEY×tamp=YOUR_TIMESTAMP&signature=YOUR_SIGNATURE'
Code language: JavaScript (javascript)
In this request:
moderation
. This specifies the moderation type. Options include:
manual
. Requires human review.aws_rek
. Uses the AWS Rekognition AI add-on for automatic moderation.webpurify
. Automatic image moderation with the WebPurify’s Image Moderation add-on.perception_point
. Scans for malware and malicious content using the Perception Point Malware Detection add-on.duplicate_image
. Detects and prevents duplicate images using the Cloudinary Duplicate Image Detection add-on.google_video_moderation
. Automatic video moderation with the Google AI Video Moderation add-on.
notification_url
. The webhook URL where moderation results will be sent.
Cloudinary also allows you to apply multiple moderation types simultaneously by specifying a pipe-separated list in the moderation parameter. This is useful if you want to evaluate assets against multiple criteria, such as detecting inappropriate content using Amazon Rekognition AI Moderation and identifying duplicates via Cloudinary’s Duplicate Image Detection add-on. The order of the list dictates the sequence in which moderations are applied, and manual moderation must always be the last step if included.
Each moderation has a distinct status:
- queued. Waiting for earlier moderations to complete.
- pending. Currently being processed.
- approved/rejected. Indicates the outcome of the moderation.
- aborted. Skipped because a prior moderation rejected the asset.
The process continues sequentially: the next begins if a moderation is approved. Any remaining moderations are aborted if one is rejected, and the asset is marked as rejected. At the end of the moderation process, a summary notification is sent detailing the status of each moderation (approved, rejected, pending, or aborted) and the overall outcome. Manual moderation only sends the final status after user action, while automatic-only moderations resolve immediately after all are approved or one is rejected. Always include a notification URL to track updates efficiently.
For example, to apply Amazon Rekognition AI Moderation and Cloudinary Duplicate Image Detection with notifications, you can structure your API call as follows:
curl https://api.cloudinary.com/v1_1/demo/image/upload -X POST \
--data 'file=your_image.jpg&moderation=aws_rek|duplicate:0¬ification_url=https://yourdomain.com/webhook/moderation×tamp=YOUR_TIMESTAMP&api_key=YOUR_API_KEY&signature=YOUR_SIGNATURE'
Code language: JavaScript (javascript)
To ensure everything is set up correctly:
- Upload an image with the moderation and notification_url parameters.
- Monitor your webhook server to verify that moderation notifications are being received.
- Confirm that your app processes the moderation status (e.g., approving or rejecting images) as expected.
Deferring moderation with Cloudinary webhooks helps your app handle image uploads quickly while managing moderation efficiently. It’s a practical solution for platforms like social networks or e-commerce apps that need both speed and reliability.
Ready to implement deferred moderation? Read Cloudinary’s documentation on webhooks and moderation tools, and sign up for a free account.