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

# WebSocket na prática

> Conecte um bot ou worker à WovePay e receba payment.paid sem webhook HTTP.

Tutorial focado em **implementar** o cliente WebSocket. Referência completa do protocolo: [guia de WebSocket](/api-reference/guides/websocket).

Ideal para **bots Discord/Telegram**, workers em VPS ou qualquer processo que não expõe porta 443.

## 1. Pré-requisitos

* Chave de API `wp_live_...` (a mesma que você usa na REST API)
* Node 18+ ou Python 3.10+
* Processo rodando no **servidor** — nunca no browser

<Warning>
  Não coloque `wp_live_...` em frontend, app mobile ou repositório público. Use variável de ambiente (`WovePay_API_KEY`).
</Warning>

## 2. Conectar e autenticar

Endpoint:

```
wss://ws.wovepay.com/v1
```

Três formas de autenticar (escolha uma):

| Modo         | Exemplo                                                 |
| ------------ | ------------------------------------------------------- |
| Query string | `wss://ws.wovepay.com/v1?token=wp_live_...`             |
| Header       | `Authorization: Bearer wp_live_...`                     |
| Mensagem     | `{ "action": "authenticate", "apiKey": "wp_live_..." }` |

Você deve receber:

```json theme={null}
{ "event": "authenticated", "version": "1" }
```

## 3. Inscrever-se em eventos

Após autenticar, envie:

```json theme={null}
{ "action": "subscribe", "pattern": "payment.*" }
```

Resposta:

```json theme={null}
{ "event": "subscribed", "pattern": "payment.*" }
```

Patterns úteis: `payment.*`, `transfer.*`, `refund.*`, `payment_link.paid` (via `payment.*`), `*`.

Para um pagamento específico:

```json theme={null}
{ "action": "subscribe", "paymentId": "clx_transacao" }
```

## 4. Node.js

```bash theme={null}
npm install ws
```

```javascript theme={null}
import WebSocket from "ws";

const API_KEY = process.env.WovePay_API_KEY;
const seen = new Set();

const ws = new WebSocket(`wss://ws.wovepay.com/v1?token=${API_KEY}`);

ws.on("open", () => {
  console.log("conectado");
  ws.send(JSON.stringify({ action: "subscribe", pattern: "payment.*" }));
});

ws.on("message", (raw) => {
  const msg = JSON.parse(String(raw));

  // Obrigatório: responder ao heartbeat do servidor
  if (msg.event === "ping") {
    ws.send(JSON.stringify({ action: "ping" }));
    return;
  }

  if (msg.event === "error") {
    console.error("erro:", msg.code);
    return;
  }

  if (!msg.id || seen.has(msg.id)) return;
  seen.add(msg.id);

  if (msg.event === "payment.paid") {
    console.log("PIX pago:", msg.data.id, msg.data.amount);
  }

  ws.send(JSON.stringify({ action: "ack", id: msg.id }));
});

ws.on("close", () => {
  console.log("desconectado — reconecte com backoff (1s → 30s)");
});
```

## 5. Python

```bash theme={null}
pip install websockets
```

```python theme={null}
import asyncio
import json
import os
import websockets

API_KEY = os.environ["WovePay_API_KEY"]
seen = set()

async def main():
    uri = f"wss://ws.wovepay.com/v1?token={API_KEY}"
    async with websockets.connect(uri) as ws:
        await ws.send(json.dumps({"action": "subscribe", "pattern": "payment.*"}))

        async for raw in ws:
            msg = json.loads(raw)
            event = msg.get("event")

            if event == "ping":
                await ws.send(json.dumps({"action": "ping"}))
                continue

            if event == "error":
                print("erro:", msg.get("code"))
                continue

            delivery_id = msg.get("id")
            if not delivery_id or delivery_id in seen:
                continue
            seen.add(delivery_id)

            if event == "payment.paid":
                print("PIX pago:", msg["data"])

            await ws.send(json.dumps({"action": "ack", "id": delivery_id}))

asyncio.run(main())
```

## 6. Testar ponta a ponta

<Steps>
  <Step title="Exportar a API key">
    ```bash theme={null}
    export WovePay_API_KEY=wp_live_SUA_CHAVE
    ```
  </Step>

  <Step title="Rodar o script">
    `node bot.js` ou `python bot.py` — aguarde `authenticated` / `subscribed`.
  </Step>

  <Step title="Criar um PIX de teste">
    Use a **mesma** API key:

    ```bash theme={null}
    curl -X POST https://api.wovepay.com/v1/payment-pix/create \
      -H "X-API-Key: $WovePay_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"amount": 100, "externalReference": "ws-test"}'
    ```
  </Step>

  <Step title="Validar eventos">
    Você deve receber `payment.created`. Após pagar o QR, `payment.paid`.
  </Step>
</Steps>

## 7. Eventos que você provavelmente precisa

| Evento                | Quando usar                    |
| --------------------- | ------------------------------ |
| `payment.paid`        | PIX recebido — liberar pedido  |
| `payment.created`     | Cobrança registrada (opcional) |
| `payment.pix.expired` | QR expirou — cancelar checkout |
| `transfer.completed`  | Saque PIX concluído            |
| `payment_link.paid`   | Link de pagamento pago         |
| `refund.completed`    | Reembolso confirmado           |
| `med.created`         | Disputa MED aberta             |

Lista completa: [guia de WebSocket — eventos](/api-reference/guides/websocket#eventos).

## 8. Escopo por API key

Conexões com `wp_live_...` recebem eventos das transações criadas pela **mesma API key**. Se o evento não chega, confira se a cobrança foi criada com a chave usada na conexão.

## Checklist

* [ ] `WovePay_API_KEY` em variável de ambiente
* [ ] Handler de `ping` → `{ "action": "ping" }`
* [ ] Idempotência pelo `id` da entrega
* [ ] `ack` após processar (opcional, recomendado)
* [ ] Reconexão com backoff após `close`
* [ ] REST API como fallback após downtime (`GET /payment-pix/get/:id`)

## Próximo passo

[Guia completo WebSocket](/api-reference/guides/websocket) · [Criar cobrança PIX](/pages/guides/receber-pix) · [Webhooks HTTP](/pages/guides/webhooks-pratica) se tiver URL pública
