Skip to main content

Webhooks

Webhooks são notificações HTTP que a Linka envia para sua aplicação quando ocorrem eventos importantes, como uma transação paga, um saque liquidado ou uma disputa aberta. Em vez de fazer polling na API, você configura uma URL e recebe os eventos em tempo real.

Como funciona

  1. Você cadastra uma URL HTTPS na tela de Integrações > Webhooks (ou via POST /v1/webhooks)
  2. Quando um evento ocorre, a Linka envia um POST com payload JSON
  3. Seu servidor deve responder 2xx em até 5 segundos
  4. Sem resposta ou com erro 5xx, a Linka retenta automaticamente (veja Comportamento de Retry)
A URL do webhook precisa ser HTTPS. URLs HTTP são rejeitadas.

Anatomia de uma entrega

Cada entrega inclui dois headers e um payload JSON com os campos do recurso no nível raiz:

Validando a assinatura

A assinatura é enviada no campo signature do body (não em header). Ela é um HMAC-SHA256 calculado sobre a string "<timestamp>.<json_do_evento>", onde:
  • <timestamp> é o valor do header X-Webhook-Timestamp;
  • <json_do_evento> é o JSON do payload sem os campos version, expires_at e signature, preservando a ordem das chaves recebidas e sem espaços;
  • o resultado é codificado como v1= + Base64URL (sem = de padding).
Além de comparar a assinatura, rejeite entregas cujo timestamp esteja a mais de 5 minutos do relógio atual (janela anti-replay).
O secret usado na validação é o secret retornado uma única vez na criação do webhook. Se você rotacionar o secret (POST /v1/webhooks/{id}/rotate-secret), atualize sua aplicação imediatamente.

Configurando um Endpoint de Webhook

1

Crie um endpoint HTTPS no seu servidor

O endpoint deve estar acessível publicamente via HTTPS e retornar HTTP 200 para confirmação.
2

Registre o webhook na Linka

Resposta 201
O campo secret é exibido apenas nesta resposta. Salve-o imediatamente, ele não será exibido novamente. Use este secret para validar a assinatura HMAC de todos os webhooks recebidos.
3

Implemente a validação de assinatura

Use o código da seção Validando a assinatura acima. Rejeite qualquer entrega com assinatura inválida ou timestamp fora da janela de 5 minutos.

Tipos de Evento

O campo eventType aparece em dois contextos diferentes:
  • No cadastro do webhook: define a categoria de eventos assinada (TRANSACTION, WITHDRAWAL, DISPUTE ou ALL).
  • No payload de cada entrega: identifica o evento específico (ex: TRANSACTION_PAID).
Os eventos de transação e saque seguem o padrão TRANSACTION_<STATUS> e WITHDRAWAL_<STATUS> — um evento para cada mudança de status do recurso. Trate nomes de evento desconhecidos com um fallback: novos status geram novos eventos automaticamente.

Eventos de Transação

Além dos exemplos abaixo, qualquer mudança de status gera o evento correspondente (TRANSACTION_PROCESSING, TRANSACTION_AUTHORIZED, TRANSACTION_REFUSED, TRANSACTION_CHARGEDBACK, TRANSACTION_DISPUTE, TRANSACTION_PARTIALLY_REFUNDED, entre outros).

TRANSACTION_CREATED

Disparado após a criação da transação, quando o provedor confirma a geração da cobrança.

TRANSACTION_WAITING_PAYMENT

Disparado quando o instrumento de pagamento foi gerado e aguarda o pagador.

TRANSACTION_PAID

Pagamento confirmado. O crédito já foi processado na sua wallet.

TRANSACTION_FAILED

Falha técnica ou erro sem mapeamento no processamento do pagamento.

TRANSACTION_EXPIRED

QR Code PIX vencido sem pagamento.

TRANSACTION_REFUNDED

Estorno total processado. Em estornos parciais, o evento é TRANSACTION_PARTIALLY_REFUNDED com refundType: "PARTIAL".

Eventos de Saque

Seguem o padrão WITHDRAWAL_<STATUS>: WITHDRAWAL_CREATED, WITHDRAWAL_APPROVED, WITHDRAWAL_PROCESSING, WITHDRAWAL_PAID, WITHDRAWAL_REJECTED, WITHDRAWAL_FAILED, WITHDRAWAL_REFUNDED.

WITHDRAWAL_PROCESSING

O saque está sendo processado pela instituição de pagamento.

WITHDRAWAL_PAID

Transferência liquidada — o valor foi enviado ao destinatário.

WITHDRAWAL_REJECTED

Saque rejeitado. O valor debitado (incluindo a tarifa) é reembolsado automaticamente para a wallet.

WITHDRAWAL_FAILED

Falha na transferência. O valor debitado (incluindo a tarifa) é reembolsado automaticamente para a wallet.

Eventos de Disputa

DISPUTE_CREATED

Disputa aberta (chargeback ou contestação recebida).

DISPUTE_RESOLVED

Decisão a seu favor, saldo restaurado.

DISPUTE_REJECTED

Decisão a favor do comprador, valor debitado permanentemente.

MED_DISPUTE_CREATED

Disputa MED (Mecanismo Especial de Devolução) do PIX aberta.

MED_DISPUTE_REFUND_COMPLETED

Devolução MED concluída após decisão favorável ao cliente.

Comportamento de Retry

Cada ciclo de entrega faz até 3 tentativas com backoff exponencial (a partir de ~1s, dobrando até o teto de 30s, com jitter). O timeout de cada tentativa é de 5 segundos. Se o ciclo esgotar as 3 tentativas, o evento é reenfileirado automaticamente para novos ciclos de entrega ao longo das horas seguintes, e a entrega expira após o expires_at (24h).
Após 10 falhas consecutivas, o webhook é desativado automaticamente (isActive: false) e você é notificado. Reative-o na tela de Integrações após corrigir o endpoint.

Reenviando Eventos Manualmente

Use os endpoints de reenvio para forçar a reentrega de eventos específicos:
Para saques, use POST /v1/webhooks/resend-withdrawal-event com o body {"withdrawalIds": ["wd_uuid_1"]} — mesmos headers.

Privacidade dos Dados (LGPD)

Todos os payloads de webhook têm dados pessoais (PII) mascarados antes do envio: Os campos não-pessoais da conta de destino (destinationAccount.bank, .branch, .accountType) são enviados sem máscara, por não conterem PII. Para acessar os dados completos, use GET /api/v1/cobranca/transactions/{id} ou GET /api/v1/cobranca/withdrawals/{id} com autenticação.