Como configurar webhooks na Área de Membros / Plataforma
Os webhooks permitem que sistemas externos recebam notificações em tempo real sobre eventos importantes da área de membros, como conclusão de aulas, publicação de conteúdo, emissão de certificados e inatividade de usuários.
Acesse a documentação completa em - Webhook - Área de Membros
Visão Geral
A plataforma TheMembers envia requisições HTTP POST para os endpoints de webhook configurados pelo cliente sempre que um evento ocorre.
Características principais:
- Protocolo: HTTP POST
- Formato: JSON
- Autenticação: HMAC-SHA256
- Timeout: 30 segundos
- Tentativas: até 3 em caso de falha
- Intervalo entre tentativas: 30s, 60s e 120s
- Para realizar o acesso ao Painel no Dashboard vá em Plataformas - Configurações - Webhook

- Após isso clique no botão de **Criar Webhook **para realizar a criação das configurações


Autenticação e Segurança
Todas as requisições de webhook incluem um mecanismo de autenticação baseado em HMAC-SHA256, garantindo a integridade e a autenticidade do payload recebido.
Cabeçalhos enviados:
X-Webhook-Signature: assinatura HMAC-SHA256 do corpo da requisiçãoX-Webhook-Event: nome do evento disparado
A assinatura é gerada a partir do corpo bruto do JSON, utilizando o client_token do cliente como chave secreta.
Como validar a assinatura
- Obtenha o corpo bruto da requisição (JSON sem qualquer modificação).
- Calcule o HMAC-SHA256 utilizando o
client_tokencomo chave. - Gere o hash em formato hexadecimal.
- Compare o resultado com o valor enviado no cabeçalho
X-Webhook-Signature.
⚠️ Importante: a validação só funcionará corretamente se o JSON for serializado exatamente conforme o padrão abaixo:
- Barras (
/) não são escapadas - Caracteres Unicode não são escapados (ex:
áao invés de\u00e1)
Exemplo em PHP
<?php
$body = file_get_contents('php://input');
$clientToken = 'seu_client_token_aqui';
$expectedSignature = hash_hmac('sha256', $body, $clientToken);
$providedSignature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (!hash_equals($expectedSignature, $providedSignature)) {
http_response_code(401);
exit('Assinatura inválida');
}
$payload = json_decode($body, true);
Exemplo em Node.js
const crypto = require('crypto');
const express = require('express');
const app = express();
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString('utf8');
}
}));
app.post('/webhook', (req, res) => {
const clientToken = 'seu_client_token_aqui';
const providedSignature = req.headers['x-webhook-signature'];
const expectedSignature = crypto
.createHmac('sha256', clientToken)
.update(req.rawBody)
.digest('hex');
if (expectedSignature !== providedSignature) {
return res.status(401).send('Assinatura inválida');
}
console.log('Evento recebido:', req.body.event);
res.status(200).send('OK');
});
Exemplo de Assinatura
Abaixo está um exemplo de corpo de requisição de webhook e o valor esperado para o cabeçalho X-Webhook-Signature, assumindo que o client_token seja mySecretKey123.
Corpo da Requisição de Exemplo:
{
"type": "class_history",
"event": "class.completed",
"created": "2025-01-13T14:30:00.000000Z",
"data": {
"datetime": "2025-01-13T14:25:00.000000Z",
"platform_id": 1,
"platform_name": "Minha Plataforma",
"student": {
"id": 12345,
"reference_id": "EXT-001",
"name": "João da Silva",
"email": "joao@exemplo.com",
"phone": "+5511999999999",
"document": "12345678900",
"gender": "male"
},
"course": {
"id": 100,
"name": "Curso de Programação",
"module": {
"id": 10,
"name": "Módulo 1 - Fundamentos",
"class": {
"id": 1,
"name": "Introdução ao PHP"
}
}
}
}
}
Assinatura Esperada
Para o corpo acima e client_token mySecretKey123, o valor do cabeçalho X-Webhook-Signature será (exemplo ilustrativo):
4a3d8c1e2f5b6a7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c
Nota: A assinatura acima é ilustrativa. O valor real dependerá da serialização exata do JSON e da chave secreta.
Importante: A assinatura só corresponderá se o JSON for serializado exatamente como acima, sem barras ou unicode escapados.
Eventos Disponíveis
Conclusão de Aula (class.completed)
Disparado quando o aluno conclui uma aula (progresso 100% ou aula finalizada).
- Tipo:
class_history - Evento:
class.completed
Inclui dados da plataforma, aluno, curso, módulo e aula.
{
"type": "class_history",
"event": "class.completed",
"created": "2025-01-13T14:30:00.000000Z",
"data": {
"datetime": "2025-01-13T14:25:00.000000Z",
"platform_id": 1,
"platform_name": "Minha Plataforma",
"student": {
"id": 12345,
"reference_id": "EXT-001",
"name": "João da Silva",
"email": "joao@exemplo.com",
"phone": "+5511999999999",
"document": "12345678900",
"gender": "male"
},
"course": {
"id": 100,
"name": "Curso de Programação",
"module": {
"id": 10,
"name": "Módulo 1 - Fundamentos",
"class": {
"id": 1,
"name": "Introdução ao PHP"
}
}
}
}
}
Publicação de Aula (class.published)
Enviado quando uma aula é criada ou publicada manualmente na plataforma.
- Tipo:
class - Evento:
class.published
Inclui dados do curso, módulo e aula publicada.
{
"type": "class",
"event": "class.published",
"created": "2025-01-13T14:30:00.000000Z",
"data": {
"datetime": "2025-01-13T14:30:00.000000Z",
"platform_id": 1,
"platform_name": "Minha Plataforma",
"course": {
"id": 100,
"name": "Curso de Programação",
"module": {
"id": 10,
"name": "Módulo 1 - Fundamentos",
"class": {
"id": 1,
"name": "Introdução ao PHP"
}
}
}
}
}
Certificado Emitido (certificate.issued)
Disparado no momento da emissão de um certificado para um aluno.
- Tipo:
certificate - Evento:
certificate.issued
Inclui dados do aluno, curso e certificado emitido.
{
"type": "certificate",
"event": "certificate.issued",
"created": "2025-01-13T14:30:00.000000Z",
"data": {
"datetime": "2025-01-13T14:30:00.000000Z",
"platform_id": 1,
"platform_name": "Minha Plataforma",
"student": {
"id": 12345,
"reference_id": "EXT-001",
"name": "João da Silva",
"email": "joao@exemplo.com",
"phone": "+5511999999999",
"document": "12345678900",
"gender": "male"
},
"course": {
"id": 100,
"name": "Curso de Programação"
},
"certificate": {
"id": 50,
"name": "Certificado de Conclusão"
}
}
}
Usuário Inativo por 7 Dias (user.inactive_for_7_days)
Enviado quando um usuário permanece exatamente 7 dias sem login.
📌 Observação: enquanto o usuário continuar inativo, o evento será reenviado a cada 7 dias.
- Tipo:
login_history - Evento:
user.inactive_for_7_days
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "login_history",
"event": "user.inactive_for_7_days",
"created": "2025-01-13T14:30:00.000000Z",
"data": {
"datetime": "2025-01-06T14:30:00.000000Z",
"inactive_days": 7,
"platform_id": 1,
"platform_name": "Minha Plataforma",
"student": {
"id": 12345,
"reference_id": "EXT-001",
"name": "João da Silva",
"email": "joao@exemplo.com",
"phone": "+5511999999999",
"document": "12345678900",
"gender": "female"
}
}
}
Formato do Payload
Content-Type: application/json- Datas no padrão ISO 8601
- Campos podem retornar
null - Telefones no padrão E.164 (ex:
+5511999999999) - CPF/CNPJ enviados apenas com números
Boas Práticas
Segurança
- Valide sempre a assinatura HMAC antes de processar o evento
- Não compartilhe o
client_token - Utilize HTTPS no endpoint de webhook
Performance e Resposta
- Responda rapidamente com HTTP 200
- Evite processamentos pesados na requisição
- Utilize filas e processamento assíncrono
Confiabilidade
- Implemente idempotência (eventos podem ser reenviados)
- Registre logs para auditoria e troubleshooting
Tratamento de Erros
- Até 3 tentativas automáticas em caso de falha
- Intervalos: 30s, 60s e 120s
- Após falha definitiva, o evento não será reenviado
Histórico
Também é possível visualizar todo o seu histórico de envios clicando em ver histórico.
Dentro do histórico, você pode clicar em Ver payload e ter acesso à todo o corpo de requisição enviado.

Considerações Finais
Os webhooks permitem integrações robustas e em tempo real com sistemas externos. Seguindo as boas práticas de segurança, performance e idempotência, é possível construir integrações confiáveis, escaláveis e seguras.
Atualizado em: 27/01/2026
