MIVY DocsEventos em tempo realWebSocket

WebSocket

Mantenha seu servidor conectado à Mivy para receber confirmações de pagamento e eventos da loja sem consultar a API continuamente.

Leitura de 6 min
WSSwss://api.mivy.com.br/api/realtime/wsToken mivy_ws_

#Crie uma conexão

O token de WebSocket é diferente da chave mivy_live_ da API. A conexão só recebe eventos da loja que a criou. Tokens permanentes são aceitos em clientes de servidor; o teste no navegador usa um ticket de uso único emitido pelo painel.

  1. Abra Integrações → WebSocket no painel e clique em Nova conexão.
  2. Escolha os eventos e a validade da conexão.
  3. Salve o token mivy_ws_ como MIVY_WS_TOKEN no ambiente do seu servidor.
  4. Use Testar conexão → Enviar teste para receber connection.test.

#Autentique na primeira mensagem

Conecte ao endereço WSS acima e envie o JSON de autenticação em até dez segundos. Não coloque o token na URL nem em código do navegador.

Primeira mensagemJSON
{
  "op": "auth",
  "token": "mivy_ws_SEU_TOKEN"
}
Resposta ready — exemploJSON
{
  "op": "ready",
  "connectionId": "ID_DA_CONEXAO",
  "events": [
    "payment.approved"
  ],
  "cursor": "42",
  "heartbeatSeconds": 20
}

#Receba os eventos

Cada mensagem op=event traz uma sequência e o evento da loja. data.paymentId identifica o Pix da API; data.orderId identifica um pedido da loja. Os dados ilustrativos abaixo seguem o mesmo contrato dos webhooks.

EventoDescrição
payment.createdPix ou cobrança de pedido criado.
payment.approvedPagamento confirmado no backend.
payment.expiredExpiração confirmada.
payment.failedFalha ou cancelamento confirmado.
deposit.approvedCrédito confirmado na carteira.
plan.activatedPlano ativado na conta.
connection.testTeste enviado para a conexão selecionada.
Evento recebido — exemploJSON
{
  "op": "event",
  "sequence": "43",
  "event": {
    "id": "payment.approved:ID_DO_PAGAMENTO",
    "type": "payment.approved",
    "createdAt": "2026-10-17T22:05:00.000Z",
    "storeId": "ID_DA_SUA_LOJA",
    "data": {
      "id": "ID_DO_PAGAMENTO",
      "status": "PAID",
      "amount": 100,
      "requestedAmount": 100,
      "fee": 1.35,
      "netAmount": 98.65,
      "currency": "BRL",
      "description": "Pedido 123",
      "passFee": false,
      "validityMinutes": 30,
      "expiresAt": "2026-10-17T22:30:00.000Z",
      "paidAt": "2026-10-17T22:05:00.000Z",
      "createdAt": "2026-10-17T22:00:00.000Z",
      "paymentId": "ID_DO_PAGAMENTO",
      "source": "api"
    }
  }
}

#Retome após uma desconexão

Sem after, a conexão começa no presente. Para retomar, envie em after a última sequência que seu sistema processou e persistiu com sucesso. A sequência é uma string numérica, pode conter saltos e não deve ser convertida para number JavaScript.

Use event.id como identificador idempotente. Só salve o cursor depois de concluir o tratamento. O servidor consulta eventos novos aproximadamente a cada dois segundos; mensagens podem se repetir após uma reconexão.

Autenticação com retomadaJSON
{
  "op": "auth",
  "token": "mivy_ws_SEU_TOKEN",
  "after": "43"
}

#Cliente Node.js com reconexão

O arquivo abaixo é o mesmo cliente genérico distribuído pela Mivy. Ele autentica, responde aos sinais do WebSocket e reconecta com espera progressiva. Forneça onEvent para tratar eventos e saveCursor para persistir a sequência.

InstalaçãoShell
npm install ws
node --env-file=.env bot.cjs
bot.cjs — escutar eventos reaisJavaScript
const { connectMivy } = require('./mivy-realtime.cjs');
const { readFile, writeFile, mkdir } = require('node:fs/promises');
const { dirname } = require('node:path');

(async () => {
  const file = process.env.MIVY_CURSOR_FILE || './data/mivy-cursor.txt';
  let after;
  try { after = (await readFile(file, 'utf8')).trim(); }
  catch (error) { if (error.code !== 'ENOENT') throw error; }
  const client = connectMivy({
    token: process.env.MIVY_WS_TOKEN,
    after,
    onEvent: async event => {
      // Faça seu tratamento idempotente por event.id antes de retornar.
      console.log(event.type, event.id);
    },
    saveCursor: async cursor => {
      await mkdir(dirname(file), { recursive: true });
      await writeFile(file, cursor, { mode: 0o600 });
    },
    onStatus: status => console.log(status)
  });
  process.on('SIGTERM', () => { void client.stop(); });
})();

#Protocolo e limites

Depois de autenticar, o único comando permitido é {"op":"ping"}, respondido com op=pong. O canal não executa depósitos nem consultas de saldo: use as rotas HTTP para essas operações. O servidor usa ping/pong WebSocket a cada 20 segundos; a biblioteca ws responde automaticamente.

Código / limiteSignificado
4000JSON inválido ou comando não permitido.
4001Autenticação inválida ou não enviada a tempo.
4003Token pausado, excluído, expirado ou conta indisponível.
4008Limite atingido; aguarde antes de reconectar.
4009Cursor inválido; revise o cursor salvo.
1012 / 1013Reinício ou indisponibilidade; reconecte com espera progressiva.
SessõesAté três por token e vinte por loja; até vinte credenciais por loja.
MensagensFrames de até 4 KiB; até vinte mensagens a cada dez segundos.
Encontrou algo que pode ser melhorado? Consulte a central de ajuda.