Skip to main content
Webhooks permitem que você receba notificações em tempo real quando eventos ocorrem na sua conta WhatsApp, como novas mensagens, atualizações de status e mudanças de conexão.

Como Funciona

Quando um evento ocorre, a Oxenty API envia um POST request para a URL configurada com os dados do evento.

Configurando um Webhook

Via Dashboard

  1. Acesse oxenty.api.br/login
  2. Crie/edite uma sessão
  3. Configure:
  • Webhook URL: Endpoint que receberá os eventos
  • Webhook Events: Quais eventos deseja receber

Via API

Webhooks são configurados por sessão.

Criar sessão já com webhook

curl -X POST "https://api.oxenty.api.br/api/sessions" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "minha-sessao",
    "webhookUrl": "https://seu-servidor.com/webhook",
    "webhookEvents": [
      "message.received",
      "message.sent",
      "message.delivered",
      "message.read",
      "session.connected",
      "session.disconnected"
    ]
  }'

Atualizar webhook de uma sessão existente

curl -X PUT "https://api.oxenty.api.br/api/sessions/{sessionId}" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://seu-servidor.com/webhook",
    "webhookEvents": [
      "message.received",
      "message.sent",
      "session.status_changed"
    ]
  }'
Resposta:
{
  "id": "sess_abc123",
  "name": "minha-sessao",
  "status": "DISCONNECTED",
  "webhookUrl": "https://seu-servidor.com/webhook",
  "webhookEvents": ["message.received", "message.sent", "..."],
  "webhookSecret": "whsec_xxxxxxxxxxxxxxxx",
  "hasWebhook": true
}
Guarde o webhookSecret em local seguro. Ele é usado para validar a autenticidade dos webhooks.

Eventos Disponíveis

Mensagens

EventoDescrição
message.receivedNova mensagem recebida
message.sentMensagem enviada com sucesso
message.deliveredMensagem entregue
message.readMensagem lida
message.failedFalha ao enviar mensagem
message.revokedMensagem apagada pelo remetente

Sessões

EventoDescrição
session.connectedSessão conectou ao WhatsApp
session.disconnectedSessão desconectou
session.qr_codeQR Code disponível
session.qr_updatedQR Code atualizado/rotacionado
session.status_changedMudança de status da sessão

Grupos

EventoDescrição
group.createdGrupo criado
group.participant.addedParticipante adicionado
group.participant.removedParticipante removido
group.updatedMetadados do grupo atualizados

Contatos

EventoDescrição
contact.updatedDados do contato atualizados
presence.updateStatus online/offline do contato
presence.updatedAtualização de presença (variação)

Payload do Webhook

Todos os webhooks seguem este formato:
{
  "id": "evt_xyz789",
  "type": "message.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "sessionId": "sess_abc123",
  "data": {
    // Dados específicos do evento
  }
}

Exemplo: message.received

{
  "id": "evt_xyz789",
  "type": "message.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "sessionId": "sess_abc123",
  "data": {
    "messageId": "msg_123",
    "from": "5511999999999@s.whatsapp.net",
    "fromName": "João Silva",
    "type": "text",
    "text": "Olá, tudo bem?",
    "timestamp": "2024-01-15T10:30:00.000Z",
    "isGroup": false
  }
}

Exemplo: message.status

{
  "id": "evt_abc456",
  "type": "message.status",
  "timestamp": "2024-01-15T10:31:00.000Z",
  "sessionId": "sess_abc123",
  "data": {
    "messageId": "msg_456",
    "to": "5511888888888@s.whatsapp.net",
    "status": "read",
    "timestamp": "2024-01-15T10:31:00.000Z"
  }
}

Exemplo: session.disconnected

{
  "id": "evt_def789",
  "type": "session.disconnected",
  "timestamp": "2024-01-15T10:35:00.000Z",
  "sessionId": "sess_abc123",
  "data": {
    "reason": "logged_out",
    "message": "Usuário deslogou do WhatsApp Web"
  }
}

Validando Webhooks

Para garantir que o webhook veio da Oxenty API, valide a assinatura:

Header de Assinatura

X-Oxenty-Signature: sha256=abc123...
X-Oxenty-Timestamp: 1704067200

Validação em Node.js

import crypto from 'crypto';

function validateWebhook(
  payload: string,
  signature: string,
  timestamp: string,
  secret: string
): boolean {
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(receivedSignature)
  );
}

// Uso no Express
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-oxenty-signature'] as string;
  const timestamp = req.headers['x-oxenty-timestamp'] as string;
  const payload = req.body.toString();
  
  if (!validateWebhook(payload, signature, timestamp, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(payload);
  // Processar evento...
  
  res.status(200).send('OK');
});

Validação em Python

import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)
WEBHOOK_SECRET = 'whsec_xxxxxxxx'

def validate_webhook(payload, signature, timestamp, secret):
    signed_payload = f"{timestamp}.{payload}"
    expected_signature = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    received_signature = signature.replace('sha256=', '')
    
    return hmac.compare_digest(expected_signature, received_signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Oxenty-Signature')
    timestamp = request.headers.get('X-Oxenty-Timestamp')
    payload = request.get_data(as_text=True)
    
    if not validate_webhook(payload, signature, timestamp, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    
    event = request.get_json()
    # Processar evento...
    
    return 'OK', 200

Retries e Falhas

Se seu endpoint retornar erro (status >= 400) ou timeout, a Oxenty API fará retries automáticos:
TentativaDelay
1Imediato
21 minuto
35 minutos
430 minutos
52 horas
Após 5 falhas consecutivas, o webhook é marcado como inativo e você receberá um email de notificação.
Responda com 200 OK o mais rápido possível. Processe eventos de forma assíncrona para evitar timeouts.

Boas Práticas

Retorne 200 OK imediatamente e processe o evento de forma assíncrona (usando filas como Redis, RabbitMQ, etc.).
Nunca processe webhooks sem validar a assinatura para evitar ataques.
Use o id do evento para evitar processar o mesmo evento duas vezes (pode haver retries).
Sempre use URLs HTTPS para receber webhooks. HTTP não é aceito em produção.

Testando Webhooks

Teste rápido

  1. Configure webhookUrl em uma sessão (via POST /sessions ou PUT /sessions/{id})
  2. Dispare um evento (ex.: enviar mensagem via POST /messages/text)
  3. Verifique se seu endpoint recebeu o payload

Ferramentas Úteis

  • webhook.site - Endpoint temporário para testes
  • ngrok - Expor localhost para a internet
  • Hookdeck - Proxy e debug de webhooks

Gerenciando Webhooks

Listar configurações

curl -X GET "https://api.oxenty.api.br/api/sessions?page=1&limit=20" \
  -H "X-API-Key: YOUR_API_KEY"

Atualizar Webhook (por sessão)

curl -X PUT "https://api.oxenty.api.br/api/sessions/sess_abc123" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://seu-servidor.com/webhook",
    "webhookEvents": ["message.received"],
    "regenerateSecret": true
  }'

Desativar Webhook

curl -X PUT "https://api.oxenty.api.br/api/sessions/sess_abc123" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": null,
    "webhookEvents": []
  }'