> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pagamentos.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks

> Como usar hooks de lifecycle e webhooks com **pagamentos.dev**

## O que são hooks?

Hooks permitem que você execute código em momentos específicos do fluxo de pagamento. O **pagamentos.dev** oferece dois tipos de hooks unificados:

* **Lifecycle hooks** — disparam automaticamente após operações de API bem-sucedidas (criar, consultar, atualizar, listar, cancelar).
* **Webhook hooks** — disparam quando eventos assíncronos chegam via webhook (pagamento realizado, cobrança vencida, etc).

Você registra os hooks diretamente na configuração da instância `Pagamentos`:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import {
  Pagamentos,
  mercadopago,
  onCobrancaCreated,
  onWebhookEvent
} from 'pagamentos'

const pg = new Pagamentos({
  providers: [mercadopago({ accessToken: '...' })],
  hooks: [
    // Lifecycle hook
    onCobrancaCreated(async (evt) => {
      console.log('Cobrança criada:', evt.output.id)
    }),

    // Webhook hook
    onWebhookEvent('pagamento.realizado', async (event) => {
      console.log('Pagamento recebido:', event.data)
    })
  ]
})
```

## Lifecycle hooks

Os lifecycle hooks capturam eventos que acontecem **imediatamente após** uma chamada de API retornar com sucesso. Eles são ideais para logging, auditoria, sincronização com seu banco de dados ou disparo de ações internas.

### Evento de lifecycle

Cada hook recebe um objeto `LifecycleEvent` com as seguintes propriedades:

| Propriedade | Descrição                                                                                   |
| ----------- | ------------------------------------------------------------------------------------------- |
| `provider`  | Nome do provedor (ex: `'mercadopago'`, `'abacatepay'`).                                     |
| `resource`  | Recurso operado (ex: `'clientes'`, `'cobrancas'`, `'checkout'`).                            |
| `operation` | Operação executada (ex: `'create'`, `'get'`, `'update'`, `'list'`, `'delete'`, `'cancel'`). |
| `input`     | Dados de entrada da operação.                                                               |
| `output`    | Dados de retorno da operação.                                                               |

### Hooks por operação

Você pode escutar eventos específicos de cada recurso e operação:

#### Clientes

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import {
  onClienteCreated,
  onClienteRetrieved,
  onClienteUpdated,
  onClienteListed,
  onClienteDeleted
} from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onClienteCreated(async (evt) => {
      await db.clientes.insert(evt.output)
    })
  ]
})
```

#### Cobranças

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import {
  onCobrancaCreated,
  onCobrancaRetrieved,
  onCobrancaUpdated,
  onCobrancaListed,
  onCobrancaCancelled
} from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onCobrancaCreated(async (evt) => {
      await enviarEmailDeConfirmacao(evt.output.cliente.email)
    })
  ]
})
```

#### Checkout

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { onCheckoutCreated } from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onCheckoutCreated(async (evt) => {
      analytics.track('checkout_iniciado', { url: evt.output })
    })
  ]
})
```

### Hooks por recurso (genéricos)

Se quiser escutar **todas** as operações de um recurso, use os hooks de recurso:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { onCliente, onCobranca, onCheckout } from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onCobranca(async (evt) => {
      // Dispara para create, get, update, list, cancel
      await auditLog.register({
        provider: evt.provider,
        operation: evt.operation,
        cobrancaId: evt.output?.id
      })
    })
  ]
})
```

### Hook genérico customizado

Para casos mais específicos, use `onLifecycleEvent` para filtrar manualmente por recurso e operação:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { onLifecycleEvent } from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onLifecycleEvent('cobrancas', 'create', async (evt) => {
      // Mesmo comportamento de onCobrancaCreated
      await cache.invalidate(`cliente:${evt.output.cliente.id}`)
    })
  ]
})
```

## Webhook hooks

Enquanto os lifecycle hooks reagem a ações que **você** realiza via API, os webhook hooks reagem a eventos que acontecem **no provedor** (ex: cliente pagou, boleto venceu, assinatura foi renovada).

### Eventos canônicos

O **pagamentos.dev** normaliza os eventos de diferentes provedores em nomes canônicos. Os principais eventos disponíveis são:

* `pagamento.realizado`
* `pagamento.falhou`
* `cobranca.vencida`
* `cobranca.cancelada`
* `cobranca.disputada`
* `assinatura.ativada`
* `assinatura.cancelada`
* `assinatura.renovada`
* `transferencia.envio`
* `transferencia.falhou`
* `desembolso.envio`
* `desembolso.falhou`

