Pular para o conteúdo
Última atualização

Webhooks

Webhooks entregam notificações em tempo real quando recursos mudam. Em vez de fazer polling na API, registre uma URL e receba requisições POST sempre que eventos ocorrerem. A API Dinie segue a especificação Standard Webhooks.

Configurando Endpoints de Webhook

Criar um Endpoint

Registre uma URL para receber eventos de webhook. Você pode se inscrever em eventos específicos ou receber todos.

const endpoint = await dinie.webhooks.endpoints.create({
  url: "https://yourapp.example.com/webhooks/dinie",
  events: ["customer.active", "credit_offer.available", "loan.*"],
  description: "Production webhook",
});

// Armazene endpoint.secret com segurança -- ele é exibido apenas uma vez.
console.log(endpoint.secret); // "whsec_xxxxx..."

O endpoint.secret retornado é necessário para verificar assinaturas -- armazene-o imediatamente no seu gerenciador de secrets.

Warning: O secret é retornado apenas na criação e rotação. Armazene-o imediatamente no seu gerenciador de secrets. Você precisa dele para verificar assinaturas de webhook.

Gerenciando Endpoints

OperaçãoMétodoEndpoint
Listar todosGET/v3/webhooks/endpoints
Obter umGET/v3/webhooks/endpoints/{id}
AtualizarPATCH/v3/webhooks/endpoints/{id}
ExcluirDELETE/v3/webhooks/endpoints/{id}

Você pode desabilitar um endpoint sem excluí-lo definindo status: "disabled" via PATCH.

Recebendo Webhooks

Cada entrega é uma requisição POST com headers de autenticação (webhook-id, webhook-timestamp, webhook-signature). Use o SDK para verificar e parsear o evento:

import express from "express";
import Dinie from "dinie";

const app = express();
const dinie = new Dinie({
  clientId: process.env.DINIE_CLIENT_ID,
  clientSecret: process.env.DINIE_CLIENT_SECRET,
  webhookSecret: process.env.DINIE_WEBHOOK_SECRET,
});

app.post("/webhooks/dinie", express.raw({ type: "application/json" }), (req, res) => {
  const event = dinie.webhooks.unwrap(req.body.toString(), req.headers);

  switch (event.type) {
    case "customer.active":
      console.log(`Cliente ${event.data.id} aprovado`);
      break;
    case "loan.active":
      console.log(`Empréstimo ${event.data.id} desembolsado`);
      break;
  }

  res.sendStatus(200);
});

O webhook_secret é configurado no construtor do client. O método unwrap usa esse secret para verificar a assinatura HMAC-SHA256, validar o timestamp (proteção contra replay de 5 minutos) e retornar o evento tipado. Se a verificação falhar, uma exceção é lançada -- retorne 400 nesse caso.

Verificação Manual de Assinatura

Se você não estiver usando os SDKs, implemente a verificação manualmente seguindo a especificação Standard Webhooks:

  1. Construa o conteúdo assinado: {webhook-id}.{webhook-timestamp}.{raw_body}
  2. Decodifique o secret: remova o prefixo whsec_ e decodifique o restante em base64
  3. Calcule o HMAC-SHA256 do conteúdo assinado usando o secret decodificado
  4. Codifique o resultado em base64 e compare com cada assinatura no header webhook-signature
  5. Rejeite se o webhook-timestamp for mais antigo que 5 minutos (proteção contra replay)

Consulte a especificação Standard Webhooks para detalhes completos sobre os headers e formato de assinatura.

Códigos de Resposta

Seu endpoint de webhook deve responder em até 15 segundos. Apenas o código de status HTTP importa -- o corpo da resposta é ignorado.

