GEMINI LABJP
PRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration windowPRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration window
Articles/API / SDK
API / SDK/2026-07-01Advanced

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.

Gemini API190API key2security11automation51Vertex AI11

Premium Article

When unrestricted keys started getting blocked, the first thing that bit me wasn't a browser-facing key — it was the server-side scheduled jobs running where nobody is watching. As an indie developer running update pipelines across several sites, most of that work runs headless: it spins up on a near-disposable execution environment, does its thing, and disappears. Build it that way and the source IP of your requests changes on every run.

That's exactly where this key-restriction change hurts. A browser has a referrer; a mobile app has a package name and signature. A headless server job has none of those. The only application restriction left is an IP allowlist — and that one is a trap. Set it, and the next run arrives from a different IP and blocks itself. A very silly way to take your own pipeline down.

This article focuses narrowly on that headless case: how to make a key restriction actually stick. The short version, which is where I landed myself: satisfy the floor with an API restriction for now, and if you're in it for the long haul, take server workloads off API keys and move to service-account auth. Here's why, and how to move without downtime.

Why application restrictions don't fit server automation

A Gemini API key takes restrictions in two layers. One is the API restriction — which APIs the key may call. The other is the application restriction — where the request may come from, in four flavors: HTTP referrer, IP address, Android app, and iOS app.

The problem is that all four application restrictions assume the caller is stably identifiable. Browsers have referrers; mobile apps have package names and signatures. A headless server job has none of them. That leaves IP restriction, and IP is the awkward one:

  • CI, serverless, and disposable execution environments get assigned a different node each run, so the egress IP changes.
  • With no fixed IP, there's no stable value to write into the allowlist in the first place.
  • Allowing a wide CIDR to compensate defeats the point of restricting at all.

So for headless work you're naturally down to three choices: give up on application restrictions and satisfy the floor with an API restriction, funnel egress through a fixed IP so an IP restriction can work, or step off the API-key mechanism entirely. Let's take them in order.

First, measure what you have

Before choosing, find out what's actually attached to each key. When you span multiple projects, pulling the list through the API Keys API is far more reliable than eyeballing the console. This inventories every key and its restriction state, authenticating with a service account (below) or your gcloud auth application-default login credentials.

# Inventory each key's restriction state (uses google-cloud-api-keys)
# pip install google-cloud-api-keys
from google.cloud import api_keys_v2
 
def audit_keys(project_id: str) -> None:
    client = api_keys_v2.ApiKeysClient()
    parent = f"projects/{project_id}/locations/global"
 
    for key in client.list_keys(parent=parent):
        restrictions = key.restrictions
        api_targets = list(restrictions.api_targets) if restrictions else []
 
        # Which application restriction, if any
        app = "none"
        if restrictions:
            if restrictions.browser_key_restrictions.allowed_referrers:
                app = "referrer"
            elif restrictions.server_key_restrictions.allowed_ips:
                app = "ip"
            elif restrictions.android_key_restrictions.allowed_applications:
                app = "android"
            elif restrictions.ios_key_restrictions.allowed_bundle_ids:
                app = "ios"
 
        api_ok = "restricted" if api_targets else "ALL-APIs"
        flag = "  <-- unrestricted (block candidate)" if app == "none" and not api_targets else ""
        print(f"{key.display_name:<28} app={app:<9} api={api_ok}{flag}")
 
audit_keys("your-project-id")
# Example output:
# cron-gemilab-pipeline        app=none      api=ALL-APIs  <-- unrestricted (block candidate)
# web-demo-key                 app=referrer  api=restricted

Keys that are app=none and api=ALL-APIs are the most exposed to the block. If a key your headless jobs use shows up there, address it with one of the following.

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
If you've been stuck on 403s from a headless environment whose IP changes each run, you'll be able to pick the restriction that actually fits your setup
You'll compare three options — API restriction only, fixed-IP egress, and Vertex service-account auth — by cost and operational weight, and decide
You'll get a step-by-step way to move a running server workload off API keys onto OAuth auth without downtime
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-03
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.
API / SDK2026-07-09
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.
API / SDK2026-06-22
Gemini API on Google Cloud: Diagnosing Production Errors Layer by Layer
Systematically diagnose Gemini API errors in Google Cloud production environments. Covers IAM permissions, Vertex AI vs AI Studio, VPC Service Controls, quota management, service accounts, and multi-region failover with full code examples.
📚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 →