Os Webhooks permitem que você receba notificações automáticas quando eventos importantes acontecem no ConnectVets Notes, como quando uma transcrição é concluída ou falha.
Como Funcionam
Configuração
Nossa equipe configura os webhooks no seu sistema conforme suas necessidades
Eventos
Quando um evento ocorre (ex: transcrição concluída), enviamos uma requisição POST
Recebimento
Sua aplicação recebe a notificação e pode processar o evento imediatamente
Confirmação
Responda com status 200 para confirmar o recebimento
Eventos Disponíveis
note.transcription.completed
Disparado quando uma transcrição é finalizada com sucesso:
{
"event": "note.transcription.completed",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Rex",
"transcription_status": "completed",
"external_id": "CLIENTE_123",
"created_at": "2024-02-14T18:25:43Z",
"completed_at": "2024-02-14T18:30:23Z"
},
"timestamp": "2024-02-14T18:30:24Z",
"webhook_id": "wh_abc123def456"
}
note.transcription.failed
Disparado quando uma transcrição falha:
{
"event": "note.transcription.failed",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Rex",
"transcription_status": "failed",
"error": {
"code": "AUDIO_QUALITY_LOW",
"message": "Áudio com qualidade insuficiente para transcrição"
},
"external_id": "CLIENTE_123",
"created_at": "2024-02-14T18:25:43Z",
"failed_at": "2024-02-14T18:28:15Z"
},
"timestamp": "2024-02-14T18:28:16Z",
"webhook_id": "wh_abc123def456"
}
Implementação
Endpoint do Webhook
Sua aplicação deve ter um endpoint que aceite requisições POST:
app.post('/webhooks/connectvets', (req, res) => {
const { event, data, timestamp } = req.body;
console.log(`Evento recebido: ${event} em ${timestamp}`);
switch (event) {
case 'note.transcription.completed':
handleTranscriptionCompleted(data);
break;
case 'note.transcription.failed':
handleTranscriptionFailed(data);
break;
default:
console.log(`Evento não tratado: ${event}`);
}
// Resposta de confirmação
res.status(200).json({ received: true });
});
function handleTranscriptionCompleted(noteData) {
// Lógica para processar transcrição concluída
console.log(`Nota ${noteData.id} foi transcrita com sucesso`);
// Exemplo: notificar o usuário
notifyUser(noteData.external_id, 'Sua consulta foi transcrita!');
// Exemplo: atualizar banco local
updateLocalNote(noteData.id, { status: 'completed' });
}
function handleTranscriptionFailed(noteData) {
// Lógica para processar falha na transcrição
console.log(`Falha na transcrição da nota ${noteData.id}: ${noteData.error.message}`);
// Exemplo: notificar erro
notifyUser(noteData.external_id, 'Houve um problema na transcrição. Tente novamente.');
}
Segurança
Validação de Origem
Para garantir que o webhook vem do ConnectVets, valide o header de assinatura:
const crypto = require('crypto');
function validateWebhookSignature(payload, signature, secret) {
const computedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
const expectedSignature = `sha256=${computedSignature}`;
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/connectvets', (req, res) => {
const signature = req.headers['x-connectvets-signature'];
const payload = JSON.stringify(req.body);
if (!validateWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Processar webhook...
});
HTTPS Obrigatório
- Todos os webhooks devem usar HTTPS
- Certificados SSL válidos são obrigatórios
- URLs localhost não são aceitas em produção
Retry Logic
Como Funciona
Se seu endpoint não responder com status 2xx, reenviamos automaticamente:
| Tentativa | Delay |
| 1ª | Imediato |
| 2ª | 1 minuto |
| 3ª | 5 minutos |
| 4ª | 15 minutos |
| 5ª | 1 hora |
Idempotência
Implemente verificação de duplicatas usando o webhook_id:
const processedWebhooks = new Set();
app.post('/webhooks/connectvets', (req, res) => {
const webhookId = req.body.webhook_id;
if (processedWebhooks.has(webhookId)) {
// Já processado, apenas confirme
return res.status(200).json({ received: true, duplicate: true });
}
processedWebhooks.add(webhookId);
// Processar webhook...
});
Monitoramento
Logs Importantes
Monitore estes aspectos:
- Latência de resposta: Tempo para processar webhook
- Taxa de erro: Percentual de falhas no processamento
- Timeouts: Requisições que demoram muito
- Duplicatas: Webhooks reprocessados
Exemplo de Logging
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'webhooks.log' })
]
});
app.post('/webhooks/connectvets', (req, res) => {
const startTime = Date.now();
const { event, webhook_id } = req.body;
try {
// Processar webhook...
const duration = Date.now() - startTime;
logger.info('webhook_processed', {
event,
webhook_id,
duration_ms: duration,
status: 'success'
});
res.status(200).json({ received: true });
} catch (error) {
const duration = Date.now() - startTime;
logger.error('webhook_failed', {
event,
webhook_id,
duration_ms: duration,
error: error.message,
status: 'error'
});
res.status(500).json({ error: 'Processing failed' });
}
});
Configuração
Importante: Webhooks não são gerenciados via API. A configuração é feita através de contato direto com nossa equipe.
Para Configurar Webhooks
- Contate nossa equipe via WhatsApp (+55 31 8883-5141)
- Forneça informações:
- URL do seu endpoint (deve ser HTTPS)
- Eventos que deseja receber
- Método de autenticação preferido
- Ambiente (produção/desenvolvimento)
- URL do Endpoint:
https://seuapp.com/webhooks/connectvets
- Eventos:
["note.transcription.completed", "note.transcription.failed"]
- Headers Customizados (opcional): Para autenticação adicional
- Secret para Validação: Para verificar autenticidade
Teste em Desenvolvimento
Nossa equipe pode configurar webhooks para ambiente de desenvolvimento usando:
- ngrok para túneis locais
- Webhook.site para testes rápidos
- RequestBin para debug
Troubleshooting
Webhook Não Recebido
Possíveis causas:
- Endpoint inacessível (timeout/erro)
- Certificado SSL inválido
- Firewall bloqueando nossa IP
Soluções:
- Verificar se endpoint responde a GET/POST
- Validar certificado SSL
- Liberar IPs do ConnectVets no firewall
Erro 401/403
Possíveis causas:
- Autenticação adicional no endpoint
- Headers de validação incorretos
Soluções:
- Revisar lógica de autenticação
- Verificar headers
x-connectvets-signature
Webhooks Duplicados
Possíveis causas:
- Endpoint demorou para responder (timeout)
- Resposta não 2xx
Soluções:
- Implementar verificação de
webhook_id
- Otimizar tempo de processamento
- Responder rapidamente (mover processamento pesado para background)
Exemplos de Uso
async function handleTranscriptionCompleted(noteData) {
// Buscar informações da consulta no sistema local
const appointment = await getAppointmentByExternalId(noteData.external_id);
if (appointment) {
// Atualizar status no CRM
await updateCRMRecord(appointment.crm_id, {
transcription_status: 'completed',
transcription_url: `https://notes.connectvets.com.br/notes/${noteData.id}`,
last_updated: new Date()
});
// Notificar veterinário
await sendNotification(appointment.veterinarian_id, {
type: 'transcription_ready',
patient: noteData.name,
note_id: noteData.id
});
}
}
Workflow de Aprovação
async function handleTranscriptionCompleted(noteData) {
// Verificar se nota precisa de aprovação
const needsApproval = await checkApprovalRules(noteData);
if (needsApproval) {
// Enviar para fila de aprovação
await addToApprovalQueue(noteData.id, {
priority: noteData.urgent ? 'high' : 'normal',
assigned_to: await getReviewerForNote(noteData)
});
// Notificar revisor
await notifyReviewer(noteData);
} else {
// Aprovação automática
await autoApproveNote(noteData.id);
}
}