Saltar para o conteúdo

Configurar webhooks e verificar a assinatura.

Webhooks da API da KENJTEC: os seis eventos enviados ao teu servidor, configurar um webhook, verificar a assinatura e como são repetidas as entregas falhadas.

VídeoConfigurar um webhook
Nesta página

Os eventos

Um webhook é um endereço do teu servidor para o qual enviamos um evento assim que ele acontece. Existem seis eventos:

form.response.created   Eine neue Antwort auf eines deiner Formulare
form.response.updated   Jemand hat seine Antwort über den Bearbeitungslink geändert
order.paid              Eine Bestellung ist bezahlt
order.fulfilled         Eine Bestellung ist versendet oder übergeben
order.canceled          Eine bestätigte Bestellung wurde storniert
order.refunded          Eine Bestellung wurde erstattet

order.refunded chega no primeiro reembolso parcial e no reembolso total. Um checkout que nunca foi pago e expira não é um cancelamento — nesse caso, não é enviado nenhum evento.

Configurar um webhook

Os programas também podem registar webhooks por si próprios: POST /v1/webhooks com uma chave que tenha webhooks:manage — e, além disso, a permissão de leitura dos dados que o webhook envia (forms:read para eventos de formulários, orders:read para encomendas).

Na área “Programador”, a Ana introduz o endereço https://deine-firma.com/kenjtec-webhook, deixa assinalada apenas a opção “Uma encomenda foi paga” e clica em “Criar webhook” — aparece “Webhook criado.” com o segredo para copiar.A gravação mostra a interface em inglês.
  1. Abre a área Programador no painel.
  2. Em “Webhooks”, introduz o endereço do teu recetor — começa por https.
  3. Em “Que eventos?”, escolhe o que queres receber e clica em “Criar webhook”.
  4. Copia o segredo que aparece a seguir para o teu recetor.
  5. Clica em “Enviar teste” — o resultado aparece logo abaixo.

O que chega

Cada evento é um POST com JSON. Em data.object, o objeto tem a mesma forma que na API — uma encomenda como em GET /v1/orders/{id}, uma resposta como na lista de respostas. Nos eventos de formulários, data.form indica também a que formulário pertence a resposta.

order.paid (abreviado)
{
  "id": "evt_Q2x9kLmP4vT7aB1cD3eF5gH7",
  "object": "event",
  "type": "order.paid",
  "api_version": "2026-09-23",
  "created_at": "2026-09-23T14:05:12Z",
  "data": {
    "object": {
      "id": 5531,
      "object": "order",
      "number": 42,
      "status": "confirmed",
      "payment_status": "paid",
      "currency": "EUR",
      "total": 3890,
      "customer": { "email": "mara@example.com", "name": "Mara Sol" },
      "items": [
        { "name": "Kaffeebohnen, 500 g", "sku": "KAF-500", "quantity": 2, "unit_price": 1690 }
      ]
    }
  }
}

Verificar a assinatura

Cada chamada inclui o cabeçalho KENJTEC-Signature: t=<tempo>,v1=<assinatura>. A assinatura é um HMAC-SHA256 calculado sobre o tempo, um ponto e o corpo inalterado do pedido — com o segredo do teu webhook como chave. Descarta tudo cujo tempo tenha mais de cinco minutos.

Verifica com base no corpo em bruto antes de leres o JSON: basta um espaço diferente para dar uma assinatura diferente. Encontras o segredo a qualquer momento em “Mostrar segredo”; “Renovar segredo” invalida o antigo de imediato.

Node.js
import crypto from "node:crypto";

// raw: the unparsed request body (Buffer), header: the KENJTEC-Signature header
export function verify(raw, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret)
    .update(`${parts.t}.`).update(raw).digest("hex");
  const given = String(parts.v1 ?? "");
  return given.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));
}
Python
import hashlib, hmac, time

def verify(raw: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

O mesmo evento pode chegar duas vezes — por exemplo, quando o teu servidor responde, mas a resposta não nos chega. O identificador em id (também no cabeçalho KENJTEC-Event-Id) mantém-se igual: guarda-o e processa cada evento apenas uma vez.

Quando algo não chega

Considera-se entregue qualquer resposta com um estado de 200 a 299 no prazo de dez segundos. Não seguimos redirecionamentos.

Se um evento não chegar, tentamos novamente: após 1, 5 e 30 minutos, após 2, 6 e 12 horas e duas vezes após 24 horas — durante pouco mais de três dias. Se cinco eventos seguidos falharem definitivamente, desativamos o webhook; o painel indica então o motivo, e “Voltar a ativar” repõe-no.

Em “Registo”, vês todas as entregas dos últimos 30 dias com estado e conteúdo. A partir daí, podes enviar novamente qualquer evento com “Enviar novamente”.

O registo de entregas do webhook do Café Lumen: três entradas “order.paid”, uma delas “Não entregue” com “O recetor respondeu com um estado de erro. (503)” e o botão “Enviar novamente”.
A gravação mostra a interface em inglês.

Os webhooks só são enviados para endereços https públicos. Não aceitamos endereços em redes internas nem endereços da própria KENJTEC.

Guias relacionados e próximos passos

Ajuda-nos a melhorar a KENJTEC

O Google Analytics ajuda-nos a melhorar o site. A Google recebe dados de utilização e do dispositivo, que podem ser tratados nos EUA.

É opcional. A tua escolha é válida por 180 dias e podes alterá-la a qualquer momento nas definições de cookies.

Política de privacidade