Opsellio — Guia de Integrações & Webhooks
🔌 Documento técnico — integrações

Webhooks & Integrações
Opsellio

Framework completo para ligar a Opsellio a plataformas externas — áreas de membros, LMS, SaaS — de forma automática, segura e à prova de falhas.

Webhook HMAC-SHA256 Kajabi Teachable Moodle WordPress Circle.so Zapier API REST SSO / JWT
01Arquitetura

Como a Opsellio se liga a plataformas externas

A Opsellio é a fonte de verdade do pagamento. A plataforma externa entrega o produto. A ligação entre as duas é feita por webhooks — chamadas HTTP automáticas que a Opsellio dispara quando algo acontece.

Modelo principal
Webhook
Opsellio → plataforma
Eventos core
18
Pagamento, acesso, cancel.
Garantia entrega
Retry
Backoff exponencial
Segurança
HMAC-SHA256
Assinar cada payload
Fluxo passo a passo
Passo 1
Comprador paga na Opsellio
O checkout da Opsellio recebe o pagamento via M-Pesa, e-Mola, Cartão, Apple Pay ou Google Pay. O gateway confirma a transação ao backend.
Passo 2
Opsellio dispara evento webhook
Após confirmação, a Opsellio faz um POST para o endpoint da plataforma externa com o payload do evento — assinado com HMAC-SHA256 no header X-Opsellio-Signature.
Passo 3
Plataforma externa recebe e age
A plataforma de destino (área de membros, SaaS, LMS) recebe o evento, valida a assinatura HMAC, e executa a ação: criar conta, dar acesso ao curso, ativar plano.
Passo 4
Resposta 200 OK em menos de 30 segundos
A plataforma externa responde com HTTP 200 imediatamente (processar em background). Se houver erro ou timeout, a Opsellio faz retry com backoff exponencial: 30s → 2min → 10min → 1h → 24h.
Nunca processar o evento de forma síncrona e depois responder — enfileirar e responder 200 de imediato.
Opcional — polling reverso
Plataforma externa consulta a Opsellio via API REST
Para casos avançados, a plataforma externa pode consultar o estado de subscrição, verificar se um utilizador tem acesso ativo, ou listar compras via REST API.
Modelos de integração disponíveis
Modelo 1 — recomendado
Webhook nativo Simples
A Opsellio envia eventos HTTP POST para um endpoint configurado pelo criador. A plataforma externa escuta e age. Ideal para equipas técnicas com backend próprio.
Modelo 2 — no-code
Zapier / Make.com No-code
A Opsellio dispara o webhook para o Zapier ou Make, que faz a ponte para qualquer outra plataforma sem código. Suporta 5000+ apps. Ideal para criadores não-técnicos.
Modelo 3 — avançado
API REST bidirecional Avançado
Para integrações complexas onde a plataforma externa precisa de consultar dados da Opsellio em tempo real — verificar status, listar membros, sincronizar cancelamentos.
Modelo 4 — melhor UX
SSO / Single Sign-On Avançado
O comprador paga na Opsellio e tem acesso transparente à plataforma externa sem criar uma segunda conta. Implementado via JWT ou OAuth 2.0. Melhor experiência para o utilizador final.
02Catálogo de Eventos

18 eventos que a Opsellio pode disparar

Cada evento corresponde a uma ação que deve acontecer na plataforma externa. Os eventos marcados como Crítico devem ser implementados antes do lançamento.

