KIRVEXDOCS

Webhooks

Receba notificações em tempo real sobre eventos na sua conta Kirvex.

Como funciona

Quando eventos acontecem na sua conta (pagamento confirmado, reembolso processado, etc.), a Kirvex envia um POST HTTP para as URLs que você configurar.

Eventos disponíveis

EventoDescrição
charge.succeededPagamento confirmado pelo adquirente
charge.failedPagamento recusado
charge.refundedReembolso total processado
charge.disputedContestação/chargeback aberto ou atualizado
payout.succeededSaque creditado na conta destino
payout.failedSaque falhou

Configuração

Via SDK (TypeScript)

const ep = await ap.webhookEndpoints.create({
  url: 'https://seuapp.com/webhooks/kirvex',
  event_types: ['charge.succeeded', 'charge.failed', 'charge.refunded'],
});

// Guarde o secret — ele só é mostrado uma vez
console.log(ep.secret); // whsec_...

Via SDK (PHP)

$ep = $ap->webhookEndpoints->create([
    'url' => 'https://seuapp.com/webhooks/kirvex',
    'event_types' => ['charge.succeeded', 'charge.failed'],
]);

Via SDK (Python)

ep = ap.webhook_endpoints.create({
    "url": "https://seuapp.com/webhooks/kirvex",
    "event_types": ["charge.succeeded", "charge.failed"],
})

Verificação de assinatura

Toda requisição webhook inclui o header X-Kirvex-Signature no formato:

t=1714432800,v1=5d41402abc4b2a76b9719d911017c592
  • t — timestamp Unix (segundos) do envio
  • v1 — HMAC-SHA256 de {timestamp}.{body} com o secret do endpoint

TypeScript

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

function verifyWebhook(rawBody: string, sigHeader: string, secret: string): boolean {
  const parts = Object.fromEntries(
    sigHeader.split(',').map(p => p.split('=', 2) as [string, string])
  );
  const expected = createHmac('sha256', secret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

PHP

use Kirvex\Sdk\WebhookHelper;

$event = WebhookHelper::verify(
    file_get_contents('php://input'),
    $_SERVER['HTTP_X_KIRVEX_SIGNATURE'],
    'whsec_...'
);

Python

from kirvex import verify_webhook

event = verify_webhook(
    raw_body=request.body,
    signature=request.headers["x-kirvex-signature"],
    secret="whsec_...",
)

Retries

Se o seu endpoint retornar status ≥ 500 ou não responder em 5s, a Kirvex reenvia com backoff exponencial:

TentativaDelay
1Imediata
25 minutos
330 minutos
42 horas
512 horas

Após 5 falhas, o evento vai para a DLQ (dead letter queue) e um alerta é emitido no dashboard.

Idempotência

Cada evento tem um id único. Seu handler deve ser idempotente — o mesmo evento pode ser entregue mais de uma vez (retry ou replay manual).

// Exemplo: use o event.id como chave de idempotência
const alreadyProcessed = await db.processedEvents.findUnique({ where: { id: event.id } });
if (alreadyProcessed) return res.status(200).end();

Payload

{
  "id": "evt_01J...",
  "type": "charge.succeeded",
  "created": "2026-04-29T12:00:00.000Z",
  "livemode": true,
  "data": {
    "charge_id": "ch_01J...",
    "status": "succeeded",
    "amount": { "amount": "9990", "currency": "BRL" },
    "vendor": "woovi",
    "vendor_ref": "..."
  }
}

livemode diz de qual modo é o evento: false para uma cobrança criada com uma chave sk_test_ (sandbox, sem dinheiro real), true para uma cobrança real. Os mesmos endpoints recebem os dois — filtre por livemode antes de liberar um pedido. Eventos de saque são sempre livemode: true.

Test Send

Envie um evento de teste para validar sua integração:

await ap.webhookEndpoints.testSend('we_...');

On this page