Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.garu.com.br/llms.txt

Use this file to discover all available pages before exploring further.

Visão Geral

Webhooks permitem que sua aplicação receba notificações automáticas quando eventos importantes acontecem, como quando um pagamento é confirmado ou um produto é criado.

Configurando Webhooks

1

Acesse o Dashboard

Faça login no Dashboard da Garu
2

Navegue até Webhooks

Vá para ConfiguraçõesWebhooks
3

Adicione um endpoint

Clique em Adicionar webhook e insira a URL do seu endpoint
4

Selecione os eventos

Escolha quais eventos deseja receber
5

Copie o segredo

Salve o segredo do webhook para validar as assinaturas

Eventos Disponíveis

Eventos de Produto

EventoDescrição
product.createdUm novo produto foi criado
product.updatedUm produto foi atualizado
product.deletedUm produto foi desativado

Eventos de Transação

EventoDescrição
transaction.createdUma nova transação foi iniciada
transaction.updatedUma transação teve seus dados atualizados
transaction.payment.succeededPagamento confirmado
transaction.payment.failedPagamento recusado (com failureCode normalizado — ver Códigos de falha)
transaction.canceledTransação cancelada (pelo seller, contrato ou operadora)
transaction.chargebackChargeback registrado pelo emissor
transaction.refundedPagamento estornado
O evento legado transaction.failed continua sendo entregue para endpoints que já o assinam, mas a partir da v0.8.0 prefira transaction.payment.failed / transaction.canceled / transaction.chargeback — eles separam falha técnica, cancelamento e chargeback.

Eventos de Cobrança Agendada (Scheduled Charge)

EventoDescrição
scheduled_charge.createdCobrança agendada criada
scheduled_charge.updatedDados da série atualizados
scheduled_charge.canceledCobrança avulsa cancelada
scheduled_charge.paidCiclo da série pago (carrega seriesId + cycleNumber)
scheduled_charge.overdueCiclo entrou em atraso
scheduled_charge.cycle_failedRetries de cartão esgotados (carrega failureCode, failureReason, gatewayFailureCode)
scheduled_charge.recurrence_canceledRecorrência cancelada (cancela ciclos futuros)
scheduled_charge.cancel_at_period_end_setSoft-cancel ativado
scheduled_charge.cancel_at_period_end_clearedSoft-cancel revertido
scheduled_charge.payment_method_attachedCartão salvo no ciclo 1
scheduled_charge.payment_method_changedCartão trocado
scheduled_charge.payment_method_clearedCartão removido (DELETE /:id/payment-method)

Eventos de Customer (Trial)

EventoDescrição
customer.trial_startedTrial iniciado
customer.trial_convertedTrial converteu em pagamento
customer.trial_lapsedTrial expirou sem pagamento

Eventos de Payment Method (Cartão Salvo)

EventoDescrição
payment_method.expiring_soonCartão vence em D-30, D-14 ou D-7 (um disparo por estágio)
payment_method.expiredCartão venceu — Garu flippou o status para expired automaticamente

Eventos de Assinatura

EventoDescrição
subscription.createdNova assinatura criada
subscription.activatedAssinatura ativada
subscription.pausedAssinatura pausada
subscription.cancelledAssinatura cancelada
subscription.renewedAssinatura renovada

Eventos de Checkout Session

EventoDescrição
checkout.session.completedPagamento da checkout session foi concluído
checkout.session.expiredCheckout session expirou sem pagamento

Formato do Payload

Todos os webhooks seguem este formato:
{
  "event": "transaction.paid",
  "timestamp": "2024-12-24T10:30:00.000Z",
  "data": {
    // Dados específicos do evento
  }
}

Exemplo: Pagamento Confirmado

{
  "event": "transaction.paid",
  "timestamp": "2024-12-24T10:30:00.000Z",
  "data": {
    "id": 456,
    "productId": 123,
    "productName": "Curso de Marketing Digital",
    "value": 297.00,
    "paymentMethod": "pix",
    "customer": {
      "name": "João Silva",
      "email": "joao@email.com",
      "document": "123.456.789-00"
    },
    "paidAt": "2024-12-24T10:30:00.000Z"
  }
}

Exemplo: Produto Criado

{
  "event": "product.created",
  "timestamp": "2024-12-24T10:30:00.000Z",
  "data": {
    "id": 123,
    "name": "Curso de Marketing Digital",
    "value": 297.00,
    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "sellerId": 456
  }
}

Exemplo: Checkout Session Concluída

{
  "event": "checkout.session.completed",
  "timestamp": "2024-12-24T14:30:00.000Z",
  "data": {
    "id": "cs_ABC123xyz",
    "status": "complete",
    "product_id": 123,
    "transaction_id": 789,
    "customer_email": "joao@email.com",
    "metadata": {
      "order_id": "12345"
    },
    "client_reference_id": "order_abc123",
    "completed_at": "2024-12-24T14:30:00.000Z"
  }
}

Exemplo: Checkout Session Expirada

{
  "event": "checkout.session.expired",
  "timestamp": "2024-12-25T12:00:00.000Z",
  "data": {
    "id": "cs_DEF456uvw",
    "status": "expired",
    "product_id": 123,
    "metadata": {
      "order_id": "67890"
    },
    "client_reference_id": "order_def456",
    "expires_at": "2024-12-25T12:00:00.000Z"
  }
}

Validando Assinaturas

Para garantir que o webhook veio da Garu, valide a assinatura:

Validando Assinatura do Webhook

const crypto = require('crypto');

function validarAssinatura(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Uso no Express.js
app.post('/webhooks/garu', (req, res) => {
  const signature = req.headers['x-garu-signature'];

  if (!validarAssinatura(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Assinatura inválida' });
  }

  res.status(200).json({ received: true });
  // Processar evento de forma assíncrona...
});
Sempre responda com HTTP 200 rapidamente (menos de 5 segundos) e processe a lógica de forma assíncrona.

Boas Práticas

Retorne HTTP 200 o mais rápido possível (em até 5 segundos). Processe a lógica de negócio de forma assíncrona.
Webhooks podem ser enviados mais de uma vez. Use o ID do evento para evitar processamento duplicado.
Configure seu endpoint com HTTPS para garantir a segurança dos dados.
Nunca processe webhooks sem validar a assinatura. Isso protege contra ataques.
Configure alertas para quando seu endpoint falhar em receber webhooks.

Retry Policy

Se seu endpoint não responder com 2xx, a Garu tentará reenviar com backoff:
TentativaIntervalo desde a anterior
11 minuto
25 minutos
330 minutos
42 horas
58 horas
616 horas
Após 6 tentativas sem sucesso (~26h36min de janela total), o webhook é marcado como falho.

Testando Webhooks

Para testar localmente, use ferramentas como:
  • ngrok - Cria um túnel para seu localhost
  • webhook.site - Inspeciona webhooks recebidos
# Usando ngrok
ngrok http 3000

# Seu endpoint público será algo como:
# https://abc123.ngrok.io/webhooks/garu

Próximos Passos

Exemplos de Código

Implementações completas em várias linguagens

Solução de Problemas

Resolva erros comuns