🚨
Três eventos obrigatórios antes do lançamento: payment.completed (dar acesso), payment.refunded (revogar), subscription.expired (revogar). Ignorar os dois últimos significa utilizadores com reembolso que continuam com acesso — buraco de receita silencioso.
Eventos de pagamento
payment.completed
Pagamento confirmado pelo gateway. Este é o único evento que deve desencadear a criação de acesso na plataforma externa. Nunca usar payment.initiated.
Crítico — implementar primeiropagamentoacesso
payment.failed
Pagamento recusado ou expirado. Não dar acesso. Disparar sequência de recuperação de venda (email + WhatsApp).
Críticopagamentorisco
payment.refunded
Reembolso processado. Revogar acesso imediatamente na plataforma externa. Se houver acesso parcial (ex: acesso por dias), calcular proporcionalmente.
Críticopagamentoacesso
payment.chargeback
Contracarga iniciada pelo banco do comprador. Suspender acesso imediatamente, notificar o criador, abrir caso de disputa com o gateway.
Críticopagamentorisco
order.bump.completed
Order bump comprado no checkout (produto adicional). Dar acesso ao produto extra identificado pelo product_id no payload.
Altopagamentoacesso
upsell.completed
Upsell aceite após a compra principal. Dar acesso ao produto de upgrade. O produto original mantém o seu acesso.
Altopagamentoacesso
Eventos de subscrição recorrente
subscription.activated
Subscrição recorrente ativada pela primeira vez. Dar acesso contínuo — vai renovar automaticamente a cada período.
Críticosubscriçãoacesso
subscription.renewed
Renovação mensal ou anual bem-sucedida. Estender o acesso pelo próximo período. Atualizar data de expiração na plataforma externa.
Altosubscriçãoacesso
subscription.cancelled
Cancelamento solicitado pelo cliente. Não revogar imediatamente — revogar no fim do período já pago. O payload inclui o campo access_until com a data exacta.
Críticosubscriçãoacesso
subscription.expired
Período de acesso terminou sem renovação. Revogar acesso agora. Disparar email de reativação com link direto para subscrever de novo.
Críticosubscriçãoacesso
subscription.payment_failed
Tentativa de renovação falhou. Implementar período de graça de 3 dias antes de revogar acesso. Notificar o cliente para atualizar dados de pagamento.
Altosubscriçãorisco
subscription.trial_started
Trial gratuito iniciado. Dar acesso por N dias sem cobrança. O payload inclui trial_ends_at.
Médiosubscriçãoacesso
subscription.trial_ending
Trial termina em 48h. Disparar email de conversão. Não revogar acesso — o comprador ainda está no trial.
Médiosubscrição
Eventos de cliente e acesso
customer.created
Novo cliente criado na Opsellio. Sincronizar o perfil (nome, email, telefone) com a plataforma externa antes de precisar dar-lhe acesso.
Médiocliente
customer.updated
Dados do cliente atualizados (email, nome, telefone). Sincronizar com a plataforma externa para manter os perfis consistentes.
Baixocliente
access.granted
Acesso manual concedido pelo criador do produto no dashboard (ex: acesso de cortesia). Criar ou atualizar o acesso na plataforma externa.
Altoacesso
access.revoked
Acesso revogado manualmente pelo criador. Remover imediatamente na plataforma externa. Útil para banir utilizadores ou corrigir erros.
Altoacessorisco
affiliate.conversion
Venda gerada por um afiliado. Registar a conversão no sistema de afiliados para calcular a comissão. O payload inclui affiliate_id e o valor da comissão.
Médioafiliados
03Payload & Headers

Estrutura completa do payload

Cada webhook enviado pela Opsellio segue este schema JSON. O campo event define o tipo de ação a executar. O campo id é único por evento — usar para idempotência.

