تسمح الويب هوك لواجهة برمجة التطبيقات Gemini API بإرسال إشعارات في الوقت الفعلي إلى خادمك عند اكتمال العمليات غير المتزامنة أو العمليات الطويلة الأمد (LRO). ويحلّ ذلك محل الحاجة إلى طلب البيانات من واجهة برمجة التطبيقات لمعرفة آخر الأخبار، ما يقلّل من وقت الاستجابة والعبء.
تتوفّر الويب هوك لعمليات مثل مهام الدفعات، التفاعلات وإنشاء الفيديوهات.
آلية العمل
بدلاً من طلب البيانات من GET /operations بشكل متكرّر لمعرفة ما إذا كانت مهمة معيّنة قد اكتملت، يمكنك ضبط الويب هوك في Gemini API لإرسال طلب HTTP POST إلى عنوان URL الخاص بالمتتبِّع فور تفعيل مشغِّل حدث معيّن.
تتيح Gemini API طريقتَين لضبط الويب هوك:
- الويب هوك الثابتة: نقاط نهاية على مستوى المشروع تم ضبطها باستخدام واجهة برمجة التطبيقات Gemini WebhookService API. وهي مناسبة لعمليات التكامل العالمية (مثل إرسال إشعار إلى Slack أو مزامنة قاعدة بيانات أو غير ذلك).
- الويب هوك الديناميكية: عمليات إلغاء على مستوى الطلب تمرِّر رابط ويب هوك في حمولة الإعدادات لطلب مهام معيّنة. وهي مثالية لتوجيه مهام معيّنة إلى نقاط نهاية مخصّصة.
الويب هوك الثابتة
يتم تسجيل الويب هوك الثابتة لمشروع كامل project ويتم تفعيلها لأي حدث مطابق event.
إنشاء ويب هوك
يمكنك إنشاء نقاط نهاية باستخدام حزمة تطوير البرامج (SDK) أو واجهة برمجة تطبيقات REST.
ملاحظة مهمة: عند إنشاء ويب هوك، تعرض واجهة برمجة التطبيقات سرًا للتوقيع مرة واحدة فقط. عليك تخزين هذا السر بشكل آمن (مثلًا في متغيّرات البيئة) للتحقّق من التوقيعات لاحقًا. إذا فقدت سر التوقيع، عليك تدويره rotate.
Python
from google import genai
client = genai.Client()
webhook = client.webhooks.create(
name="MyBatchWebhook",
subscribed_events=["batch.completed", "batch.failed"],
uri="https://my-api.com/gemini-callback",
)
# Store webhook.new_signing_secret securely
webhook_secret = webhook.new_signing_secret
print(f"Created webhook: {webhook.name}, {webhook.id}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function createWebhook() {
const webhook = await client.webhooks.create({
name: "MyBatchWebhook",
subscribed_events: ["batch.completed", "batch.failed"],
uri: "https://my-api.com/gemini-callback",
});
// Store webhook.signingSecret securely
const webhookSecret = webhook.new_signing_secret;
console.log(`Created webhook: ${webhook.name}, ${webhook.id}`);
}
createWebhook();
REST
curl -X POST \
"https://generativelanguage.googleapis.com/v1/webhooks" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GOOGLE_API_KEY" \
-d '{
"name": "MyBatchWebhook",
"uri": "https://my-api.com/gemini-callback",
"subscribed_events": ["batch.completed", "batch.failed"]
}'
للحصول على تفاصيل حول إعداد خادمك لتلقّي البيانات، يُرجى الاطّلاع على قسم معالجة طلبات الويب هوك.
الحصول على ويب هوك
يمكنك استرداد تفاصيل حول ويب هوك معيّنة من خلال اسم المورد.
Python
from google import genai
client = genai.Client()
webhook = client.webhooks.get(id="<your_webhook_id>")
print(f"Webhook: {webhook.name}")
print(f"URI: {webhook.uri}")
print(f"Events: {webhook.subscribed_events}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI(); // Assumes process.env.GEMINI_API_KEY is set
async function getWebhook() {
const webhook = await client.webhooks.get("<your_webhook_id>");
console.log(`Webhook: ${webhook.name}`);
console.log(`URI: ${webhook.uri}`);
console.log(`Events: ${webhook.subscribed_events}`);
}
getWebhook();
REST
curl -X GET \
"https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>" \
-H "x-goog-api-key: $GOOGLE_API_KEY"
سرد الويب هوك
يمكنك سرد جميع الويب هوك التي تم ضبطها للمشروع الحالي، مع إمكانية استخدام الترقيم الاختياري للصفحات.
Python
from google import genai
client = genai.Client()
webhooks = client.webhooks.list()
for wh in webhooks:
print(f"{wh.id}: {wh.name} -> {wh.uri}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function listWebhooks() {
const webhooks = await client.webhooks.list();
for (const wh of webhooks) {
console.log(`${wh.id}: ${wh.name} -> ${wh.uri}`);
}
}
listWebhooks();
REST
curl -X GET \
"https://generativelanguage.googleapis.com/v1/webhooks" \
-H "x-goog-api-key: $GOOGLE_API_KEY"
تعديل ويب هوك
يمكنك تعديل خصائص ويب هوك حالية، مثل الاسم المعروض أو عنوان URI المستهدَف أو الأحداث التي تم الاشتراك فيها.
Python
from google import genai
client = genai.Client()
updated_webhook = client.webhooks.update(
id="<your_webhook_id>",
subscribed_events=["batch.completed", "batch.failed", "batch.cancelled"],
)
print(f"Updated webhook: {updated_webhook.name}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function updateWebhook() {
const updatedWebhook = await client.webhooks.update(
"<your_webhook_id>",
{
subscribed_events: ["batch.completed", "batch.failed", "batch.cancelled"],
}
);
console.log(`Updated webhook: ${updatedWebhook.name}`);
}
updateWebhook();
REST
curl -X PATCH \
"https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GOOGLE_API_KEY" \
-d '{
"subscribed_events": ["batch.completed", "batch.failed", "batch.cancelled"]
}'
حذف ويب هوك
يمكنك إزالة نقطة نهاية ويب هوك من المشروع. وسيؤدي ذلك إلى إيقاف عمليات تسليم الأحداث المستقبلية إلى نقطة النهاية هذه.
Python
from google import genai
client = genai.Client()
client.webhooks.delete(id="<your_webhook_id>")
print("Webhook deleted.")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function deleteWebhook() {
await client.webhooks.delete("<your_webhook_id>");
console.log("Webhook deleted.");
}
deleteWebhook();
REST
curl -X DELETE \
"https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>" \
-H "x-goog-api-key: $GOOGLE_API_KEY"
تدوير سر التوقيع
يمكنك تدوير سر التوقيع لويب هوك. ويمكنك تحديد ما إذا كان سيتم إبطال الأسرار النشطة سابقًا على الفور أو بعد فترة سماح مدتها 24 ساعة.
ملاحظة مهمة: يتم عرض سر التوقيع الجديد مرة واحدة فقط في وقت التدوير. عليك تخزينه بشكل آمن قبل تعديل منطق التحقّق.
Python
from google import genai
from google.genai import types
client = genai.Client()
response = client.webhooks.rotate_signing_secret(
id="<your_webhook_id>",
revocation_behavior="REVOKE_PREVIOUS_SECRETS_AFTER_H24",
)
# Store response.secret securely, then update your server's verification config
print("New signing secret generated. Update your server configuration.")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function rotateSigningSecret() {
const response = await client.webhooks.rotateSigningSecret(
"<your_webhook_id>",
{
revocation_behavior: "REVOKE_PREVIOUS_SECRETS_AFTER_H24",
}
);
// Store response.secret securely, then update your server's verification config
console.log("New signing secret generated. Update your server configuration.");
}
rotateSigningSecret();
REST
curl -X POST \
"https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>/rotate_secret" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GOOGLE_API_KEY" \
-d '{
"revocation_behavior": "REVOKE_PREVIOUS_SECRETS_AFTER_H24"
}'
معالجة طلبات الويب هوك على خادم
عند وقوع حدث اشتركت فيه، سيتلقّى رابط ويب هوك الخاص بك طلب HTTP POST. يجب أن تستجيب نقطة النهاية برمز حالة 2xx في غضون بضع ثوانٍ لتجنُّب إعادة المحاولة. لضمان التسليم، تعيد Gemini API تلقائيًا محاولة إرسال الطلبات التي فشلت لمدة 24 ساعة باستخدام التراجع الدليلي.
تتّبع Gemini بدقة مواصفات الويب هوك العادية لـ عناوين الأمان. عليك التحقّق من الحمولة على خادمك باستخدام توقيعات العناوين المُوقَّعة وسر التوقيع الثابت المخزَّن. يمكنك الاطّلاع على قسم غلاف الويب هوك للحصول على معلومات الحمولة.
إليك مثال على استخدام Flask للمستمع HTTP:
Python
# pip install flask standardwebhooks
import os
from flask import Flask, request, jsonify
# Standard verification wrapper for Standard Webhook Headers
from standardwebhooks.webhooks import Webhook, WebhookVerificationError
app = Flask(__name__)
SIGNING_SECRET = os.environ.get('WEBHOOK_SIGNING_SECRET')
@app.route('/gemini-callback', methods=['POST'])
def gemini_callback():
payload = request.get_data(as_text=True)
headers = request.headers
try:
wh = Webhook(SIGNING_SECRET)
event = wh.verify(payload, headers)
except WebhookVerificationError as e:
return jsonify({"error": "Signature invalid"}), 400
# Process thin payload contents
if event.get("type") in ("batch.completed", "video.generated"):
uri = event['data']['output_file_uri']
print(f"Batch finished! Results at: {uri}")
return jsonify({"status": "received"}), 200
if __name__ == "__main__":
app.run(port=8000)
JavaScript
// npm install standardwebhooks
import { Webhook } from "standardwebhooks";
import express from "express";
const app = express();
const client = new GoogleGenAI({ webhookSecret: process.env.WEBHOOK_SIGNING_SECRET });
// Don't use express.json() because signature verification needs the raw text body
app.use(express.text({ type: "application/json" }));
app.post("/gemini-callback", async (req, res) => {
const payload = await req.text();
const headers: Record<string, string> = {};
req.headers.forEach((value, key) => {
headers[key] = value;
});
try {
const wh = new Webhook(process.env.WEBHOOK_SIGNING_SECRET);
const event = wh.verify(payload, headers) as Record<string, any>;
// Process thin payload contents
if (event.type === "batch.completed" || event.type === "video.generated") {
const uri = event.data.output_file_uri;
console.log(`Job finished! Results at: ${uri}`);
}
res.status(200).json({ status: "received" });
} catch (e) {
console.error("Webhook verification failed:", e);
res.status(400).send("Invalid signature");
}
});
app.listen(8000, () => {
console.log("Webhook server is running on port 8000");
});
الويب هوك الديناميكية
تسمح لك الويب هوك الديناميكية بربط نقطة نهاية ويب هوك بـ إعداد طلب معيّن، ما يجعلها مثالية لقوائم انتظار تنسيق الوكلاء. تستخدِم الويب هوك الديناميكية توقيعات JWKS غير المتماثلة للمفتاح العام بدلاً من الأسرار المتماثلة.
إرسال طلب ديناميكي
يمكنك إضافة webhook_config عند تفعيل مهمة غير متزامنة (مثل إنشاء دفعة).
Python
from google import genai
from google.genai import types
client = genai.Client()
file_batch_job = client.batches.create(
model="gemini-3-flash-preview",
src="files/uploaded_file_id",
config={
"display_name": "My Setup",
"webhook_config": {
"uris": ["https://my-api.com/gemini-webhook-dynamic"],
"user_metadata":{"job_group": "nightly-eval", "priority": "high"}
}
}
)
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function createBatchWithWebhook() {
const fileBatchJob = await client.batches.create({
model: "gemini-3-flash-preview",
src: "files/uploaded_file_id",
config: {
displayName: "My Setup",
webhookConfig: {
uris: ["https://my-api.com/gemini-webhook-dynamic"],
user_metadata: {"job_group": "nightly-eval", "priority": "high"}
},
},
});
}
REST
curl -X POST \
"https://generativelanguage.googleapis.com/v1/models/gemini-3-flash-preview:batchCreate" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GOOGLE_API_KEY" \
-d '{
"src": "files/uploaded_file_id",
"config": {
"display_name": "My Setup",
"webhook_config": {
"uris": ["https://my-api.com/gemini-webhook-dynamic"],
"user_metadata": {"job_group": "nightly-eval", "priority": "high"}
}
}
}'
التحقّق من التوقيعات الديناميكية (JWKS)
تُصدر طلبات الويب هوك الديناميكية توقيع رمز JSON المميّز للويب (JWT). على المستمع استخراج التوقيع والتحقّق منه باستخدام نقاط نهاية الشهادات العامة من Google .
Python
import jwt
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
# Google public cert list endpoint
JWKS_URI = "https://generativelanguage.googleapis.com/.well-known/jwks.json"
def load_google_public_key(kid):
response = requests.get(JWKS_URI).json()
for key_item in response.get('keys', []):
if key_item.get('kid') == kid:
# Convert JWK to Cert wrapper
return jwt.algorithms.RSAAlgorithm.from_jwk(key_item)
return None
@app.route('/gemini-webhook-dynamic', methods=['POST'])
def dynamic_handler():
payload = request.get_data(as_text=True)
headers = request.headers
token = headers.get('Webhook-Signature')
if not token:
return jsonify({"error": "No signature header"}), 400
try:
# Extract kid from JWT header
unverified_headers = jwt.get_unverified_header(token)
pub_key = load_google_public_key(unverified_headers.get('kid'))
if not pub_key:
return jsonify({"error": "Key cert not found"}), 400
# Verify Signature against expected audience (e.g., your project client ID)
event = jwt.decode(
token,
pub_key,
algorithms=["RS256"],
audience="your-configured-audience"
)
except Exception as e:
return jsonify({"error": "Invalid Dynamic signature", "details": str(e)}), 400
print("Verified Dynamic payload success.")
return jsonify({"status": "received"}), 200
JavaScript
import { GoogleGenAI } from "@google/genai";
import express from "express";
import jwt from "jsonwebtoken";
import jwksClient from "jwks-rsa";
const app = express();
app.use(express.text({ type: 'application/json' }));
const client = jwksClient({
jwksUri: "https://generativelanguage.googleapis.com/.well-known/jwks.json"
});
function getKey(header, callback) {
client.getSigningKey(header.kid, (err, key) => {
const signingKey = key.getPublicKey();
callback(null, signingKey);
});
}
app.post('/gemini-webhook-dynamic', (req, res) => {
const token = req.headers['webhook-signature'];
if (!token) {
return res.status(400).json({ error: "No signature header" });
}
jwt.verify(
token,
getKey,
{
algorithms: ["RS256"],
audience: "your-configured-audience"
},
(err, decoded) => {
if (err) {
return res.status(400).json({ error: "Invalid Dynamic signature", details: err.message });
}
console.log("Verified Dynamic payload success.");
res.status(200).json({ status: "received" });
}
);
});
غلاف الويب هوك
لتجنُّب ازدحام النطاق الترددي، تستخدِم الويب هوك في Gemini نموذج حمولة صغيرة لتسليم البيانات. وترسل عمليات التسليم لقطة تحتوي على تفاصيل الحالة ومؤشرات إلى النتائج، بدلاً من ملف الإخراج الأولي نفسه.
في ما يلي مثال على تنسيق الحمولة:
{
"type": "batch.completed",
"version": "v1",
"timestamp": "2026-01-22T12:00:00Z",
"data": {
"id": "batch_123456",
"output_file_uri": "gs://my-bucket/results.jsonl",
"error_count": 0
}
}
مرجع كتالوج الأحداث
يتم تفعيل الأحداث التالية للوظائف المتوافقة:
| نوع الحدث | Trigger | عنصر الحمولة (data) |
|---|---|---|
batch.succeeded |
اكتملت المعالجة بنجاح. | id وoutput_file_uri |
batch.cancelled |
ألغى المستخدم الطلب | id |
batch.expired |
لم تتم معالجة الدفعة (اكتملت) خلال فترة 24 ساعة | id |
batch.failed |
فشلت مهمة الدفعة (حدث خطأ في النظام أو التحقّق من الصحة). | id وerror_code وerror_message |
interaction.requires_action |
استدعاء الدالة، على المستخدم اتّخاذ إجراء | id |
interaction.completed |
اكتملت العملية الطويلة الأمد (LRO) في واجهة برمجة التطبيقات Interactions API بنجاح | id |
interaction.failed |
فشلت العملية الطويلة الأمد (LRO) في واجهة برمجة التطبيقات Interactions API (حدث خطأ في النظام أو التحقّق من الصحة). | id وerror_code وerror_message |
interaction.cancelled |
تم إلغاء العملية الطويلة الأمد (LRO) في واجهة برمجة التطبيقات Interactions API | id |
video.generated |
اكتملت العملية الطويلة الأمد (LRO) لإنشاء الفيديو. | file_id وvideo_uri |
أفضل الممارسات
لضمان عملية موثوقة وقابلة للتوسّع:
- التحقّق الدقيق من الحماية من إعادة التشغيل: تحمل جميع الطلبات
webhook-timestampعنوان. عليك دائمًا التحقّق من هذا الطابع الزمني على طبقة إعدادات الخادم لرفض الحمولات التي يزيد عمرها عن 5 دقائق (للتخفيف من هجمات إعادة التشغيل). - المعالجة غير المتزامنة: عليك الردّ باستخدام
2xx OKفور رصد توقيع صالح ، ووضع عمليات التحليل في قائمة الانتظار داخليًا. ستؤدي فترات الانتظار الطويلة للمستمع إلى تفعيل دورة إعادة محاولة التسليم. - معالجة إزالة التكرار: تُسلّم الويب هوك العادية البيانات "مرة واحدة على الأقل". استخدِم عنوان
webhook-idالمتسق لمعالجة أي تكرارات محتملة في تدفقات الازدحام الأعلى.
ما هي الخطوات التالية؟
- واجهة برمجة التطبيقات Batch API: يمكنك استخدام الويب هوك لأتمتة نقاط النهاية ذات الحجم الكبير.