Webhooks (JSON)

Envía cada respuesta de Google Forms como JSON firmado a tu propio endpoint, Zapier, Make o n8n, y verifica la firma

Una regla de Webhook envía por POST cada respuesta que coincide, como JSON, a una URL que tú indicas. Úsala para alimentar un CRM, una herramienta de hojas de cálculo, tu propio servidor o una plataforma de automatización como Zapier, Make o n8n.

Crear una regla de webhook

  1. Haz clic en + Nueva regla y elige Webhook
  2. Cuándo: deja Cada respuesta, o elige Solo tras la aprobación / Al rechazarse y define un aprobador. Agrega condiciones en Solo si para enviar solo las respuestas que coincidan
  3. Para: pega la URL de tu endpoint (solo HTTPS). No hay paso Mensaje: la regla envía una carga JSON fija. Ver payload, bajo la URL, la muestra con las preguntas de tu formulario, lista para copiar
  4. Haz clic en Crear regla y copia el secreto de firma que se muestra una sola vez (ver más abajo)

Enviar prueba manda una carga de muestra, firmada, al endpoint y muestra el estado HTTP que devolvió. Las URL guardadas se almacenan cifradas y se muestran enmascaradas; haz clic en Reemplazar para pegar una nueva.

La carga

Cada solicitud es POST, Content-Type: application/json, con este cuerpo:

{
  "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 es uno de submitted, approved, rejected; también viaja en la cabecera X-Skyfield-Event
  • response.respondentEmail es null salvo que el formulario recopile direcciones de correo
  • answers[].value siempre es una cadena; las respuestas de casillas se unen con ,
  • rule.id y rule.name identifican la regla que se activó; name es null cuando la regla no tiene nombre
  • En approved y rejected se incluye un campo extra approval: { "decision": "approved", "decidedBy": "Dana" }. decidedBy es el nombre que el aprobador escribió en la página de aprobación; si no escribió ninguno, su correo electrónico, o null

version se mantiene en 1 mientras la forma anterior sea estable. Pueden añadirse campos nuevos; ninguno se elimina ni se renombra sin subir la versión.

Verificar la firma

Cada solicitud lleva una cabecera X-Skyfield-Signature: sha256=<hex>, el HMAC-SHA256 del cuerpo sin procesar de la solicitud con el secreto de firma de la regla como clave. Verifícala antes de confiar en una solicitud.

El secreto (whsec_...) se muestra una sola vez, justo después del guardado que da a la regla su primera URL de webhook. Cópialo en ese momento; no se puede volver a mostrar. Reemplazar la URL más adelante conserva el mismo secreto. Si lo pierdes, abre la regla, haz clic en Nuevo secreto de firma y guarda: el secreto nuevo se muestra una vez y el antiguo deja de funcionar de inmediato.

Calcula el HMAC sobre los bytes del cuerpo exactamente como se recibieron. Si primero analizas y vuelves a serializar el JSON, cambiarán los espacios y la comparación fallará.

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

Responde con cualquier estado 2xx. El cuerpo se ignora.

Zapier, Make, n8n

Los tres aceptan un webhook JSON genérico:

  • Zapier: disparador Webhooks by Zapier, evento Catch Hook (o Catch Raw Hook para verificar la firma tú mismo). Pega en la regla la URL que muestra Zapier
  • Make: agrega un módulo Webhooks, Custom webhook, y copia su URL
  • n8n: agrega un nodo Webhook, método POST, y usa su URL de producción

Envía una prueba desde la regla y luego asigna los campos de response.answers en la plataforma. La carga de muestra usa respuestas de ejemplo para que todos los campos estén presentes.

Entrega y límites

  • El endpoint debe ser accesible desde internet por HTTPS. Las direcciones privadas y locales se rechazan al guardar
  • No se siguen redirecciones: usa la URL final
  • El endpoint tiene 5 segundos para responder. Un tiempo de espera agotado o una respuesta 5xx se reintentan una vez
  • Una respuesta 404 o 410 significa que el endpoint ya no existe: la regla queda en pausa y recibes un único correo. Pega una URL nueva en la regla para reanudarla
  • La página Historial lista cada entrega con el estado HTTP que devolvió tu endpoint
  • Una regla de webhook en pausa o desactivada no bloquea las demás reglas del formulario

Conviene saber

  • Una regla de webhook respeta Enviar cuando, así que un endpoint puede recibir una decisión de aprobación en lugar de cada envío. Consulta Enviar cuando
  • Para enviar solo respuestas revisadas, configura el Enviar cuando de la regla como Solo tras la aprobación y elige un aprobador. Consulta Aprobación. La carga lleva entonces approval.decision
  • Cambiar canal… pasa una regla de webhook a Correo o a un canal de chat; indica ahí el nuevo destino. Si vuelves a Webhook, hay que pegar la URL de nuevo
  • Las reglas de webhook necesitan una licencia activa. La prueba gratuita cuenta. Consulta qué necesita licencia