Sua aplicação não precisa consultar GET /payment-pix/get/:id em loop. Quando um pagamento confirma, a GoatPay envia um POST HTTPS para a URL cadastrada.
Configurar
1. Endpoint HTTPS
Exponha uma rota pública, por exemplo https://api.suaempresa.com/goatpay/webhook.
3. Guardar o segredo
Anote o whsec_... exibido uma única vez na criação.
Escopo por API key
Endpoints criados com POST /v1/webhooks/create ficam vinculados à chave usada. Recebem eventos das transações criadas pela mesma API key. Endpoints do dashboard (sem vínculo de chave) recebem eventos de toda a conta.
Teste
Dispare o evento webhook.test cadastrando o tipo na lista de events e processando um teste a partir do painel da conta, ou aguarde uma transação real da mesma API key.
Corpo JSON:
{
"id": "clxxx_delivery",
"event": "payment.paid",
"createdAt": "2026-05-24T12:00:00.000Z",
"data": {
"id": "clx_transacao",
"type": "PIX_IN",
"status": "COMPLETED",
"amount": 100,
"feeAmount": 8.5,
"netAmount": 91.5,
"currency": "BRL",
"externalReference": "pedido-123",
"referenceId": "ref_pix_abc",
"endToEndId": "E12345678202505301234567890123456",
"completedAt": "2026-05-24T12:00:00.000Z",
"createdAt": "2026-05-24T11:55:00.000Z"
}
}
O objeto data segue o mesmo formato enxuto das respostas /v1 (sem provider, accountId, metadata nem histórico de entregas).
Headers:
Content-Type: application/json
x-goatpay-event: payment.paid
x-goatpay-signature: sha256=<hmac do corpo JSON>
x-goatpay-delivery: <id da entrega>
A assinatura é calculada sobre o raw body (bytes exatos recebidos), não sobre um objeto re-serializado.
Segurança e assinatura
Cada entrega usa HMAC-SHA256 com o segredo whsec_... da criação do endpoint.
Validação (Node.js)
import crypto from "node:crypto";
export function verifyGoatPayWebhook(
rawBody: string | Buffer,
signatureHeader: string | undefined,
webhookSecret: string,
): boolean {
if (!signatureHeader?.startsWith("sha256=")) return false;
const received = signatureHeader.slice("sha256=".length);
const expected = crypto
.createHmac("sha256", webhookSecret)
.update(typeof rawBody === "string" ? rawBody : Buffer.from(rawBody))
.digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(received, "hex");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Use timingSafeEqual na comparação. Nunca processe o evento sem validar x-goatpay-signature.
Retentativas
Se o endpoint não responder 2xx a tempo, a GoatPay reenvia com backoff: 1 min, 5 min, 15 min, 1 h, 4 h (até 5 tentativas).
Idempotência
Persista o id da entrega antes de processar. Duplicatas devem responder 200 sem efeito colateral.
const deliveryId = req.body.id;
if (await alreadyProcessed(deliveryId)) {
return res.status(200).json({ ok: true });
}
await processEvent(req.body);
await markProcessed(deliveryId);
return res.status(200).json({ ok: true });
Checklist
- URL HTTPS em produção
- Validar
x-goatpay-signature com o whsec_... correto
- Responder
200 após processar ou enfileirar com segurança
- Tratar o mesmo
id de entrega apenas uma vez
- Ignorar campos extras desconhecidos em
data
Eventos
Inscreva os tipos abaixo em events ao criar o endpoint. Use "*" apenas se realmente precisar de todos os eventos futuros.
Pagamentos PIX e boleto
| Evento | Quando ocorre |
|---|
payment.created | Cobrança registrada (pendente). |
payment.paid | Pagamento confirmado. |
payment.failed | Falha ou cancelamento. |
payment.refunded | Estorno confirmado (legado; mantido por compatibilidade). |
payment.pix.expired | QR PIX expirou. |
Reembolso PIX (depósito recebido)
| Evento | Quando ocorre |
|---|
refund.requested | Estorno solicitado (POST /refunds/create); saldo reservado. |
refund.completed | Devolução confirmada no SPI (também dispara payment.refunded). |
refund.failed | Estorno não concluído; saldo restaurado. |
Pagamentos cripto
| Evento | Quando ocorre |
|---|
payment.crypto.created | Cobrança cripto criada. |
payment.crypto.paid | Depósito confirmado. |
payment.crypto.failed | Falha no fluxo. |
payment.crypto.expired | Cobrança expirou. |
Transferências PIX
| Evento | Quando ocorre |
|---|
transfer.created | Saída PIX ou saque cripto registrado (pendente). |
transfer.completed | Saída PIX concluída com sucesso. |
transfer.failed | Saída PIX falhou ou expirou. |
Transferências cripto
| Evento | Quando ocorre |
|---|
transfer.created | Saque cripto criado (mesmo evento da saída PIX). |
transfer.crypto.completed | Saque on-chain confirmado. |
transfer.crypto.failed | Saque cripto falhou. |
Transferência interna
| Evento | Quando ocorre |
|---|
transfer.internal.completed | Conta de origem — débito concluído. |
transfer.internal.received | Conta de destino — crédito recebido. |
MED
| Evento | Quando ocorre |
|---|
med.created | Nova disputa MED (trilho PADRAO). |
med.updated | Status alterado. |
med.evidence_sent | Evidências enviadas via API. |
Cartão (Stripe Connect)
| Evento | Quando ocorre |
|---|
payment.paid | Checkout avulso POST /v1/card/checkout confirmado (type cartão no data). |
payment.failed | Pagamento recusado ou sessão Stripe encerrada sem sucesso. |
Inscreva esses eventos ao integrar cobrança direta na API. Para links de pagamento com CARD, use também payment_link.paid (abaixo).
Guia: Cartão Stripe Connect.
Links de pagamento
| Evento | Quando ocorre |
|---|
payment_link.paid | Sessão de link confirmada (PIX, boleto, cripto ou cartão Stripe). |
Exemplo de data:
{
"sessionId": "clx_session",
"status": "PAID",
"method": "CARD",
"amount": 99.9,
"feeAmount": 5.15,
"netAmount": 94.75,
"currency": "BRL",
"transactionId": "clx_tx",
"externalReference": "pedido-42",
"paidAt": "2026-06-02T15:00:00.000Z",
"payer": {
"name": "Maria",
"email": "maria@email.com"
},
"paymentLink": {
"id": "clx_link",
"name": "Plano Pro",
"slug": "plano-pro",
"publicCode": "abc12"
}
}
Para links pagos via PIX/boleto, payment.paid também pode ser emitido (formato de transação). Para integração focada em checkout de link, inscreva-se em payment_link.paid.
Teste
| Evento | Quando ocorre |
|---|
webhook.test | Disparo manual no dashboard. |
Endpoints da API
Permissões na API key: webhooks/create, webhooks/list, webhooks/get, webhooks/update, webhooks/delete.