Webhooks
Receba notificações em tempo real sobre eventos da sua loja.
Visão Geral
Webhooks permitem que sua aplicação receba notificações em tempo real quando eventos acontecem na sua loja Plasma. Quando um evento ocorre, enviamos uma requisição HTTP POST para a URL que você configurou.
Endpoints
A API de Webhooks está dividida em dois grupos:
Gerenciar Endpoints (CRUD)
| Método | Endpoint | Descrição |
|---|---|---|
POST | /api/sdk/webhooks/endpoints | Registrar endpoint |
GET | /api/sdk/webhooks/endpoints | Listar endpoints |
GET | /api/sdk/webhooks/endpoints/:id | Detalhes do endpoint |
PUT | /api/sdk/webhooks/endpoints/:id | Atualizar endpoint |
DELETE | /api/sdk/webhooks/endpoints/:id | Remover endpoint |
POST | /api/sdk/webhooks/endpoints/:id/test | Testar endpoint |
Monitorar Entregas (Deliveries)
| Método | Endpoint | Descrição |
|---|---|---|
GET | /api/sdk/webhooks | Listar entregas |
GET | /api/sdk/webhooks/stats | Estatísticas |
GET | /api/sdk/webhooks/:id | Detalhes de uma entrega |
POST | /api/sdk/webhooks/:id/retry | Retry manual |
Registrar Endpoint
POST /api/sdk/webhooks/endpointsBody
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
url | string | ✅ | URL do webhook (HTTPS recomendado) |
events | string[] | ✅ | Lista de eventos para ouvir |
Exemplo
curl -X POST "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://meusite.com/api/webhooks/plasma",
"events": ["order.created", "order.paid", "product.created"]
}'const response = await fetch(
'https://api.plasmacheckout.com/api/sdk/webhooks/endpoints',
{
method: 'POST',
headers: {
'X-PLASMA-Public-Key': 'pk_live_xxxxxxxxxxxxxxxxxxxx',
'X-PLASMA-Secret-Key': 'sk_live_xxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://meusite.com/api/webhooks/plasma',
events: ['order.created', 'order.paid', 'product.created']
})
}
);
const { data } = await response.json();
console.log(data.secret); // Salve! Não será mostrado novamenteResposta (201 Created)
{
"data": {
"id": "cm5webhook123abc",
"url": "https://meusite.com/api/webhooks/plasma",
"events": ["order.created", "order.paid", "product.created"],
"secret": "a1b2c3d4e5f6...64chars...hex",
"isActive": true,
"createdAt": "2025-01-15T10:00:00Z"
},
"message": "Webhook endpoint registered. Save the secret — it will not be shown again."
}Salve o secret imediatamente! Ele é retornado apenas na criação e é necessário para verificar a assinatura dos webhooks recebidos. Máximo de 10 endpoints por loja.
Listar Endpoints
GET /api/sdk/webhooks/endpointscurl -X GET "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"data": [
{
"id": "cm5webhook123abc",
"url": "https://meusite.com/api/webhooks/plasma",
"events": ["order.created", "order.paid", "product.created"],
"isActive": true,
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z"
}
]
}Detalhes do Endpoint
GET /api/sdk/webhooks/endpoints/:idcurl -X GET "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints/cm5webhook123abc" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Atualizar Endpoint
PUT /api/sdk/webhooks/endpoints/:idBody (todos opcionais)
| Campo | Tipo | Descrição |
|---|---|---|
url | string | Nova URL |
events | string[] | Nova lista de eventos |
isActive | boolean | Ativar/desativar endpoint |
Exemplo
curl -X PUT "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints/cm5webhook123abc" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"events": ["order.created", "order.paid", "order.fulfilled", "checkout.completed"],
"isActive": true
}'Resposta
{
"data": {
"id": "cm5webhook123abc",
"url": "https://meusite.com/api/webhooks/plasma",
"events": ["order.created", "order.paid", "order.fulfilled", "checkout.completed"],
"isActive": true,
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T12:00:00Z"
},
"message": "Webhook endpoint updated"
}Remover Endpoint
DELETE /api/sdk/webhooks/endpoints/:idcurl -X DELETE "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints/cm5webhook123abc" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"data": { "id": "cm5webhook123abc", "deleted": true },
"message": "Webhook endpoint deleted"
}Testar Endpoint
POST /api/sdk/webhooks/endpoints/:id/testEnvia um payload de teste para o endpoint e retorna o resultado.
curl -X POST "https://api.plasmacheckout.com/api/sdk/webhooks/endpoints/cm5webhook123abc/test" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"success": true,
"endpointId": "cm5webhook123abc",
"url": "https://meusite.com/api/webhooks/plasma",
"httpStatus": 200,
"latencyMs": 145,
"responseBody": "{\"received\":true}",
"error": null
}O teste envia um payload com event: "test". O timeout é de 10 segundos.
Eventos Disponíveis
Pedidos
| Evento | Descrição |
|---|---|
order.created | Pedido criado |
order.updated | Pedido atualizado |
order.paid | Pagamento confirmado |
order.fulfilled | Pedido enviado |
order.cancelled | Pedido cancelado |
order.refunded | Pedido reembolsado |
Produtos
| Evento | Descrição |
|---|---|
product.created | Produto criado |
product.updated | Produto atualizado |
product.deleted | Produto removido |
Checkout
| Evento | Descrição |
|---|---|
checkout.completed | Checkout finalizado |
checkout.expired | Checkout expirou |
Payload do Webhook
{
"id": "evt_123abc",
"event": "order.paid",
"createdAt": "2025-01-15T10:30:00Z",
"data": {
"order": {
"id": "cm5order123abc456def",
"orderNumber": "PLS-2025-A1B2C3",
"status": "processing",
"paymentStatus": "paid",
"customer": {
"email": "cliente@email.com",
"name": "João Silva"
},
"items": [...],
"total": 17480,
"currency": "BRL"
}
}
}Verificando Assinatura
Todos os webhooks incluem uma assinatura HMAC-SHA256 no header X-PLASMA-Signature para verificar a autenticidade.
Header de Assinatura
X-PLASMA-Signature: sha256=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
X-PLASMA-Event: order.paidVerificação em Node.js
import crypto from 'crypto';
export function verifyWebhookSignature(payload, signature, secret) {
if (!signature || !signature.startsWith('sha256=')) {
return false;
}
const hash = signature.slice(7); // Remove "sha256="
// Calcula o hash esperado
const expectedHash = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
// Comparação timing-safe
return crypto.timingSafeEqual(
Buffer.from(hash),
Buffer.from(expectedHash)
);
}Exemplo de Endpoint (Next.js)
import { NextResponse } from 'next/server';
import { verifyWebhookSignature } from '@/lib/verify-webhook';
export async function POST(request: Request) {
const payload = await request.json();
const signature = request.headers.get('X-PLASMA-Signature');
// Verifica a assinatura
const isValid = verifyWebhookSignature(
payload,
signature,
process.env.PLASMA_WEBHOOK_SECRET!
);
if (!isValid) {
return NextResponse.json(
{ error: 'Assinatura inválida' },
{ status: 401 }
);
}
// Processa o evento
switch (payload.event) {
case 'order.paid':
await handleOrderPaid(payload.data.order);
break;
case 'order.fulfilled':
await handleOrderFulfilled(payload.data.order);
break;
case 'checkout.completed':
await handleCheckoutCompleted(payload.data);
break;
// ... outros eventos
}
// Sempre retorne 200 para confirmar recebimento
return NextResponse.json({ received: true });
}
async function handleOrderPaid(order: any) {
console.log('Pedido pago:', order.orderNumber);
}
async function handleOrderFulfilled(order: any) {
console.log('Pedido enviado:', order.orderNumber);
}
async function handleCheckoutCompleted(data: any) {
console.log('Checkout concluído:', data.token);
}Retry Automático
Se seu endpoint não responder com status 2xx, tentaremos novamente:
| Tentativa | Intervalo |
|---|---|
| 1ª | Imediato |
| 2ª | 1 minuto |
| 3ª | 5 minutos |
| 4ª | 15 minutos |
| 5ª | 1 hora |
| 6ª | 4 horas |
Após 6 tentativas sem sucesso, o webhook é marcado como falho e não será mais retentado automaticamente. Use o retry manual via API.
Listar Entregas (Deliveries)
GET /api/sdk/webhooksParâmetros de Query
| Parâmetro | Tipo | Descrição |
|---|---|---|
limit | number | Máximo de itens (1-100, padrão: 50) |
status | string | delivered, failed, pending, retrying |
event | string | Filtrar por tipo de evento |
include_stats | string | true para incluir estatísticas na mesma resposta |
Exemplo
curl -X GET "https://api.plasmacheckout.com/api/sdk/webhooks?status=failed&include_stats=true" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"data": {
"deliveries": [
{
"id": "cm5delivery123",
"event": "order.paid",
"status": "failed",
"attempts": 3,
"webhookUrl": "https://meusite.com/api/webhooks/plasma",
"errorMessage": "Connection timeout",
"createdAt": "2025-01-15T10:30:00Z"
}
],
"stats": {
"total": 1500,
"delivered": 1480,
"failed": 15,
"pending": 5,
"successRate": 98.67
}
},
"meta": {
"count": 1,
"limit": 50,
"filters": {
"status": "failed",
"event": null
}
}
}Detalhes de uma Entrega
GET /api/sdk/webhooks/:idcurl -X GET "https://api.plasmacheckout.com/api/sdk/webhooks/cm5delivery123" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"data": {
"id": "cm5delivery123",
"event": "order.paid",
"eventId": "evt_abc123",
"webhookUrl": "https://meusite.com/api/webhooks/plasma",
"status": "failed",
"httpStatus": null,
"responseBody": null,
"errorMessage": "Connection timeout",
"attempts": 6,
"maxAttempts": 6,
"nextRetryAt": null,
"createdAt": "2025-01-15T10:30:00Z",
"deliveredAt": null,
"payload": {
"event": "order.paid",
"data": { "..." : "..." }
}
}
}Estatísticas de Webhooks
GET /api/sdk/webhooks/statscurl -X GET "https://api.plasmacheckout.com/api/sdk/webhooks/stats" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"data": {
"total": 1500,
"delivered": 1480,
"failed": 15,
"pending": 5,
"successRate": 98.67
}
}Retry Manual
POST /api/sdk/webhooks/:id/retryRetenta uma entrega que falhou.
curl -X POST "https://api.plasmacheckout.com/api/sdk/webhooks/cm5delivery123/retry" \
-H "X-PLASMA-Public-Key: pk_live_xxxxxxxxxxxxxxxxxxxx" \
-H "X-PLASMA-Secret-Key: sk_live_xxxxxxxxxxxxxxxxxxxx"Resposta
{
"success": true,
"deliveryId": "cm5delivery123",
"event": "order.paid",
"httpStatus": 200,
"error": null,
"retryScheduled": false
}Não é possível retentá-la se o status já for delivered.
Boas Práticas
Responda rapidamente
Retorne 200 o mais rápido possível. Processe pesado em background.
Use uma fila
Coloque eventos em uma fila (Redis, SQS) e processe assincronamente.
Implemente idempotência
Use o id do evento para evitar processar duplicados.
const processedEvents = new Set();
if (processedEvents.has(payload.id)) {
return NextResponse.json({ received: true });
}
processedEvents.add(payload.id);
// processa o evento...Verifique sempre a assinatura
Nunca processe webhooks sem verificar a assinatura X-PLASMA-Signature.
Use HTTPS
Sua URL de webhook deve usar HTTPS obrigatoriamente em produção.
Configurando via Dashboard
Além da API, você pode gerenciar webhooks pelo Dashboard:
- Acesse Configurações → Webhooks
- Clique em Adicionar Endpoint
- Configure a URL e selecione os eventos
- Use o botão Enviar Teste para validar
Os logs de entrega ficam disponíveis por 30 dias.