Artigos sobre: Dashboard (Área do Administrador)

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ção
  • X-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


  1. Obtenha o corpo bruto da requisição (JSON sem qualquer modificação).
  2. Calcule o HMAC-SHA256 utilizando o client_token como chave.
  3. Gere o hash em formato hexadecimal.
  4. 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