Webhooks provide instant notifications when your video generation tasks complete, fail, or timeout. No more polling!
Setup Guide
Create Webhook Endpoint
Set up an HTTPS endpoint that can receive POST requests. from flask import Flask, request, jsonify
app = Flask( __name__ )
@app.route ( '/webhook' , methods = [ 'POST' ])
def handle_webhook ():
data = request.json
if data[ 'success' ]:
print ( f "Video ready: { data[ 'video_url' ] } " )
else :
print ( f "Generation failed: { data[ 'message' ] } " )
return jsonify({ 'status' : 'received' }), 200
Add Webhook URL
Include your webhook URL when creating a generation task. curl -X POST https://api.runblob.com/api/veo/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A sunset over mountains",
"callback_url": "https://your-app.com/webhook"
}'
Handle Notifications
Your endpoint will receive instant notifications when tasks complete.
Payload Structure
Sent when video generation completes successfully. {
"success" : true ,
"message" : "Task completed successfully" ,
"task_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"video_url" : "https://cdn.runblob.com/videos/your-video.mp4"
}
Always true for successful generations
Human-readable success message
UUID of the completed task
Direct download URL for the generated video
Sent when video generation fails with specific error codes. {
"success" : false ,
"message" : "UNSAFE_CONTENT" ,
"task_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"video_url" : null
}
Always false for failed generations
Always null for failed tasks
Sent when generation exceeds the 10-minute limit. {
"success" : false ,
"message" : "TIMEOUT" ,
"task_id" : "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ,
"video_url" : null
}
Credits are automatically refunded for timed-out tasks.
Reliability Features
Retry Policy: Up to 5 attempts with 30-second intervalsBackoff Strategy: Linear backoff between retriesFailure Handling: After 5 failed attempts, the webhook is marked as failed
Request Timeout: 30 seconds per webhook requestConnection Timeout: 10 seconds to establish connectionBest Practice: Respond quickly with a 200 status code
HTTPS Required: All webhook URLs must use HTTPSIP Allowlist: Consider restricting access to RunBlob’s IP rangesValidation: Always validate the task_id in your webhook handler
Example Implementations
from flask import Flask, request, jsonify
import logging
app = Flask( __name__ )
logging.basicConfig( level = logging. INFO )
@app.route ( '/webhook' , methods = [ 'POST' ])
def runblob_webhook ():
try :
data = request.json
task_id = data.get( 'task_id' )
if data.get( 'success' ):
video_url = data.get( 'video_url' )
logging.info( f "Video ready for task { task_id } : { video_url } " )
# Process successful generation
process_video(task_id, video_url)
else :
error_code = data.get( 'message' )
logging.error( f "Generation failed for task { task_id } : { error_code } " )
# Handle failure
handle_failure(task_id, error_code)
return jsonify({ 'status' : 'received' }), 200
except Exception as e:
logging.error( f "Webhook error: { str (e) } " )
return jsonify({ 'error' : 'Internal error' }), 500
def process_video ( task_id , video_url ):
# Your video processing logic here
pass
def handle_failure ( task_id , error_code ):
# Your error handling logic here
pass
Important: Always return a 200 status code quickly to acknowledge receipt. Perform heavy processing asynchronously to avoid timeouts.