Plasma

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étodoEndpointDescrição
POST/api/sdk/webhooks/endpointsRegistrar endpoint
GET/api/sdk/webhooks/endpointsListar endpoints
GET/api/sdk/webhooks/endpoints/:idDetalhes do endpoint
PUT/api/sdk/webhooks/endpoints/:idAtualizar endpoint
DELETE/api/sdk/webhooks/endpoints/:idRemover endpoint
POST/api/sdk/webhooks/endpoints/:id/testTestar endpoint

Monitorar Entregas (Deliveries)

MétodoEndpointDescrição
GET/api/sdk/webhooksListar entregas
GET/api/sdk/webhooks/statsEstatísticas
GET/api/sdk/webhooks/:idDetalhes de uma entrega
POST/api/sdk/webhooks/:id/retryRetry manual

Registrar Endpoint

POST /api/sdk/webhooks/endpoints

Body

CampoTipoObrigatórioDescrição
urlstringURL do webhook (HTTPS recomendado)
eventsstring[]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 novamente

Resposta (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/endpoints
curl -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/:id
curl -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/:id

Body (todos opcionais)

CampoTipoDescrição
urlstringNova URL
eventsstring[]Nova lista de eventos
isActivebooleanAtivar/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/:id
curl -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/test

Envia 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

EventoDescrição
order.createdPedido criado
order.updatedPedido atualizado
order.paidPagamento confirmado
order.fulfilledPedido enviado
order.cancelledPedido cancelado
order.refundedPedido reembolsado

Produtos

EventoDescrição
product.createdProduto criado
product.updatedProduto atualizado
product.deletedProduto removido

Checkout

EventoDescrição
checkout.completedCheckout finalizado
checkout.expiredCheckout expirou

Payload do Webhook

Exemplo: order.paid
{
  "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.paid

Verificação em Node.js

lib/verify-webhook.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)

app/api/webhooks/plasma/route.ts
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:

TentativaIntervalo
Imediato
1 minuto
5 minutos
15 minutos
1 hora
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/webhooks

Parâmetros de Query

ParâmetroTipoDescrição
limitnumberMáximo de itens (1-100, padrão: 50)
statusstringdelivered, failed, pending, retrying
eventstringFiltrar por tipo de evento
include_statsstringtrue 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/:id
curl -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/stats
curl -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/retry

Retenta 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:

  1. Acesse Configurações → Webhooks
  2. Clique em Adicionar Endpoint
  3. Configure a URL e selecione os eventos
  4. Use o botão Enviar Teste para validar

Os logs de entrega ficam disponíveis por 30 dias.