وب هوک ها

وب‌هوک‌ها به API مربوط به Gemini اجازه می‌دهند تا هنگام تکمیل عملیات ناهمزمان یا عملیات طولانی‌مدت (LRO) اعلان‌های بلادرنگ را به سرور شما ارسال کند. این امر جایگزین نیاز به نظرسنجی از API برای به‌روزرسانی وضعیت می‌شود و تأخیر و سربار را کاهش می‌دهد.

وب‌هوک‌ها برای عملیاتی مانند کارهای دسته‌ای ، تعاملات و تولید ویدیو در دسترس هستند.

چگونه کار می‌کند؟

به جای اینکه مرتباً از GET /operations برای بررسی اتمام یک کار استفاده کنید، می‌توانید Gemini API Webhooks را طوری پیکربندی کنید که بلافاصله پس از وقوع یک رویداد، یک درخواست HTTP POST به آدرس اینترنتی شنونده شما ارسال کند.

رابط برنامه‌نویسی کاربردی Gemini از دو روش برای پیکربندی وب‌هوک‌ها پشتیبانی می‌کند:

  • وب‌هوک‌های استاتیک : نقاط پایانی سطح پروژه که با رابط برنامه‌نویسی Gemini WebhookService پیکربندی شده‌اند. برای یکپارچه‌سازی‌های جهانی (مثلاً اطلاع‌رسانی به Slack، همگام‌سازی پایگاه داده و غیره) مناسب هستند.
  • وب‌هوک‌های پویا : سطح درخواست، ارسال یک URL وب‌هوک را در پیکربندی یک فراخوانی شغل خاص لغو می‌کند. ایده‌آل برای مسیریابی مشاغل خاص به نقاط انتهایی اختصاصی.

وب‌هوک‌های استاتیک

وب‌هوک‌های استاتیک برای کل پروژه ثبت می‌شوند و برای هر رویداد منطبق، فعال می‌شوند.

ایجاد یک وب هوک

شما می‌توانید با استفاده از SDK یا REST API، نقاط پایانی (endpoints) ایجاد کنید.

مهم : هنگام ایجاد یک وب‌هوک، API فقط یک بار رمز امضا را برمی‌گرداند. شما باید این را به طور ایمن (مثلاً در متغیرهای محیطی خود) ذخیره کنید تا بعداً امضاها را تأیید کنید. اگر رمز امضا را گم کنید، باید آن را بچرخانید .

پایتون

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}")

جاوا اسکریپت

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();

استراحت

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"]
  }'

برای جزئیات بیشتر در مورد تنظیم سرور خود برای دریافت داده‌ها، به بخش مدیریت درخواست‌های وب‌هوک مراجعه کنید.

یک وب هوک دریافت کنید

جزئیات مربوط به یک وب‌هوک خاص را با نام منبع آن بازیابی کنید.

پایتون

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}")

جاوا اسکریپت

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();

استراحت

curl -X GET \
  "https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>" \
  -H "x-goog-api-key: $GOOGLE_API_KEY"

فهرست کردن وب هوک‌ها

تمام وب‌هوک‌های پیکربندی‌شده برای پروژه فعلی را به همراه صفحه‌بندی اختیاری فهرست کنید.

پایتون

from google import genai

client = genai.Client()

webhooks = client.webhooks.list()

for wh in webhooks:
    print(f"{wh.id}: {wh.name} -> {wh.uri}")

جاوا اسکریپت

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();

استراحت

curl -X GET \
  "https://generativelanguage.googleapis.com/v1/webhooks" \
  -H "x-goog-api-key: $GOOGLE_API_KEY"

به‌روزرسانی یک وب‌هوک

ویژگی‌های یک وب‌هوک موجود مانند نام نمایشی، آدرس هدف یا رویدادهای مشترک را به‌روزرسانی کنید.

پایتون

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}")

جاوا اسکریپت

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();

استراحت

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"]
  }'

حذف یک وب هوک

یک نقطه پایانی وب‌هوک را از پروژه حذف کنید. این کار تحویل رویدادهای آینده به آن نقطه پایانی را متوقف می‌کند.

پایتون

from google import genai

client = genai.Client()

client.webhooks.delete(id="<your_webhook_id>")

print("Webhook deleted.")

جاوا اسکریپت

import { GoogleGenAI } from "@google/genai";

const client = new GoogleGenAI();

async function deleteWebhook() {
  await client.webhooks.delete("<your_webhook_id>");

  console.log("Webhook deleted.");
}

