Video Moderation / Receive Video Moderation Callbacks

Receive Video Moderation Callbacks

Introduction

Sightengine uses callbacks to let your application know when things happen asynchronously, outside of an API request cycle.

For instance, when a live-stream or a long-running video is moderated, callbacks will be used to inform you when the status of the moderation job changes, or when specific content is detected.

Please use callbacks to track moderation jobs rather than polling the API. Callbacks are much more efficient for both you and Sightengine. Polling requests are rate-limited so polling would not scale and might introduce unwanted delays.

Receiving webhook callbacks

Once you have submitted a video stream and received a 200 HTTP status code, the Moderation Engine will start consuming the stream and will assign a moderation score to relevant frames and send detailed moderation results to your callback URL.

To avoid sending too many callback events, the engine will send callbacks only when one of the following happens:

  • the video has been completely read and moderation is done
  • an "interesting event" has been detected. One such event would for instance be the presence of nudity. This is defined by setting threshold values on the nudity probabilities.
  • an error was encountered after the initial request was closed

Server-side code for callback receipt

Sightengine will submit a POST request to your configured callback URL. You can listen for this callback and process it like this:


# callbacks cannot be received through the command line
# please choose a server-side language to receive and process callbacks
# or use an approach that does not require callbacks (such as sequential video moderation)


import json
from django.http import HttpResponse

# Using Django
@csrf_exempt
def my_callback_view(request):
  payload = request.body
  content = json.loads(payload)

  # You now have access to the following
  # the media id => content['media']['id']
  # the moderation data => content['data']
  # the moderation status => content['data']['status']

  # Acknowledge receipt
  return HttpResponse(status=200)


$payload = @file_get_contents('php://input');
$content = json_decode($payload, true)

// You now have access to the following:
// the media id => $content['media']['id']
// the moderation data => $content['data']
// the moderation status => $content['data']['status']

// Acknowledge receipt
http_response_code(200);


// This example uses Express to receive callbacks
const app = require('express')();

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
  let event;

  content = JSON.parse(request.body);

  // You now have access to the following:
  // the media id => content.media.id
  // the moderation data => content.data
  // the moderation status => content.data.status

  // Acknowledge receipt
  response.json({received: true});
});

app.listen(8000, () => console.log('Running on port 8000'));

Callback recommendations

Acknowledging receipt

To acknowledge receipt of a callback, your endpoint should return a 2xx HTTP status code. Any other information returned in the request headers or request body is ignored. All response codes outside this range, including 3xx codes, will indicate to Sightengine that you did not receive the callback. This does mean that a URL redirection or a "Not Modified" response will be treated as a failure.

If your callback script performs complex logic, or makes network calls, it's possible the script would timeout before Sightengine sees its complete execution. For that reason, you may want to have your callback endpoint immediately acknowledge receipt by returning a 2xx HTTP status code, and then perform the rest of its duties.

CSRF

If you are using a web framework such as Rails or Django, your site might be expecting a CSRF token to be set for all incoming POST requests. CSRFs are important to prevent cross site request forgery, but they will prevent you from receiving legitimate callbacks from Sightengine. You should therefore exempt the callback route from CSRF protection.

Verifying callbacks

As an extra security measure, you should check that the media id value returned in the callback matches the media id returned in the initial API response. This is can be helpful if you have several streams moderated at the same time and need to verify what media each callback refers to.

HTTPS

If you use an HTTPS URL for your callback endopint, please make sure that your server is correctly configured to support HTTPS with a valid server certificate. Sightengine will valide that the connection to your server is secure before sending the data.

Idempotency

Keep in mind that your callback may occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing idempotent.

Did you find this page helpful?

We're always looking for advice to help improve our documentation!

Let us know what you think

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more

OK