Webhooks (JSON)

Envie cada resposta do Google Forms como JSON assinado para o seu próprio destino, Zapier, Make ou n8n, e verifique a assinatura

Uma regra de Webhook envia (POST) cada resposta correspondente como JSON para uma URL que você informa. Use-a para alimentar um CRM, uma ferramenta de planilhas, o seu próprio servidor ou uma plataforma de automação como Zapier, Make ou n8n.

Crie uma regra de webhook

  1. Clique em + Nova regra e escolha Webhook
  2. Quando: mantenha Toda resposta, ou escolha Somente após aprovação / Quando rejeitada e defina um aprovador. Adicione condições em Somente se para enviar apenas as respostas correspondentes
  3. Para: cole a URL do seu destino (somente HTTPS). Não há etapa Mensagem: a regra envia um payload JSON fixo. Ver payload, abaixo da URL, mostra o payload com as perguntas do seu formulário, pronto para copiar
  4. Clique em Criar regra e copie o segredo de assinatura exibido uma única vez (veja abaixo)

Enviar teste envia um payload de exemplo, assinado, ao destino e mostra o status HTTP retornado. As URLs salvas são armazenadas criptografadas e exibidas mascaradas; clique em Substituir para colar uma nova.

O payload

Cada requisição é um POST, Content-Type: application/json, com este corpo:

{
  "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 é um de submitted, approved, rejected; ele também vai no cabeçalho X-Skyfield-Event
  • response.respondentEmail é null, a menos que o formulário colete endereços de e-mail
  • answers[].value é sempre uma string; respostas de caixas de seleção são unidas com ,
  • rule.id e rule.name identificam a regra que disparou; name é null quando a regra não tem nome
  • Em approved e rejected, é incluído um approval: { "decision": "approved", "decidedBy": "Dana" } extra. decidedBy é o nome que o aprovador digitou na página de aprovação; se não houver, o e-mail do aprovador, ou null

version permanece 1 enquanto o formato acima for estável. Novos campos podem ser adicionados; nenhum é removido ou renomeado sem uma mudança de versão.

Verificando a assinatura

Toda requisição traz um cabeçalho X-Skyfield-Signature: sha256=<hex>, o HMAC-SHA256 do corpo bruto da requisição com a chave sendo o segredo de assinatura da regra. Verifique-o antes de confiar em uma requisição.

O segredo (whsec_...) é exibido uma vez, logo depois do salvamento que dá à regra sua primeira URL de webhook. Copie-o nesse momento; ele não pode ser exibido de novo. Substituir a URL depois mantém o mesmo segredo. Se você o perder, abra a regra, clique em Novo segredo de assinatura e salve: o novo segredo é exibido uma vez e o antigo para de funcionar imediatamente.

Calcule o HMAC sobre os bytes do corpo exatamente como recebidos. Fazer o parse e reserializar o JSON antes altera os espaços em branco e quebra a comparação.

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

Responda com qualquer status 2xx. O corpo é ignorado.

Zapier, Make, n8n

Os três aceitam um webhook JSON genérico:

  • Zapier: gatilho Webhooks by Zapier, evento Catch Hook (ou Catch Raw Hook para verificar a assinatura por conta própria). Cole na regra a URL que o Zapier mostra
  • Make: adicione um módulo Webhooks, Custom webhook, e copie a URL dele
  • n8n: adicione um nó Webhook, método POST, e use a URL de produção dele

Envie um teste pela regra e depois mapeie os campos de response.answers na plataforma. O payload de exemplo usa respostas fictícias, então todos os campos estão presentes.

Entrega e limites

  • O destino precisa estar acessível na internet pública via HTTPS. Endereços privados e locais são rejeitados ao salvar
  • Redirecionamentos não são seguidos: use a URL final
  • O destino tem 5 segundos para responder. Um tempo esgotado ou uma resposta 5xx é repetido uma vez
  • Uma resposta 404 ou 410 significa que o destino não existe mais: a regra é pausada e você recebe um e-mail. Cole uma nova URL na regra para retomar
  • A página Histórico lista cada entrega com o status HTTP que o seu destino retornou
  • Uma regra de webhook pausada ou desativada não bloqueia outras regras do formulário

Bom saber

  • Uma regra de webhook respeita o Enviar quando, então um destino pode receber uma decisão de aprovação em vez de todo envio. Veja Enviar Quando
  • Para enviar apenas respostas verificadas, defina o Enviar quando da regra como Somente após aprovação e escolha um aprovador. Veja Aprovação. O payload passa a trazer approval.decision
  • Alterar canal… move uma regra de webhook para E-mail ou para um canal de chat; informe o novo destino ali. Ao voltar para Webhook, a URL precisa ser colada de novo
  • As regras de webhook precisam de uma licença ativa. O período de teste gratuito conta. Veja o que precisa de licença