Headers HTTP enviados
Header obrigatório
X-Opsellio-Signature
Assinatura HMAC-SHA256 do corpo raw. Formato: sha256=abc123.... Verificar ANTES de processar qualquer payload.
Headers informativos
X-Opsellio-Event · X-Opsellio-Version
O tipo de evento (ex: payment.completed) e a versão do schema (ex: 2025-05) para facilitar o routing no handler.
Payload JSON — exemplo de payment.completed
// POST https://suaplataforma.com/webhook/opsellio // Content-Type: application/json // X-Opsellio-Signature: sha256=3a7b9c2d4e5f8a1b2c3d4e5f6a7b8c9d... // X-Opsellio-Event: payment.completed // X-Opsellio-Version: 2025-05 { "id": "evt_01J8K9X2M4N7P3Q6R8S", // ID único — usar para idempotência "event": "payment.completed", "created_at": "2025-05-09T14:32:11Z", "version": "2025-05", "data": { "order": { "id": "ord_01J8K9X2M4N7P3", "amount": 1500, // em centavos (1500 = 15.00 MZN) "currency": "MZN", "payment_method": "mpesa", // mpesa | emola | card | apple_pay | google_pay "status": "paid" }, "customer": { "id": "cus_01J8K9", "email": "joao@gmail.com", "name": "João Machava", "phone": "+258841234567" }, "product": { "id": "prod_01J8K9", "name": "Curso de Marketing Digital", "type": "course", // course | subscription | digital_product "access_duration_days": 365, // null se subscrição recorrente "access_until": "2026-05-09T14:32:11Z" }, "subscription": null, // preenchido se produto recorrente "metadata": { "utm_source": "instagram", "utm_campaign": "jan2025", "affiliate_id": "aff_abc123" // null se sem afiliado } }, "signature": "sha256=3a7b9c2d4e5f..." // repetido no body por conveniência }
Payload de subscription.cancelled — exemplo
{ "id": "evt_01J8K9X2CANCEL", "event": "subscription.cancelled", "data": { "subscription": { "id": "sub_01J8K9", "status": "cancelled", "cancelled_at": "2025-05-09T14:32:11Z", "access_until": "2025-06-09T14:32:11Z" // ← revogar acesso SÓ nesta data }, "customer": { ... }, "product": { ... } } }
04Segurança & Retry

Segurança, idempotência e garantia de entrega

Sem estas três implementações, a integração tem buracos críticos: eventos falsos podem dar acesso grátis, eventos duplicados podem criar registos em duplicado, e eventos não entregues ficam silenciosamente perdidos.

⚠️
Qualquer URL pode receber um POST. Sem verificação de assinatura, qualquer pessoa pode enviar eventos falsos à tua plataforma e dar acesso a utilizadores que não pagaram. A verificação HMAC é obrigatória.
1 — Verificação de assinatura HMAC-SHA256
Como verificar no endpoint (Node.js / Express) Obrigatório
Usar o corpo raw em bytes — nunca o JSON já parseado. A assinatura é calculada sobre o body original, não sobre o objeto JS.
// IMPORTANTE: usar express.raw() antes do json() parser const crypto = require('crypto'); function verifyWebhook(rawBody, signatureHeader, secret) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) // rawBody deve ser Buffer, não string .digest('hex'); // timingSafeEqual protege contra timing attacks return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signatureHeader) ); } // Endpoint app.post('/webhook/opsellio', express.raw({type: '*/*'}), (req, res) => { const sig = req.headers['x-opsellio-signature']; if (!verifyWebhook(req.body, sig, process.env.OPSELLIO_WEBHOOK_SECRET)) { return res.status(401).json({ error: 'Assinatura inválida' }); } const event = JSON.parse(req.body.toString()); processEventAsync(event); // enfileirar e processar em background res.status(200).json({ received: true }); // responder IMEDIATAMENTE });
Verificação em Python (Django / Flask) Python
import hmac, hashlib, os def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool: expected = 'sha256=' + hmac.new( secret.encode(), raw_body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature) # Django view def webhook_view(request): sig = request.META.get('HTTP_X_OPSELLIO_SIGNATURE', '') if not verify_webhook(request.body, sig, os.environ['WEBHOOK_SECRET']): return JsonResponse({'error': 'Inválido'}, status=401) event = json.loads(request.body) process_event.delay(event) # Celery task — async return JsonResponse({'received': True})
2 — Idempotência — processar cada evento uma vez
Guardar IDs processados Obrigatório
Com retry automático, o mesmo evento pode chegar 2 a 6 vezes. Guardar os IDs processados e ignorar silenciosamente os duplicados.
// Redis — guardar IDs por 7 dias async function processWebhook(event) { const key = `webhook:processed:${event.id}`; const alreadyDone = await redis.get(key); if (alreadyDone) { console.log(`Evento duplicado ignorado: ${event.id}`); return; // retornar sem processar } await redis.set(key, '1', 'EX', 86400 * 7); // 7 dias de TTL await handleEvent(event); // processar uma única vez } // Handler por tipo de evento async function handleEvent(event) { switch (event.event) { case 'payment.completed': await grantAccess(event.data); break; case 'payment.refunded': case 'subscription.expired': case 'access.revoked': await revokeAccess(event.data); break; case 'subscription.cancelled': await scheduleRevoke(event.data.subscription.access_until, event.data); break; default: console.log(`Evento não tratado: ${event.event}`); } }
3 — Sistema de retry — backoff exponencial
Tentativa 1 — imediato
Primeiro disparo
Assim que o evento é gerado após confirmação do pagamento.
Tentativa 2 — 30 segundos
Primeiro retry
Se o endpoint retornou erro 5xx, 4xx (exceto 401), ou timeout de 30s.
Tentativa 3 — 2 minutos
Backoff × 4
Tentativa 4 — 10 minutos
Alerta por email ao criador do produto
O criador é notificado que um evento está com falhas de entrega. Pode investigar o endpoint.
Tentativa 5 — 1 hora
Backoff × 6
Tentativa 6 — 24 horas
Evento movido para dead letter queue
Após 6 falhas, o evento é marcado como morto e fica disponível para reprocessamento manual no dashboard da Opsellio. O criador pode reenviar individualmente.
05Plataformas Externas

Guia de integração por plataforma

Para cada plataforma externa, os eventos a implementar, o método de autenticação da API e as ações a executar quando cada evento chega.

K
Kajabi
Área de membros premium
Auth: API Key + Secret no header
payment.completed → POST /api/v1/members (criar membro)
payment.completed → POST /api/v1/grants (dar acesso ao produto)
payment.refunded → DELETE /api/v1/grants/:id
subscription.cancelled → agendar revogação para access_until
T
Teachable
Plataforma de cursos
Auth: API Key no header Authorization
payment.completed → POST /api/v1/users + enrollment
payment.refunded → DELETE /api/v1/enrollments/:id
customer.updated → PUT /api/v1/users/:id
M
Moodle
LMS open source
Auth: Token de serviço web Moodle
payment.completed → core_user_create_users + enrol_manual_enrol_users
payment.refunded → enrol_manual_unenrol_users
customer.updated → core_user_update_users
Th
Thinkific
Plataforma de cursos
Auth: API Key + X-Auth-Subdomain
payment.completed → POST /api/v1/enrollments
payment.refunded → PUT /api/v1/enrollments/:id (expired)
Thinkific suporta webhooks bidirecionais nativos
W
WordPress + MemberPress
Área de membros self-hosted
Auth: WP Application Password
payment.completed → POST /wp-json/mp/v1/members
payment.refunded → PUT /wp-json/mp/v1/memberships/:id (cancel)
Usar plugin MemberPress Developer Tools
C
Circle.so
Comunidade & cursos
Auth: API Key no header Authorization
payment.completed → POST /api/v1/community_members
payment.refunded → DELETE /api/v1/community_members/:id
access.granted → POST /api/v1/space_members
H
Hotmart Club
Área de membros
Auth: Hotmart OAuth 2.0
Hotmart tem webhooks nativos bidirecionais
payment.completed → API Hotmart Club membership
Usar Hotmart Sandbox para testes
Z
Zapier / Make.com
Middleware no-code
Auth: URL de webhook Zapier/Make
Trigger: Opsellio dispara webhook para URL do Zapier
Action: criar registo em qualquer app (5000+)
Sem código — configurar no dashboard Zapier/Make
Plataforma própria (custom)
SaaS / webapp feito à medida
Auth: HMAC-SHA256 (ver secção 04)
Implementar endpoint POST /webhook/opsellio
Verificar assinatura antes de processar
Responder 200 em <5s, processar async
Implementar idempotência por event.id
06Checklist Técnico

O que implementar — lado a lado

Checklist dividido pelo que a equipa da Opsellio implementa no backend da plataforma, e o que a plataforma externa (área de membros, SaaS) deve implementar para receber os eventos.

Progresso da implementação0 / 0 itens
Lado Opsellio — backend da plataforma
Lado plataforma externa — quem recebe os webhooks
Opsellio
Guia de Integrações & Webhooks — Referência para programadores · v2025-05
18 eventos · HMAC-SHA256 · Retry backoff exponencial · 9 plataformas