Google a livré des webhooks event-driven pour l'API Gemini, éliminant le polling pour les jobs longs sur trois familles d'endpoints : Batch (succeeded / cancelled / expired / failed), Interactions (requires_action / completed / failed / cancelled), et Video Generation (video.generated). L'implémentation suit la spec Standard Webhooks — signature HMAC-SHA256 pour les webhooks statiques (niveau projet), JWT asymétrique (RS256) via JWKS pour les webhooks dynamiques (par requête), avec headers `webhook-signature`, `webhook-id`, et `webhook-timestamp`. Livraison at-least-once, fenêtre de retry de 24h avec backoff exponentiel. Fenêtre anti-rejeu recommandée : rejeter les charges utiles vieilles de plus de cinq minutes.
Les deux modes de configuration comptent. *Statique* : configuré au niveau projet via une WebhookService API, déclenche pour tout event correspondant sous ce projet, utilise un secret partagé pour la validation HMAC. *Dynamique* : surcharge au moment de la requête avec un payload `webhook_config`, utilise du JWT asymétrique signé par les clés de Google (vérifiable sur `https://generativelanguage.googleapis.com/.well-known/jwks.json`). Le mode dynamique supporte aussi un champ `user_metadata` pour le routage — les métadonnées font l'aller-retour dans le payload du webhook, donc un seul endpoint peut fan-out par tenant, utilisateur ou workflow sans stocker l'état du job-ID séparément. Les payloads sont volontairement minces : snapshots de statut avec pointeurs comme `output_file_uri` (Batch) ou `file_id` et `video_uri` (Video), pas les sorties brutes. Les serveurs répondent `2xx` immédiatement et traitent en async pour éviter les cycles de retry. Le header `webhook-id` te donne la primitive de déduplication.
Pour le contexte écosystémique, ça met l'API Gemini en parité-plus sur la livraison d'events. La Batch API d'OpenAI et les Message Batches d'Anthropic roulent toutes les deux en async avec un statut que tu *pollies* présentement — une exécution batch de 24h, c'est du polling à l'horaire qui brûle du budget de requêtes en attendant la complétion. Les webhooks inversent ça : ton application dort jusqu'à ce que Google la notifie. Pour la génération vidéo spécifiquement (les charges style Veo peuvent rouler de dizaines de secondes à des minutes par requête), le polling est encore plus dispendieux. Le split statique-vs-dynamique est bien pensé : statique pour « j'ai une équipe qui fait rouler des batch jobs, donne-moi un secret pour les vérifier toutes », dynamique pour « je suis un SaaS qui fait rouler des charges Gemini multi-tenant et il me faut que chaque webhook tenant atterrisse sur son endpoint isolé avec ses métadonnées attachées ». C'est une forme de capacité utile à copier si tu bâtis quelque chose de similaire.
Lectures pratiques. Si tu fais rouler des jobs Gemini Batch ou vidéo et que tu pollies présentement, switch — ça sauve des appels API, réduit la latence de queue sur la détection de complétion, et c'est structurellement plus propre. La fenêtre anti-rejeu de 5 minutes plus la dédup par `webhook-id` veut dire que ton handler de webhook a besoin d'une couche d'idempotence (la plupart en ont déjà une). Pour les développeurs multi-tenant, les webhooks dynamiques avec `user_metadata` c'est le bon pattern — n'essaie pas de mapper des webhooks statiques entre tenants en parsant des job IDs. Compare ton overhead de polling OpenAI / Anthropic actuel et décide si ça vaut la peine de pousser ces fournisseurs à livrer la couverture Standard Webhooks aussi. Le signal n'est pas « les webhooks sont nouveaux »; les webhooks sont vieux. Le signal, c'est que les APIs IA reçoivent finalement le traitement Standard Webhooks, ce qui veut dire que l'infrastructure agent-et-batch peut être bâtie avec les mêmes primitives opérationnelles que le reste de ton stack.
