Zera

Guias

Webhooks

Como receber e validar o aviso de mudança de status do pedido.

A Zera chama o seu HTTPS quando o status de um pedido muda. Isso é diferente dos webhooks que o Banco do Brasil e o adquirente mandam para a Zera: esses últimos não fazem parte da sua integração.

Você implementaZera → seu HTTPS

Evento order.status_changed, assinado em X-Zera-Signature.

Não é a sua rotaÓrgão → Zera

O Banco do Brasil avisa a Zera. Você não expõe essa URL.

Não é a sua rotaAdquirente → Zera

A confirmação de Pix ou cartão chega na Zera, não no seu servidor.

Evento

order.status_changed

{
  "event": "order.status_changed",
  "order_id": "55ee44dd-33cc-22bb-11aa-009988776655",
  "status": "paid",
  "plate": "ABC1D23",
  "total_amount": "139.80",
  "refunded_amount": "0.00"
}

O corpo é JSON compacto, sem espaços. A assinatura é calculada sobre esses bytes exatos.

Assinatura

Header: X-Zera-Signature

Valor: HMAC-SHA256 do corpo cru, em hexadecimal, usando o segredo configurado no webhook da marca.

import { createHmac, timingSafeEqual } from "node:crypto";

export function isValidSignature(rawBody, header, secret) {
  const digest = createHmac("sha256", secret).update(rawBody).digest("hex");
  const left = Buffer.from(digest);
  const right = Buffer.from(header ?? "");
  return left.length === right.length && timingSafeEqual(left, right);
}

Responda 2xx rápido. A Zera espera até 10 segundos. Status 4xx ou 5xx, ou timeout, marca a entrega como falha. O GET /api/v1/orders/{order_id} continua sendo a fonte para reconciliar.

O webhook é configurado por marca no portal do parceiro (URL, segredo e flag ativo). Sem URL ativa, o evento fica registrado do lado da Zera e não é enviado.

Os status possíveis são os mesmos do pedido: awaiting_payment, paying_detran, paid, partial, failed, needs_review e refunded.