Google adds webhooks to the Gemini API. Batch API just got a lot less annoying.
This week Google shipped event-driven webhooks for the Gemini API, rolling them out to all developers. Long-running AI work doesn't fit into a synchronous request-response loop, and polling for completion is a bad use of everyone's compute.
The main use case is the Batch API, where jobs can take minutes or hours to finish. But the rollout also covers the Interactions API (multi-turn agent conversations with human-in-the-loop function calling) and video generation.
Here's what shipped, what makes Gemini's implementation different, and where the reliability work lives.
What Google shipped
Gemini webhooks follow the Standard Webhooks specification, so webhook-id / webhook-timestamp / webhook-signature headers may be familiar. Configuration is currently API-only (there's no AI Studio UI for endpoint management at launch) and Google has done something none of its peers have: shipped two parallel webhook configuration models with two different signing schemes.
Static webhooks are project-level endpoints registered once via the WebhookService API. They apply to all matching events in the project and are signed with HMAC-SHA256 using a shared secret returned at creation time.
Dynamic webhooks are configured per-job by passing a webhook_config object inside an individual API call — for example, when creating a Batch job. They're signed with RS256 JWTs that Google's identity service issues, which you verify against the Gemini JWKS endpoint. They also carry an arbitrary user_metadata object that Gemini echoes back in the webhook payload — useful for routing or correlating events to the originating job.
The split is genuinely useful: static is right for global integrations (a Slack notifier, an audit logger), dynamic is right for routing specific jobs to dedicated workers or fan-out queues. But it does mean any production handler that supports both styles needs verification logic for two distinct cryptographic models.
The events on offer
Gemini emits webhooks across three product surfaces:
- Batch API —
batch.succeeded,batch.failed,batch.cancelled,batch.expired. The succeeded payload includes ags://bucket URI pointing at the result file in Google Cloud Storage. - Interactions API —
interaction.requires_action(when a function call is pending and your agent needs to step in),interaction.completed,interaction.failed,interaction.cancelled. - Video generation —
video.generated, with the file ID and video URI in the payload.
The payloads are deliberately thin: just enough to identify the resource. To actually use the result, you read the GCS URI or call back into the API.
What this unlocks
The use cases are where the announcement actually starts to bite, because webhooks turn Gemini from a request-response API into something that can drive event-driven architectures:
- A nightly Batch job processing thousands of prompts pushes its
gs://result URI to your data pipeline the moment it lands, instead of you pollingGET /operationsevery 30 seconds for an hour. - An Interactions session pauses on
interaction.requires_action, fires a webhook that drops a Slack approval request to a human reviewer, and resumes when they decide. - A video generation job notifies your CDN to pre-warm a cache and your app to email the user as soon as the video is ready.
- A Batch failure event pages on-call with the failure reason and triggers a retry routine — without anyone having to write a polling loop with backoff.
- The
user_metadatafield on dynamic webhooks lets a multi-tenant agent platform tag each job with its tenant and route the resulting events to the right downstream queue without an extra database lookup.
The pattern is what every webhook integration does, just with higher per-event stakes because each event represents an AI workload, not a row update.
Where this gets messy
Google's reliability promises track the rest of the industry. Delivery is at-least-once with exponential backoff up to 24 hours. Ordering isn't guaranteed. Receivers should respond within a few seconds and queue heavier processing internally. The webhook-id header is your idempotency key — Google explicitly says duplicates can occur under congestion.
A few Gemini-specific details worth noting:
- The signing secret for static webhooks is shown only once. Lose it and you have to delete and recreate the endpoint.
- Secret rotation has a built-in 24-hour grace period via the
REVOKE_PREVIOUS_SECRETS_AFTER_H24revocation behaviour — more developer-friendly than several competitors that require you to manage overlap manually. - Output is a
gs://URI, not an HTTPS link. Your handler needs Google Cloud credentials to fetch the result file. - No first-party CLI for local development. The cookbook quickstart walks through ngrok. As with OpenAI, this is a gap that third-party tooling fills.
You can solve all of this with code, and plenty of teams will. We argue that most webhook agents don't need a workflow engine — what they actually need is a durable queue, idempotent delivery, and retries with backoff. When you do need real workflow state, the gateway and the runtime do different jobs (gateways own ingress, runtimes own execution) and starting with the gateway keeps your options open.
How Hookdeck helps
Hookdeck Event Gateway sits between Gemini and your application, handling the operational layer so your handler only ever sees verified, deduplicated events.
For static webhooks, Event Gateway verifies the HMAC at the edge using Standard Webhooks rules. For dynamic webhooks, Event Gateway verifies the RS256 JWT against Google's JWKS endpoint. Either way, your downstream handler stops needing two cryptographic verification paths.
Beyond verification, Event Gateway dedupes on webhook-id so duplicate deliveries from Google's at-least-once retries don't cause double-processing, queues every event durably so a slow downstream consumer doesn't trip the 5-minute freshness window, fans out one event to multiple subscribers (handy when a batch.succeeded needs to update a database and notify Slack and warm a cache), and replays anything that failed when you fix the bug.
For local development, the Hookdeck CLI gives you a stable public HTTPS URL, full request inspection, and one-key event replay — directly replacing ngrok in the cookbook quickstart and letting you iterate on a webhook handler without re-running long Batch jobs every time.
Webhooks turning the Gemini Batch API from a polling loop into a push primitive is a real shift, and the same boring infrastructure problems you'd solve for Stripe or GitHub apply here too — just with the wrinkle of two signing schemes to verify and Google Cloud credentials to fetch results.
If you're wiring Gemini into your stack, start with Event Gateway. You can decide later whether you also need a runtime.