GEMINI LABJP
MODEL — Gemma 4 is now available in Google AI Studio and the Gemini APIAGENT — Managed Agents enter public preview, running autonomous agents in isolated sandboxesMODEL — Gemini 3.5 Flash reaches GA for agentic and coding tasksSTUDIO — Google AI Studio adds Workspace integrations and one-click deploy to Cloud RunSTUDIO — You can now build native Android apps in the AI Studio build tabMIGRATE — Gemini Code Assist IDE extensions and CLI ended for individuals on June 18; move to AntigravityMODEL — Gemma 4 is now available in Google AI Studio and the Gemini APIAGENT — Managed Agents enter public preview, running autonomous agents in isolated sandboxesMODEL — Gemini 3.5 Flash reaches GA for agentic and coding tasksSTUDIO — Google AI Studio adds Workspace integrations and one-click deploy to Cloud RunSTUDIO — You can now build native Android apps in the AI Studio build tabMIGRATE — Gemini Code Assist IDE extensions and CLI ended for individuals on June 18; move to Antigravity
Articles/API / SDK
API / SDK/2026-07-03Advanced

A Webhook Is a Claim, Not a Fact — Three Layers of Defense for Your Gemini Webhooks Endpoint

Your Gemini Webhooks receiver is a public URL, which means forged events, replays, and duplicate deliveries are all on the table. This walkthrough builds a three-layer defense — reachability checks, dedupe, and a lightweight handler that re-fetches truth from the API — with working FastAPI and SQLite code.

Gemini API163Webhooks2security11idempotency3automation48

Premium Article

After I moved my Gemini Batch monitoring from polling to Webhooks, I reread the receiving code and stopped cold. Somewhere along the way I had assumed that only Google would ever POST to that URL. In reality, a webhook receiver is a public internet endpoint. Anyone who finds it can send it any JSON they like.

Webhook receivers in indie projects tend to start life as "whatever works." I would have shipped mine wide open too, if I hadn't spent years operating Stripe webhooks for the membership billing behind my Dolice Labs sites. In the payments world, "trusting the webhook too much" is a textbook failure mode, and the discipline that grew around it transfers directly to Gemini automation pipelines. Here is the three-layer defense I ended up with, along with code that runs.

What actually goes wrong with an unguarded receiver

Before designing defenses, it helps to name the failure modes. If your receiver believes whatever JSON arrives, three things can happen.

Forged events. An attacker — or simply a misconfigured system somewhere else — POSTs a payload dressed up as a "job completed" notification. If the receiver takes it at face value and kicks off downstream work, you end up fetching results that don't exist, saving empty artifacts, or pushing unfinished data into a publish step. No malice is required: staging notifications landing on a production endpoint is a real, mundane accident.

Replays. A legitimate event you already handled arrives again. Deliberate replay is one cause, but ordinary delivery retries produce the same effect. The downstream side runs twice, burning compute or overwriting data you already published.

Duplicate processing. If your handler responds slowly, the delivery side times out and resends. The heavier the synchronous work inside your handler, the slower it responds, the more retries pile up — a self-reinforcing loop.

Note that the last two happen without any attacker at all. Defending against malice and defending against retries land in almost the same code. I covered event ordering separately in A Finished Gemini Job Flipped Back to 'Running' — Stopping Out-of-Order Webhooks with Monotonic State Apply; this piece focuses on the receiving endpoint itself.

The principle — a payload is a notification, not a fact

One rule underpins all three layers: never update state from the webhook payload.

Treat every incoming event as a hint that "something may have changed," and always re-fetch the actual state from the Gemini API. Even if the payload says state: succeeded, that is not a reason to run downstream work. You run it only when your own query confirms completion. This single move structurally defuses forged events: the only thing an attacker can fabricate is a reason to check, while the facts live solely on the API side.

This is a direct continuation of the reconciliation design I wrote up in When a Deploy Drops the Webhook: Reconciling Gemini Long-Running Operations with a Belt-and-Suspenders Design. If you already reconcile against the API to catch dropped events, the very same query logic doubles as your "don't trust the payload" mechanism. You barely need any new parts.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You'll be able to harden a wide-open webhook receiver against forged events, replays, and duplicate processing with three inexpensive layers
You can implement the 'notification vs. fact' separation — never trusting the payload, always re-fetching state from the API — with working FastAPI and SQLite code
You'll take away a cost-vs-benefit table for each defense, adapted from payment-webhook discipline to Gemini automation pipelines
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API / SDK2026-07-01
Locking Down a Gemini API Key on Servers Whose IP Keeps Changing — Restrictions for Headless Automation
After unrestricted keys started getting blocked, headless server automation whose egress IP changes every run can't cleanly use HTTP referrer, app restrictions, or an IP allowlist. Do you get by with API restrictions alone, funnel egress through a fixed IP, or move server workloads off API keys onto Vertex service-account auth? A decision framework and working code, without taking your pipelines down.
API / SDK2026-06-24
When a Deploy Drops the Webhook: Reconciling Gemini Long-Running Operations with a Belt-and-Suspenders Design
Even after you move from polling to Webhooks, events still get dropped during deploys and transient 5xx windows. Here is how I double up Gemini long-running operations with an operation ledger and a low-frequency reconciliation poller so a missing terminal event never goes unnoticed.
API / SDK2026-04-16
Google Sheets API × Gemini API: A Python Data Pipeline — No Apps Script Required
Learn how to build a fully Python-based pipeline that reads data from Google Sheets, processes it with Gemini API, and writes results back — without touching Apps Script. Covers service account auth, structured output, and rate limit handling.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →