Webhooks (JSON)

Envoyez chaque réponse Google Forms en JSON signé vers votre propre destination, Zapier, Make ou n8n, et vérifiez la signature

Une règle Webhook envoie en POST chaque réponse correspondante, au format JSON, vers une URL que vous fournissez. Utilisez-la pour alimenter un CRM, un outil de tableur, votre propre serveur ou une plateforme d'automatisation comme Zapier, Make ou n8n.

Créer une règle webhook

  1. Cliquez sur + Nouvelle règle et choisissez Webhook
  2. Quand : gardez Chaque réponse ou choisissez Seulement après approbation / En cas de rejet et définissez un approbateur. Ajoutez des conditions sous Seulement si pour n'envoyer que les réponses correspondantes
  3. Destinataire : collez l'URL de votre destination (HTTPS uniquement). Il n'y a pas d'étape Message : la règle envoie un payload JSON fixe. Voir le payload, sous l'URL, l'affiche avec les questions de votre formulaire, prêt à copier
  4. Cliquez sur Créer la règle, puis copiez le secret de signature affiché une seule fois (voir ci-dessous)

Envoyer un test envoie un payload d'exemple signé vers la destination et affiche le statut HTTP renvoyé. Les URL enregistrées sont stockées chiffrées et affichées masquées ; cliquez sur Remplacer pour en coller une nouvelle.

Le payload

Chaque requête est un POST, Content-Type: application/json, avec ce corps :

{
  "version": 1,
  "event": "submitted",
  "form": { "id": "1AbC...", "name": "Workshop sign-up" },
  "response": {
    "id": "a3f1...",
    "submittedAt": "2026-01-31T09:30:00.000Z",
    "respondentEmail": "respondent@example.com",
    "answers": [
      { "questionId": "q1", "title": "Your name", "value": "Ada Lovelace" },
      { "questionId": "q3", "title": "Department", "value": "Ops" }
    ]
  },
  "rule": { "id": "rule id", "name": "Zapier: new lead" }
}
  • event vaut submitted, approved ou rejected ; il figure aussi dans l'en-tête X-Skyfield-Event
  • response.respondentEmail vaut null sauf si le formulaire collecte les adresses e-mail
  • answers[].value est toujours une chaîne ; les réponses à cases à cocher sont jointes par ,
  • rule.id et rule.name identifient la règle qui s'est déclenchée ; name vaut null si la règle n'a pas de nom
  • Sur approved et rejected, un champ supplémentaire approval: { "decision": "approved", "decidedBy": "Dana" } est inclus. decidedBy est le nom saisi par l'approbateur sur la page de confirmation, à défaut l'adresse e-mail de l'approbateur, ou null.

version reste à 1 tant que la structure ci-dessus est stable. De nouveaux champs peuvent être ajoutés ; aucun n'est retiré ni renommé sans changement de version.

Vérifier la signature

Chaque requête porte un en-tête X-Skyfield-Signature : sha256=<hex>, le HMAC-SHA256 du corps brut de la requête, avec le secret de signature de votre règle comme clé. Vérifiez-le avant de faire confiance à une requête.

Le secret (whsec_...) est affiché une seule fois, juste après l'enregistrement qui donne à la règle sa première URL de webhook. Copiez-le à ce moment-là ; il ne peut plus être affiché ensuite. Remplacer l'URL plus tard conserve le même secret. Si vous le perdez, ouvrez la règle, cliquez sur Nouveau secret de signature et enregistrez : le nouveau secret est affiché une fois et l'ancien cesse immédiatement de fonctionner.

Calculez le HMAC sur les octets du corps exactement tels que reçus. Analyser puis resérialiser le JSON au préalable modifie les espaces et fait échouer la comparaison.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto'

// rawBody: string or Buffer of the request body, before any JSON parsing
function verify(rawBody, header, secret) {
  const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
  const a = Buffer.from(expected)
  const b = Buffer.from(header ?? '')
  return a.length === b.length && timingSafeEqual(a, b)
}

// Express example: use express.raw() so req.body is the untouched bytes
app.post('/hook', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verify(req.body, req.get('X-Skyfield-Signature'), process.env.SKYFIELD_SECRET))
    return res.status(401).end()
  const payload = JSON.parse(req.body)
  res.status(200).end()
})

Python

import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest("sha256=" + digest, header or "")

# Flask example
@app.post("/hook")
def hook():
    if not verify(request.get_data(), request.headers.get("X-Skyfield-Signature"), SECRET):
        return "", 401
    payload = request.get_json()
    return "", 200

Répondez avec n'importe quel statut 2xx. Le corps est ignoré.

Zapier, Make, n8n

Les trois acceptent un webhook JSON générique :

  • Zapier : déclencheur Webhooks by Zapier, événement Catch Hook (ou Catch Raw Hook pour vérifier la signature vous-même). Collez dans la règle l'URL affichée par Zapier
  • Make : ajoutez un module Webhooks, Custom webhook, et copiez son URL
  • n8n : ajoutez un nœud Webhook, méthode POST, et utilisez son URL de production

Envoyez un test depuis la règle, puis mappez les champs response.answers dans la plateforme. Le payload d'exemple utilise des réponses fictives pour que chaque champ soit présent.

Livraison et limites

  • La destination doit être joignable sur l'internet public en HTTPS. Les adresses privées et locales sont refusées à l'enregistrement
  • Les redirections ne sont pas suivies : utilisez l'URL finale
  • La destination a 5 secondes pour répondre. Un délai dépassé ou une réponse 5xx est réessayé une fois
  • Une réponse 404 ou 410 signifie que la destination n'existe plus : la règle est mise en pause et vous recevez un seul e-mail. Collez une nouvelle URL sur la règle pour reprendre
  • La page Historique liste chaque livraison avec le statut HTTP renvoyé par votre destination
  • Une règle webhook en pause ou désactivée ne bloque pas les autres règles du formulaire

Bon à savoir

  • Une règle webhook respecte Envoyer quand : une destination peut donc recevoir une décision d'approbation au lieu de chaque soumission. Voir Envoyer quand
  • Pour n'envoyer que des réponses validées, réglez Envoyer quand de la règle sur Seulement après approbation et choisissez un approbateur. Voir Approbation. Le payload contient alors approval.decision
  • Changer de canal… fait passer une règle webhook à E-mail ou à un canal de chat ; indiquez-y la nouvelle destination. Si vous revenez à Webhook, l'URL doit être collée à nouveau
  • Les règles webhook nécessitent une licence active. L'essai gratuit compte. Voir ce qui nécessite une licence