PRA INTEGRADORES / Playground

Playground · HMAC verify

Cole o secret e os headers do webhook + payload bruto recebido. Tudo roda no seu browser via Web Crypto API — nada vai pro servidor.

Quando você precisa desta página
Se você está usando o Outposted pelo painel (psicólogo, agência, infoprodutor), pode fechar esta aba sem culpa — ela não é pra você. Se você é dev integrando o Outposted no seu produto, é aqui que testa a verificação da assinatura HMAC dos webhooks.
Roda 100% no seu browser
Toda computação acontece via Web Crypto API. O secret que você cola nunca sai do browser. Pode usar com tranquilidade até com secret de produção.

Como usar

Pra verificar um aviso recebido

  1. Receba um webhook real no seu endpoint (pode ser via ngrok pra desenvolvimento).
  2. Copie os 3 headers (Outposted-Signature, Outposted-Timestamp) e o body bruto.
  3. Cole nos campos acima junto com o secret do seu webhook (whsec_*).
  4. Clica em Verificar. Verde = bate com a nossa assinatura.

Pra simular um aviso

  1. Cola seu secret e o payload que você quer testar.
  2. Clica em Assinar. Preenchemos timestamp e signature calculados na hora.
  3. Pega esses valores e manda como POST pro seu endpoint local. Seu código de verificação tem que dar OK.
Pra integradores

Equivalente server-side

Esta verificação no servidor (Node.js ou Cloudflare Worker):

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyOutpostedWebhook(opts: {
  secret: string;
  signatureHeader: string;   // "sha256=..."
  timestampHeader: string;   // unix epoch
  rawBody: string;
  toleranceSeconds?: number;
}): boolean {
  const { secret, signatureHeader, timestampHeader, rawBody } = opts;
  const tolerance = opts.toleranceSeconds ?? 300;

  const presented = signatureHeader.replace(/^sha256=/, '');
  const timestamp = parseInt(timestampHeader, 10);
  if (Number.isNaN(timestamp)) return false;

  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > tolerance) return false;

  const computed = createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');

  const a = Buffer.from(presented, 'hex');
  const b = Buffer.from(computed, 'hex');
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}

Atalho via SDK

import { Outposted } from '@outposted/node';

const valid = Outposted.webhooks.verify({
  payload: rawBody,
  signature: req.header('outposted-signature')!,
  timestamp: req.header('outposted-timestamp')!,
  secret: process.env.OUTPOSTED_WEBHOOK_SECRET!,
});

Endpoint público de verificação

Se você não está em Node nem em ambiente com Web Crypto, dá pra usar nosso endpoint público que valida pra você:

curl -X POST "https://api.outposted.one/api/v1/webhooks/verify" \
  -H "Content-Type: application/json" \
  -d '{
    "secret": "whsec_...",
    "signature_header": "sha256=a3f...",
    "payload": "1735350120.{\"id\":\"evt_...\"}",
    "tolerance_seconds": 300
  }'
Use só pra debug. Em produção, faça a verificação localmente — mandar o secret pra qualquer endpoint, mesmo o nosso, não é boa prática.
← WebhooksCódigos de erro →