### Usando `onWebhookEvent`

Registre um handler para um evento específico:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { onWebhookEvent } from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    onWebhookEvent('pagamento.realizado', async (event) => {
      event.event  // 'pagamento.realizado'
      event.data   // { cobranca: Cobranca; cliente?: Cliente }
      event.raw    // payload original do provedor

      await db.pedidos.update({
        cobrancaId: event.data.cobranca.id,
        status: 'pago'
      })
    })
  ]
})
```

### Aliases curinga

Você pode usar padrões curinga para escutar múltiplos eventos de uma vez:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { onWebhookEvent } from 'pagamentos'

const pg = new Pagamentos({
  providers: [/* ... */],
  hooks: [
    // Todos os eventos de pagamento
    onWebhookEvent('pagamento.*', async (event) => {
      if (event.event === 'pagamento.realizado') {
        await liberarAcesso(event.data.cobranca.id)
      } else if (event.event === 'pagamento.falhou') {
        await notificarCliente(event.data.cobranca.cliente)
      }
    }),

    // Todos os eventos de cobrança
    onWebhookEvent('cobranca.*', async (event) => {
      await auditLog.register({ tipo: event.event, dados: event.data })
    }),

    // Catch-all: qualquer evento
    onWebhookEvent('*', async (event) => {
      console.log('Evento recebido:', event.event, event.data)
    })
  ]
})
```

<Info>
  Para mais detalhes sobre como receber e validar webhooks, consulte a página dedicada a [Webhooks](/features/webhooks).
</Info>

## Exemplo prático combinado

Aqui está um exemplo completo que combina lifecycle hooks e webhook hooks para gerenciar o ciclo de vida de uma cobrança:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import {
  Pagamentos,
  mercadopago,
  onCobrancaCreated,
  onWebhookEvent
} from 'pagamentos'

const pg = new Pagamentos({
  providers: [mercadopago({
    accessToken: process.env.MP_ACCESS_TOKEN,
    signingSecret: process.env.MP_SIGNING_SECRET
  })],
  hooks: [
    // 1. Lifecycle: quando criamos a cobrança
    onCobrancaCreated(async (evt) => {
      await db.cobrancas.create({
        idempotencyKey: crypto.randomUUID(),
        id: evt.output.id,
        valor: evt.input.valor,
        status: 'pendente',
        cliente: evt.input.cliente
      })

      await enviarEmailDePixGerado({
        email: evt.input.cliente.email,
        qrCode: evt.output.pix.qrCode
      })
    }),

    // 2. Webhook: quando o provedor notifica que foi pago
    onWebhookEvent('pagamento.realizado', async (event) => {
      await db.cobrancas.update({
        id: event.data.cobranca.id,
        status: 'pago',
        pagoEm: new Date()
      })

      await liberarProduto(event.data.cobranca.id)
      await enviarComprovante(event.data.cliente?.email)
    }),

    // 3. Webhook: quando a cobrança vence
    onWebhookEvent('cobranca.vencida', async (event) => {
      await db.cobrancas.update({
        id: event.data.cobranca.id,
        status: 'vencido'
      })

      await enviarLembreteDeVencimento(event.data.cobranca.cliente)
    })
  ]
})
```

Neste exemplo:

1. O **lifecycle hook** `onCobrancaCreated` garante que toda cobrança criada seja salva no banco de dados local e que o cliente receba o e-mail com o QR Code.
2. O **webhook hook** `pagamento.realizado` atualiza o status no banco e libera o produto assim que o pagamento é confirmado pelo provedor.
3. O **webhook hook** `cobranca.vencida` trata cobranças não pagas dentro do prazo.

## Dicas e boas práticas

* **Hooks são síncronos ou assíncronos**: handlers podem retornar `void` ou `Promise<void>`. O SDK aguarda a conclusão dos hooks assíncronos.
* **Evite lógica pesada nos hooks**: se o processamento for longo, considere enfileirar em um background job para não bloquear a resposta da API ou do webhook.
* **Idempotência em webhooks**: provedores podem enviar o mesmo evento múltiplas vezes. Verifique se o evento já foi processado usando o `event.id`.
* **Tipagem forte**: os hooks de webhook são totalmente tipados. Ao usar eventos canônicos, o TypeScript infere corretamente o formato de `event.data`.
