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

# Webhooks da NyxPag: visão geral

> Como a NyxPag avisa o seu servidor quando um Pix muda de estado: configuração, regras da URL, entrega, retentativas e boas práticas.

Em vez de perguntar a cada segundo se o Pix foi pago, você deixa a NyxPag avisar. Quando uma transação muda de estado, a gente envia um `POST` assinado para a sua URL, e você reage.

É o caminho recomendado para confirmar pagamentos: mais rápido que consultar, e não gasta a cota de 100 requisições por minuto da sua chave.

## Como funciona

<Steps>
  <Step title="Você registra uma URL">
    No dashboard, ou no campo `webhookUrl` da própria requisição.
  </Step>

  <Step title="Algo acontece">
    Um Pix é pago, uma transferência falha, uma contestação é aberta.
  </Step>

  <Step title="A NyxPag envia um POST">
    O corpo é JSON e o cabeçalho `X-NyxPag-Signature` prova a origem.
  </Step>

  <Step title="Você valida e responde 2xx">
    Se não responder `2xx`, a gente tenta de novo, até 8 vezes.
  </Step>
</Steps>

## Eventos

| Evento | Quando | Página |
| - | - | - |
| `transaction.approved` | Pix pago ou transferência enviada | [transaction.\*](/webhooks/transacoes) |
| `transaction.failed` | Operação falhou de forma definitiva | [transaction.\*](/webhooks/transacoes) |
| `transaction.cancelled` | Cobrança cancelada ou expirada | [transaction.\*](/webhooks/transacoes) |
| `med.created` | Contestação MED aberta, valor retido | [med.\*](/webhooks/med) |
| `med.updated` | Situação da contestação mudou | [med.\*](/webhooks/med) |

## Configurar

Há duas formas, e você pode combinar.

<Tabs>
  <Tab title="Endpoint no dashboard">
    É o jeito recomendado, porque gera o **segredo de assinatura**.

    <Steps>
      <Step title="Abra Webhooks">
        Acesse [Dashboard → Webhooks](https://nyxpag.com.br/dashboard/webhooks).
      </Step>

      <Step title="Informe a URL e a chave vinculada">
        Em **URL do endpoint**, cole algo como `https://seusite.com.br/webhooks/nyxpag` e escolha a chave de API a que esse endpoint pertence.
      </Step>

      <Step title="Copie o segredo">
        O segredo de assinatura aparece **uma única vez**. Guarde no seu cofre de segredos. Se perder, use **Rotacionar segredo**.
      </Step>
    </Steps>

    Toda operação criada com essa chave passa a notificar esse endpoint.
  </Tab>

  <Tab title="webhookUrl na requisição">
    Envie `webhookUrl` ao criar a [cobrança](/guides/pix/receber) ou a [transferência](/guides/pix/transferir). Vale só para aquela operação e tem prioridade sobre o endpoint da chave.

    ```json theme={"dark"}
    {
      "amount": 149.90,
      "externalId": "PEDIDO-1042",
      "webhookUrl": "https://seusite.com.br/webhooks/nyxpag",
      "payer": { "name": "Maria Silva", "document": "52998224725" }
    }
    ```

    Útil para rotear por pedido, tenant ou ambiente.
  </Tab>
</Tabs>

<Note>
  Se a operação não tem `webhookUrl` e a chave não tem endpoint ativo, nenhum webhook é enviado. Você ainda consulta o estado por [`GET /transactions/{id}`](/api-reference/transações/verificar-transação).
</Note>

## Regras da URL

A NyxPag recusa URLs inseguras na hora de configurar. Para passar na validação:

| Regra | Detalhe |
| - | - |
| HTTPS | Obrigatório. `http://` é recusado |
| Porta | Somente a padrão (443) |
| Sem credenciais | Nada de `https://usuario:senha@...` |
| Sem fragmento | Nada de `#algo` no final |
| Rede pública | `localhost`, IPs privados e hosts que resolvem para rede privada são recusados |
| Sem redirecionamento | Redirecionamentos (`3xx`) **não são seguidos** e contam como falha |

<Warning>
  Se o seu endpoint redireciona (por exemplo de `www` para o domínio raiz, ou de `http` para `https`), a entrega falha. Cadastre a URL final, a que responde `2xx` direto.
</Warning>

## Entrega e retentativas

A NyxPag considera a entrega bem-sucedida somente com resposta `2xx` em até **8 segundos**. Qualquer outra coisa, incluindo timeout, `3xx`, `4xx` e `5xx`, conta como falha e agenda uma nova tentativa.

| Tentativa que falhou | Próxima tentativa em |
| - | - |
| 1ª | cerca de 30 segundos |
| 2ª | cerca de 1 minuto |
| 3ª | cerca de 2 minutos |
| 4ª | cerca de 4 minutos |
| 5ª | cerca de 8 minutos |
| 6ª | cerca de 16 minutos |
| 7ª | cerca de 32 minutos |
| 8ª | acabou: a entrega é marcada como falha |

A espera dobra a cada falha e nunca passa de 1 hora. Os tempos são aproximados porque dependem do ciclo do reenvio.

<Warning>
  Depois da 8ª falha a NyxPag **não tenta mais**. Se o seu servidor ficou fora do ar por muito tempo, concilie com [`GET /transactions`](/api-reference/transações/listar-transações) filtrando por `status`. Veja [Acompanhar transações](/guides/pix/acompanhar).
</Warning>

### O que isso significa para o seu código

* **Entrega ao menos uma vez.** O mesmo evento pode chegar duas ou mais vezes. Deduplique.
* **Sem garantia de ordem.** Um evento antigo pode chegar depois de um novo.
* **Responda rápido.** Grave o evento, responda `2xx` e processe fora do request.

## Boas práticas

<Steps>
  <Step title="Valide a assinatura primeiro">
    Antes de qualquer efeito. Veja [Validando a assinatura](/webhooks/assinatura).
  </Step>

  <Step title="Deduplique de forma durável">
    Para `transaction.*`, use o `id` do evento. Para `med.*`, que não tem `id` de evento, use o cabeçalho `X-NyxPag-Delivery`.
  </Step>

  <Step title="Persista antes de responder 2xx">
    Se você responde `200` e a fila cai logo depois, o evento se perdeu e a NyxPag não tenta de novo.
  </Step>

  <Step title="Reconcilie periodicamente">
    Um job que lista as transações recentes cobre o caso de uma entrega ter esgotado as tentativas.
  </Step>

  <Step title="Não registre dados pessoais">
    O corpo traz nome, CPF e e-mail do pagador. Evite gravar em logs abertos.
  </Step>
</Steps>

## Testando localmente

Como `localhost` é recusado, use um túnel HTTPS para expor a sua máquina:

```bash theme={"dark"}
# com ngrok
ngrok http 3000

# ou com cloudflared
cloudflared tunnel --url http://localhost:3000
```

Cadastre a URL `https://...` que o túnel devolver como endpoint em **Dashboard → Webhooks**. Para disparar um evento real, crie uma cobrança de valor baixo e pague pelo seu banco.

<Note>
  Não existe um botão "enviar evento de teste". Por não haver sandbox, o teste é uma cobrança real de valor baixo. Veja [Ambientes](/guides/comece-aqui/ambientes).
</Note>

<CardGroup cols={2}>
  <Card title="Validando a assinatura" icon="shield-check" href="/webhooks/assinatura">
    HMAC-SHA256, vetor de teste e código em Node, Python e PHP.
  </Card>

  <Card title="Eventos de transação" icon="receipt" href="/webhooks/transacoes">
    Payload completo de `transaction.approved`, `failed` e `cancelled`.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.