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

# Webhooks

> Receba notificações automáticas quando algo acontecer com suas transações PIX

## O que são Webhooks?

Webhooks são notificações automáticas que a StylePay envia para sua aplicação quando uma transação PIX muda de status. É como receber um SMS avisando que um pagamento foi confirmado.

<Info>
  **Em resumo:** Você informa uma URL do seu site, e a StylePay manda uma mensagem para essa URL sempre que algo importante acontecer.
</Info>

## Passo 1: Configure sua URL

Ao criar uma transação, informe onde quer receber as notificações:

<CodeGroup>
  ```json Criar QR Code (Recebimento) theme={null}
  {
    "amount": 100.50,
    "external_id": "pedido_123",
    "postbackUrl": "https://seusite.com/webhook",
    ...
  }
  ```

  ```json Fazer Pagamento theme={null}
  {
    "amount": 50.00,
    "description": "Pagamento",
    "callbackUrl": "https://seusite.com/webhook",
    ...
  }
  ```
</CodeGroup>

<Tip>
  Você pode usar a mesma URL para todos os tipos de notificação.
</Tip>

## Passo 2: Entenda os Eventos

A StylePay envia 3 tipos principais de notificação:

<CardGroup cols={3}>
  <Card title="Recebimento" icon="arrow-down">
    Quando alguém paga seu QR Code
  </Card>

  <Card title="Pagamento" icon="arrow-up">
    Quando seu pagamento é processado
  </Card>

  <Card title="Estorno" icon="rotate-left">
    Quando um recebimento é devolvido
  </Card>
</CardGroup>

## Passo 3: Receba as Notificações

### 📥 Recebimento Confirmado

Quando alguém paga seu QR Code:

```json theme={null}
{
  "event": "pix.cashin.paid",
  "requestNumber": "pedido_123",
  "statusTransaction": "PAID",
  "idTransaction": "uuid-da-transacao",
  "value": 100.50,
  "debtorName": "João Silva",
  "date": "2025-01-01T10:00:00.000Z"
}
```

**Campos importantes:**

* `event`: Sempre será `pix.cashin.paid` para recebimentos
* `requestNumber`: Seu código de pedido
* `value`: Quanto você recebeu
* `debtorName`: Nome de quem pagou

### 📤 Pagamento Realizado

Quando seu pagamento é concluído:

```json theme={null}
{
  "event": "pix.cashout.paid",
  "idTransaction": "uuid-da-transacao",
  "statusTransaction": "PAID",
  "value": 50.00,
  "date": "2025-01-01T11:00:00.000Z"
}
```

### ❌ Pagamento Cancelado

Quando seu pagamento falha:

```json theme={null}
{
  "event": "pix.cashout.cancelled",
  "idTransaction": "uuid-da-transacao",
  "statusTransaction": "CANCELLED",
  "value": 50.00,
  "message": "NOT_PAID"
}
```

### 🔄 Estorno de Recebimento

Quando um pagamento que você recebeu é devolvido:

```json theme={null}
{
  "event": "pix.refund.paid_out",
  "requestNumber": "pedido_123",
  "statusTransaction": "CANCELLED",
  "value": 100.50
}
```

## Passo 4: Crie seu Endpoint

Seu site precisa ter uma página que receba essas notificações. Aqui está um exemplo simples:

<CodeGroup>
  ```javascript Node.js (Simples) theme={null}
  // Usando Express.js
  const express = require('express');
  const app = express();

  app.use(express.json());

  app.post('/webhook', (req, res) => {
    const { event, value, requestNumber } = req.body;
    
    // Identificar o tipo de evento
    if (event === 'pix.cashin.paid') {
      console.log(`✅ Recebido: R$ ${value} - Pedido: ${requestNumber}`);
      // Atualizar seu banco de dados aqui
    }
    
    if (event === 'pix.cashout.paid') {
      console.log(`✅ Pagamento enviado: R$ ${value}`);
    }
    
    if (event === 'pix.cashout.cancelled') {
      console.log(`❌ Pagamento cancelado: R$ ${value}`);
    }
    
    // IMPORTANTE: Sempre responda com sucesso
    res.json({ ok: true });
  });

  app.listen(3000);
  ```

  ```python Python (Simples) theme={null}
  from flask import Flask, request, jsonify

  app = Flask(__name__)

  @app.route('/webhook', methods=['POST'])
  def webhook():
      data = request.get_json()
      
      event = data.get('event')
      value = data.get('value')
      request_number = data.get('requestNumber')
      
      # Identificar o tipo de evento
      if event == 'pix.cashin.paid':
          print(f"✅ Recebido: R$ {value} - Pedido: {request_number}")
          # Atualizar seu banco de dados aqui
      
      if event == 'pix.cashout.paid':
          print(f"✅ Pagamento enviado: R$ {value}")
      
      if event == 'pix.cashout.cancelled':
          print(f"❌ Pagamento cancelado: R$ {value}")
      
      # IMPORTANTE: Sempre responda com sucesso
      return jsonify({'ok': True}), 200

  if __name__ == '__main__':
      app.run(port=3000)
  ```

  ```php PHP (Simples) theme={null}
  <?php
  // webhook.php

  $data = json_decode(file_get_contents('php://input'), true);

  $event = $data['event'];
  $value = $data['value'];
  $requestNumber = $data['requestNumber'] ?? null;

  // Identificar o tipo de evento
  if ($event === 'pix.cashin.paid') {
      error_log("✅ Recebido: R$ $value - Pedido: $requestNumber");
      // Atualizar seu banco de dados aqui
  }

  if ($event === 'pix.cashout.paid') {
      error_log("✅ Pagamento enviado: R$ $value");
  }

  if ($event === 'pix.cashout.cancelled') {
      error_log("❌ Pagamento cancelado: R$ $value");
  }

  // IMPORTANTE: Sempre responda com sucesso
  header('Content-Type: application/json');
  echo json_encode(['ok' => true]);
  ?>
  ```
