Pular para o conteúdo

Catálogo de demonstração. Produtos, criadores, preços e avaliações são fictícios. Recursos gratuitos podem ser adquiridos de verdade; itens pagos não são cobrados nem simulados. Ver o que já funciona

Webhooks

Eventos de licença entregues ao seu servidor, assinados e com retentativa.

Eventos

EventoQuando dispara
license.createdLicença emitida
license.activatedPrimeira ativação
license.deactivatedInstalação desvinculada
license.revokedLicença revogada
license.expiredLicença expirada

Cadastre endpoints em /seller/licensing/webhooks. Disponível a partir do plano Starter.

Corpo

json
{
  "id": "evt_a1b2c3d4e5f6a7b8c9d0",
  "type": "license.activated",
  "createdAt": "2026-11-11T22:00:00.000Z",
  "data": {
    "license": {
      "id": "clx1a2b3c4d5e6f7g8h9",
      "productId": "lsp_a1b2c3d4e5f6a7b8c9d0e1f2",
      "pluginName": "Aurum Economy",
      "status": "ACTIVE",
      "source": "PURCHASE",
      "isTest": false,
      "issuedAt": "2026-11-10T14:22:31.000Z",
      "expiresAt": null,
      "maxInstallations": 2,
      "activeInstallations": 1,
      "keyHint": "K7P2"
    }
  }
}

O que NÃO vai no corpo

Chave de licença, e-mail do comprador e IP declarado. Nada disso é necessário para o seu sistema reagir ao evento, e tudo isso vazaria para um servidor de terceiro a cada entrega. O keyHint (últimos 4 caracteres) existe para você casar com o seu próprio registro, se precisar.

Cabeçalhos

CabeçalhoPara quê
X-Lodestone-EventTipo do evento.
X-Lodestone-DeliveryIdentificador da entrega. ESTÁVEL entre tentativas — use para deduplicar.
X-Lodestone-Signaturet=<epoch>,v1=<hex> — HMAC-SHA256.
User-AgentLodestone-Licensing-Webhooks/1.0

Verificar a assinatura

Verifique antes de confiar no corpo

Sem isso, qualquer um que descubra a sua URL consegue forjar um evento — e revogar uma licença no seu sistema interno, por exemplo.
javascript
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verificar(req, segredo) {
  const cabecalho = req.headers['x-lodestone-signature']  // t=...,v1=...
  if (!cabecalho) return false

  const campos = Object.fromEntries(
    cabecalho.split(',').map((parte) => parte.split('=')),
  )

  // Rejeita entrega antiga reapresentada. O timestamp está DENTRO da
  // assinatura, então não dá para alterá-lo sem invalidar o v1.
  const agora = Math.floor(Date.now() / 1000)
  if (Math.abs(agora - Number(campos.t)) > 300) return false

  const esperado = createHmac('sha256', segredo)
    .update(`${campos.t}.${req.rawBody}`)   // corpo CRU
    .digest('hex')

  const a = Buffer.from(esperado)
  const b = Buffer.from(campos.v1 ?? '')
  return a.length === b.length && timingSafeEqual(a, b)
}

Use o corpo cru

Antes de qualquer parsing. Reserializar o JSON muda os bytes — espaço, ordem de chaves, escape — e a assinatura deixa de conferir. No Express: express.raw({ type: "application/json" }).

Java

java
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(segredo.getBytes(UTF_8), "HmacSHA256"));
byte[] calculado = mac.doFinal((timestamp + "." + corpoCru).getBytes(UTF_8));

// Comparação em tempo constante.
boolean confere = MessageDigest.isEqual(calculado, HexFormat.of().parseHex(v1));

Retentativa

Entregas que falham são repetidas até 6 vezes, com espera crescente: 30s, 2 min, 10 min, 1 h, 6 h.

  • Responda 2xx para confirmar. Qualquer outro status conta como falha.
  • Responda rápido. O timeout é de 8 segundos. Enfileire o trabalho pesado e responda imediatamente.
  • Deduplique por X-Lodestone-Delivery. O identificador é o mesmo em todas as tentativas da mesma entrega.

Endpoints mortos são desativados sozinhos

Depois de 15 falhas seguidas, o endpoint é desativado automaticamente. Um endpoint morto que nunca para de ser tentado vira tráfego de saída perpétuo contra um terceiro — e, se o domínio for vendido, contra um terceiro que não pediu nada.

Restrições de destino

Um webhook é SSRF em potencial. Por isso:

  • Apenas HTTPS, apenas porta 443.
  • O host precisa resolver para endereço público. Rede privada, loopback, link-local, multicast e os ranges de metadados de nuvem são recusados.
  • A validação roda no cadastro e de novo a cada entrega, contra DNS rebinding.
  • Redirecionamento não é seguido.

Segredo

Cada endpoint tem segredo próprio, mostrado uma única vez na criação. Ele fica cifrado no banco com AES-256-GCM — precisa ser recuperável para assinar cada entrega, então não pode ser hash.

A rotação gera um segredo novo imediatamente. Atualize o seu servidor antes de considerar a troca concluída: as entregas seguintes já usam o novo.

Licenças de teste não disparam

Licenças do Playground não geram webhook. Para testar a sua integração, emita uma licença normal para um e-mail seu e revogue-a depois.