Documentation Index Fetch the complete documentation index at: https://docs.runblob.io/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks доставляют события завершения, ошибки и таймаута прямо на ваш эндпоинт — без polling.
Руководство по настройке
Создайте webhook-эндпоинт
Поднимите HTTPS-эндпоинт, принимающий POST-запросы. from flask import Flask, request, jsonify
app = Flask( __name__ )
@app.route ( '/webhook/o3-video' , methods = [ 'POST' ])
def handle_webhook ():
data = request.json
if data[ 'status' ] == 'completed' :
print ( f "Video ready: { data[ 'video_url' ] } " )
# Process the completed video
else :
print ( f "Generation failed: { data[ 'message' ] } " )
# Handle the error
return jsonify({ 'status' : 'received' }), 200
Передайте URL webhook
Укажите URL вашего webhook при создании задачи. curl -X POST https://platform.runblob.io/v1/kling/o3-video/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Dragon flying over mountains",
"duration": "10",
"mode": "pro",
"callback_url": "https://your-app.com/webhook/o3-video"
}'
Обработайте уведомления
Ваш эндпоинт получит мгновенное уведомление по готовности задачи.
Структура payload
Отправляется при успешной генерации. {
"generation_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"status" : "completed" ,
"video_url" : "https://cdn.example.com/videos/550e8400.mp4" ,
"model" : "kling-o3-video-10s-pro" ,
"message" : null
}
Всегда "completed" при успехе
Прямая ссылка для скачивания видео
Использованная конфигурация модели (например, kling-o3-video-10s-pro)
Отправляется при ошибке генерации с конкретным кодом. {
"generation_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"status" : "failed" ,
"video_url" : null ,
"model" : "kling-o3-video-10s-pro" ,
"message" : "CONTENT_POLICY_VIOLATION"
}
Всегда "failed" при ошибке
Всегда null при неудачной задаче
Отправляется при превышении лимита в 15 минут. {
"generation_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"status" : "failed" ,
"video_url" : null ,
"model" : "kling-o3-video-10s-pro" ,
"message" : "TIMEOUT"
}
Кредиты автоматически возвращаются при таймауте.
Коды ошибок
Типичные коды, приходящие через webhooks:
Код Описание Действие CONTENT_POLICY_VIOLATIONКонтент нарушает правила Измените промпт IMAGE_INACCESSIBLEURL изображения вернул 404/403 Проверьте URL INVALID_IMAGEФормат изображения невалиден Используйте JPEG/PNG TIMEOUTГенерация превысила 15 минут Кредиты возвращены TASK_FAILEDОбщая системная ошибка Кредиты возвращены, повтор MAINTENANCEСервис временно недоступен Повторите позже
Возможности надёжности
Политика повторов: до 5 попыток с интервалом 30 секундСтратегия задержки: линейнаяОбработка отказа: после 5 попыток webhook помечается как failed
Тайм-аут запроса: 30 секундТайм-аут соединения: 10 секундРекомендация: быстро отвечайте кодом 200, обрабатывайте асинхронно
HTTPS обязателен: URL webhook должен использовать HTTPSIP allowlist: рассмотрите ограничение по IP RunBlobВалидация: всегда проверяйте generation_id
Примеры реализации
Flask
Express.js
TypeScript + Next.js
from flask import Flask, request, jsonify
import logging
app = Flask( __name__ )
logging.basicConfig( level = logging. INFO )
@app.route ( '/webhook/o3-video' , methods = [ 'POST' ])
def o3_video_webhook ():
try :
data = request.json
generation_id = data.get( 'generation_id' )
if data.get( 'status' ) == 'completed' :
video_url = data.get( 'video_url' )
model = data.get( 'model' )
logging.info( f "Video ready for { generation_id } : { video_url } ( { model } )" )
# Process successful generation
process_video(generation_id, video_url, model)
else :
error_code = data.get( 'message' )
logging.error( f "Generation failed for { generation_id } : { error_code } " )
# Handle failure
handle_failure(generation_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 ( generation_id , video_url , model ):
"""Process completed video - download, store, notify user"""
# Download video to your storage
# Update database
# Notify user via email/push notification
pass
def handle_failure ( generation_id , error_code ):
"""Handle failed generation - log, refund, notify"""
# Log error for analytics
# Update database with failure reason
# Notify user of failure
pass
if __name__ == '__main__' :
app.run( port = 3000 )
Лучшие практики
Всегда сразу возвращайте 200 OK. Тяжёлую обработку делайте асинхронно: app . post ( '/webhook' , async ( req , res ) => {
// Acknowledge receipt immediately
res . status ( 200 ). json ({ status: 'received' });
// Process asynchronously
processWebhookAsync ( req . body ). catch ( console . error );
});
Сохраняйте generation IDs
Храните ID генераций в базе, чтобы избежать повторной обработки: def handle_webhook ( data ):
generation_id = data[ 'generation_id' ]
# Check if already processed
if db.is_processed(generation_id):
return # Skip duplicate
# Mark as processed
db.mark_processed(generation_id)
# Process the video
process_video(data)
Всегда проверяйте payload перед обработкой: function validateWebhook ( payload ) {
if ( ! payload . generation_id || ! payload . status ) {
throw new Error ( 'Invalid webhook payload' );
}
if ( payload . status === 'completed' && ! payload . video_url ) {
throw new Error ( 'Missing video_url for completed generation' );
}
return true ;
}
Важно: всегда быстро возвращайте код 200, чтобы подтвердить получение. Тяжёлую обработку выполняйте асинхронно.