</CodeGroup>

## 5 Regras Importantes

<Steps>
  <Step title="Sempre responda rapidamente">
    Retorne status `200` em menos de 5 segundos. Se precisar fazer algo demorado, faça depois de responder.

    ```javascript theme={null}
    // ✅ Certo
    res.json({ ok: true }); // Responde primeiro
    atualizarBancoDeDados(); // Faz depois

    // ❌ Errado
    atualizarBancoDeDados(); // Demora muito
    res.json({ ok: true }); // Responde depois
    ```
  </Step>

  <Step title="Evite processar duas vezes">
    Guarde o `idTransaction` para não processar a mesma notificação mais de uma vez.

    ```javascript theme={null}
    // Verificar se já processou
    if (jaProcessei(idTransaction)) {
      return res.json({ ok: true });
    }
    ```
  </Step>

  <Step title="Use HTTPS">
    Sua URL precisa começar com `https://` (não `http://`)
  </Step>

  <Step title="Verifique o evento">
    Sempre confira o campo `event` antes de processar

    ```javascript theme={null}
    if (event === 'pix.cashin.paid') {
      // Processar recebimento
    }
    ```
  </Step>

  <Step title="Salve tudo">
    Guarde um registro de todas as notificações recebidas para consultar depois
  </Step>
</Steps>

## Testando em Casa

Para testar enquanto desenvolve:

<Steps>
  <Step title="Instale o ngrok">
    Baixe em: [https://ngrok.com/download](https://ngrok.com/download)
  </Step>

  <Step title="Execute seu servidor">
    ```bash theme={null}
    node seu-servidor.js
    ```
  </Step>

  <Step title="Abra um túnel">
    ```bash theme={null}
    ngrok http 3000
    ```
  </Step>

  <Step title="Use a URL gerada">
    ```
    https://abc123.ngrok.io/webhook
    ```

    Cole essa URL no `postbackUrl` ou `callbackUrl`
  </Step>
</Steps>

## Exemplo Completo

Aqui está um exemplo completo e funcional:

```javascript theme={null}
const express = require('express');
const app = express();

app.use(express.json());

// Simulação de banco de dados
const processados = new Set();

app.post('/webhook', async (req, res) => {
  const { event, idTransaction, value, requestNumber, statusTransaction } = req.body;
  
  console.log('📩 Webhook recebido:', event);
  
  // 1. Evitar processar duas vezes
  if (processados.has(idTransaction)) {
    console.log('⚠️  Já processado anteriormente');
    return res.json({ ok: true });
  }
  
  // 2. Responder rapidamente
  res.json({ ok: true });
  
  // 3. Processar o webhook
  try {
    if (event === 'pix.cashin.paid') {
      console.log(`✅ Pagamento recebido!`);
      console.log(`   Valor: R$ ${value}`);
      console.log(`   Pedido: ${requestNumber}`);
      
      // Atualizar pedido no banco de dados
      // await db.pedidos.update(requestNumber, { status: 'pago' });
    }
    
    if (event === 'pix.cashout.paid') {
      console.log(`✅ Pagamento enviado com sucesso!`);
      console.log(`   Valor: R$ ${value}`);
      
      // Atualizar transação no banco de dados
      // await db.transacoes.update(idTransaction, { status: 'concluido' });
    }
    
    if (event === 'pix.cashout.cancelled') {
      console.log(`❌ Pagamento cancelado`);
      console.log(`   Valor: R$ ${value}`);
      
      // Marcar como cancelado
      // await db.transacoes.update(idTransaction, { status: 'cancelado' });
    }
    
    if (event === 'pix.refund.paid_out') {
      console.log(`🔄 Estorno processado`);
      console.log(`   Valor: R$ ${value}`);
      console.log(`   Pedido: ${requestNumber}`);
      
      // Processar estorno
      // await db.pedidos.update(requestNumber, { status: 'estornado' });
    }
    
    // Marcar como processado
    processados.add(idTransaction);
    
  } catch (error) {
    console.error('❌ Erro ao processar:', error);
  }
});

app.listen(3000, () => {
  console.log('🚀 Servidor rodando na porta 3000');
  console.log('📍 Webhook: http://localhost:3000/webhook');
});
```

## Dúvidas Frequentes

<AccordionGroup>
  <Accordion title="Minha URL precisa ter autenticação?">
    Não é obrigatório, mas é recomendado. Você pode adicionar um token secreto na URL ou verificar um header específico.
  </Accordion>

  <Accordion title="E se meu servidor estiver fora do ar?">
    A StylePay tentará reenviar a notificação algumas vezes. Por isso é importante ter um servidor estável.
  </Accordion>

  <Accordion title="Posso usar a mesma URL para tudo?">
    Sim! Você usa o campo `event` para saber que tipo de notificação recebeu.
  </Accordion>

  <Accordion title="Como sei se recebi todas as notificações?">
    Você pode consultar o status da transação pela API usando o `idTransaction` se precisar confirmar.
  </Accordion>

  <Accordion title="Preciso responder com algum dado específico?">
    Não. Basta retornar status HTTP 200. O conteúdo da resposta não importa.
  </Accordion>
</AccordionGroup>

## Precisa de Ajuda?

<CardGroup cols={2}>
  <Card title="Suporte Técnico" icon="headset">
    [suporte@stylepay.com.br](mailto:suporte@stylepay.com.br)
  </Card>

  <Card title="WhatsApp" icon="whatsapp">
    +55 11 9999-9999
  </Card>
</CardGroup>