deleteWebhook();

استراحت

curl -X DELETE \
  "https://generativelanguage.googleapis.com/v1/webhooks/<your_webhook_id>" \
  -H "x-goog-api-key: $GOOGLE_API_KEY"

چرخاندن یک راز امضا

رمز امضای یک وب‌هوک را بچرخانید. می‌توانید پیکربندی کنید که آیا رمزهای فعال قبلی بلافاصله یا پس از یک دوره مهلت ۲۴ ساعته لغو شوند.

مهم : رمز امضای جدید فقط یک بار در زمان چرخش بازگردانده می‌شود. قبل از به‌روزرسانی منطق تأیید خود، آن را به طور ایمن ذخیره کنید.

پایتون

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.")

جاوا اسکریپت

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();

استراحت

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"
  }'

مدیریت درخواست‌های وب‌هوک روی سرور

وقتی رویدادی اتفاق می‌افتد که شما در آن مشترک هستید، URL وب‌هوک شما یک درخواست HTTP POST دریافت می‌کند. نقطه پایانی شما باید ظرف چند ثانیه با یک کد وضعیت 2xx پاسخ دهد تا از تلاش مجدد جلوگیری شود. برای اطمینان از تحویل، API Gemini به طور خودکار درخواست‌های ناموفق را به مدت 24 ساعت با استفاده از روش بازگشت نمایی (exponential backoff) دوباره امتحان می‌کند.

Gemini به شدت از مشخصات استاندارد Webhooks برای هدرهای امنیتی پیروی می‌کند. با استفاده از امضاهای هدر امضا شده و رمز امضای استاتیک ذخیره شده، بار داده را روی سرور خود تأیید کنید. برای اطلاعات بار داده به بخش پوشش Webhook مراجعه کنید.

در اینجا مثالی از استفاده از Flask برای شنونده HTTP آورده شده است:

پایتون

# 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)

جاوا اسکریپت

// 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 اضافه کنید.

پایتون

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"}
        }
    }
)

جاوا اسکریپت

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"}
      },
    },
  });
}

استراحت

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 Web Token (JWT) را منتشر می‌کنند. شنونده شما باید امضا را استخراج کرده و آن را با استفاده از نقاط پایانی گواهی عمومی گوگل تأیید کند.

پایتون

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

جاوا اسکریپت

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 از یک مدل payload نازک برای تحویل داده‌ها استفاده می‌کنند. تحویل‌ها به جای خود فایل خروجی خام، یک snapshot حاوی جزئیات وضعیت و اشاره‌گرهایی به نتایج ارسال می‌کنند.

در اینجا یک نمونه از قالب بارگذاری آمده است:

{
  "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
  }
}

مرجع کاتالوگ رویداد

رویدادهای زیر برای پشتیبانی از مشاغل فعال می‌شوند:

نوع رویداد ماشه کالای بار ( 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 در تعاملات API موفق شد id
interaction.failed LRO در تعاملات API ناموفق بود (خطای سیستم یا اعتبارسنجی). id ، error_code ، error_message
interaction.cancelled لغو تعاملات API در LRO id
video.generated تولید ویدیو از LRO به پایان رسید. file_id ، video_uri

بهترین شیوه‌ها

برای اطمینان از عملکرد قابل اعتماد و مقیاس‌پذیر:

  • بررسی دقیق محافظت در برابر تکرار : همه درخواست‌ها دارای یک هدر webhook-timestamp هستند. همیشه این timestamp را در لایه پیکربندی سرور خود اعتبارسنجی کنید تا بارهای داده قدیمی‌تر از ۵ دقیقه را رد کنید (برای کاهش حملات تکرار).
  • پردازش ناهمزمان : بلافاصله پس از تشخیص امضای معتبر، با 2xx OK پاسخ دهید و عملیات تجزیه را به صورت داخلی در صف قرار دهید. زمان‌های طولانی انتظار شنونده، چرخه تلاش مجدد تحویل را آغاز می‌کند.
  • مدیریت حذف داده‌های تکراری : وب‌هوک‌های استاندارد «حداقل یک بار» این کار را انجام می‌دهند. از هدر webhook-id ثابت برای مدیریت داده‌های تکراری بالقوه در جریان‌های تراکم بالاتر استفاده کنید.

بعدش چی؟

  • API دسته‌ای : از وب‌هوک‌ها برای خودکارسازی نقاط پایانی با حجم بالا استفاده کنید.