StatusComportamentoDescrição
2xx (200-299)SucessoEntrega confirmada. Mais comuns: 200 OK ou 204 No Content.
3xx (300-399)Falha + retentativaRedirecionamentos NÃO são seguidos. Atualize a URL do endpoint via API.
410 GoneEndpoint desativadoDinie desativa permanentemente o endpoint e para de enviar eventos. Use para cancelar a inscrição sem chamar a API.
429 Too Many RequestsThrottleDinie reduz a taxa de envio e reagenda com backoff.
4xx (outros)Falha + retentativaQualquer outro erro de cliente dispara retentativas.
502 Bad GatewayThrottleDinie reduz a taxa de envio antes de retentar.
504 Gateway TimeoutThrottleMesmo comportamento do 502.
5xx (outros)Falha + retentativaQualquer outro erro de servidor dispara retentativas.
Timeout (sem resposta em 15s)Falha + retentativaConexão encerrada, entrega tratada como falha.

Política de Retentativa

Entregas com falha são reenviadas com exponential backoff. Jitter aleatório é adicionado a cada intervalo para evitar thundering herd.

TentativaIntervalo
1Imediato
25 segundos
35 minutos
430 minutos
52 horas
65 horas
710 horas
814 horas
920 horas
1024 horas

Após 10 tentativas com falha (~3 dias), o evento é marcado como failed. Eventos com falha podem ser reenviados manualmente. Falhas repetidas em múltiplos eventos desabilitarão automaticamente o endpoint de webhook.

Info: Use o header webhook-id como chave de idempotência para deduplicar entregas do seu lado. O mesmo evento pode ser entregue mais de uma vez durante as retentativas.

Rotação de Secret

Rotacione o secret de assinatura do seu webhook sem downtime:

curl -X POST https://sandbox.api.dinie.com.br/v3/webhooks/endpoints/we_550e8400.../secret/rotate \
  -H "Authorization: Bearer dinie_at_..." \
  -H "Content-Type: application/json" \
  -d '{ "expire_current_in": 3600 }'

Durante o período de transição (expire_current_in, padrão 1 hora, máximo 24 horas), ambos os secrets -- antigo e novo -- estão ativos. O header webhook-signature contém assinaturas para ambos os secrets, então seu código de verificação vai corresponder a qualquer um deles.

  1. Chame POST /v3/webhooks/endpoints/{id}/secret/rotate com um período de transição
  2. Atualize sua aplicação com o novo secret da resposta
  3. Faça o deploy -- durante o período de transição, ambos os secrets funcionam
  4. Após o período de transição, apenas o novo secret é usado

Boas Práticas

  1. Sempre verifique assinaturas -- nunca confie nos payloads de webhook sem verificação
  2. Responda rapidamente -- retorne um status 200 em até 15 segundos. Processe o evento de forma assíncrona se necessário.
  3. Implemente idempotência -- use o webhook-id para deduplicar. Seu handler deve processar o mesmo evento duas vezes com segurança.
  4. Use HTTPS -- URLs de webhook devem usar HTTPS. Endpoints HTTP são rejeitados.
  5. Registre as entregas -- armazene o webhook-id e o webhook-timestamp para debugging e trilhas de auditoria.

Eventos Disponíveis

Todos os payloads seguem o mesmo envelope:

{
  "type": "resource.action",
  "timestamp": 1709546400,
  "data": { ... }
}

Inscrição por Wildcard

  • Eventos específicos: ["customer.active", "loan.created"]
  • Todos de um recurso: ["loan.*"]
  • Todos os eventos: omita o campo events ou passe um array vazio

Eventos por Recurso

RecursoEventoDescrição
Clientecustomer.createdNovo cliente cadastrado
customer.under_reviewKYC enviado, análise iniciada
customer.kyc_updatedStatus de requisito KYC alterado
customer.activeTotalmente verificado, elegível para crédito
customer.deniedPermanentemente bloqueado
Oferta de Créditocredit_offer.availableNova oferta criada para o cliente
credit_offer.expiredOferta ultrapassou a data de validade
Empréstimoloan.createdEmpréstimo criado com CCB gerada sincronamente, signing_url disponível
loan.signature_receivedAssinatura individual recebida
loan.processingTodas assinaturas coletadas, desembolso em andamento
loan.activeFundos desembolsados, pagamento iniciado
loan.payment_receivedParcela recebida
loan.finishedEmpréstimo totalmente quitado
loan.cancelledEmpréstimo cancelado
loan.errorErro no processamento ou desembolso