Ferramenta grátis · Mercado Pago

Validar a assinatura de um webhook
do Mercado Pago (x-signature)

Cole o que o Mercado Pago enviou e veja se a assinatura confere, qual manifest foi assinado e o hash esperado ao lado do recebido. Feito para quando o seu handler de webhooks responde 401 e você não sabe por quê.

Tudo é calculado no seu navegador. A assinatura é calculada nesta página com a Web Crypto API. Nada do que você digita é enviado a algum servidor e o segredo não sai desta página.

O valor completo, no formato ts=…,v1=…

Deixe vazio se a notificação não trouxe.

Vem da query string da URL da notificação (?data.id=…). Deixe vazio se não existir.

A chave secreta da sua aplicação, nas configurações de Webhooks do painel de desenvolvedores do Mercado Pago.

Como o Mercado Pago assina um webhook

Cada notificação de webhook traz uma assinatura HMAC-SHA256 para você provar que ela veio do Mercado Pago e não é um replay. Verificá-la leva cinco passos.

  1. 01

    Separe o header x-signature

    O header tem este formato: x-signature: ts=1704908010,v1=618c8534…. Divida por vírgulas e depois pelo primeiro sinal de igual de cada parte. ts é o timestamp da assinatura (o exemplo oficial tem 10 dígitos, ou seja, segundos; aceite segundos ou milissegundos) e v1 é o hash.

  2. 02

    Reúna as três entradas

    data.id vem da query string da URL da notificação (?data.id=123456), x-request-id é um header da requisição e ts vem do passo um.

  3. 03

    Monte o manifest

    Concatene id:<data.id>;request-id:<x-request-id>;ts:<ts>; exatamente assim, com o ponto e vírgula final. Se data.id ou x-request-id estiver ausente, omita o segmento inteiro. O SDK de Go converte o data.id para minúsculas antes de usá-lo.

  4. 04

    Calcule o HMAC-SHA256

    Assine o manifest usando como chave o segredo de webhook da sua aplicação e pegue o digest em hexadecimal minúsculo.

  5. 05

    Compare e depois confira o timestamp

    Compare o seu digest com v1 em tempo constante e rejeite a requisição se ts for antigo demais. Uma janela de cinco minutos é uma escolha comum.

A mesma verificação em Node.js

Uma implementação sem dependências dos cinco passos, com node:crypto. Coloque numa rota do Express ou do Next.js e chame com os headers da requisição, o parâmetro data.id e o seu segredo.

verify-mercadopago-webhook.ts
 1  import { createHmac, timingSafeEqual } from 'node:crypto';
 2  
 3  export function verifyMercadoPagoWebhook(req, secret: string): boolean {
 4    const xSignature = req.header('x-signature') ?? '';
 5    const xRequestId = req.header('x-request-id') ?? '';
 6    const dataId = String(req.query['data.id'] ?? '').toLowerCase();
 7  
 8    const parts = Object.fromEntries(
 9      xSignature.split(',').map((p) => p.trim().split('=')),
10    );
11    const { ts, v1 } = parts;
12    if (!ts || !v1) return false;
13  
14    let manifest = '';
15    if (dataId) manifest += `id:${dataId};`;
16    if (xRequestId) manifest += `request-id:${xRequestId};`;
17    manifest += `ts:${ts};`;
18  
19    const expected = createHmac('sha256', secret).update(manifest).digest('hex');
20    const a = Buffer.from(expected);
21    const b = Buffer.from(v1);
22    if (a.length !== b.length || !timingSafeEqual(a, b)) return false;
23  
24    // Replay protection: reject a signed timestamp older than 5 minutes.
25    // Mercado Pago's example ts has 10 digits (seconds); accept seconds or milliseconds.
26    const tsMs = Number(ts) < 1e12 ? Number(ts) * 1000 : Number(ts);
27    return Math.abs(Date.now() - tsMs) <= 5 * 60 * 1000;
28  }

Por que a minha assinatura do Mercado Pago é inválida?

Por que a assinatura do meu webhook do Mercado Pago não confere?+
Quase sempre é uma de quatro coisas: o manifest é montado de forma diferente do que o Mercado Pago assinou (ordem errada, falta o ponto e vírgula final, um segmento incluído quando deveria ser omitido), o segredo é de outra aplicação, o data.id foi lido do lugar errado ou está com maiúsculas, ou um proxy alterou os headers. Esta página mostra o manifest que assinou para você comparar com o seu.
O data.id precisa estar em minúsculas?+
O SDK de Go converte o data.id para minúsculas antes de colocá-lo no manifest. Ids numéricos de pagamento não são afetados, então a diferença só aparece com ids alfanuméricos. Este validador converte o data.id para minúsculas por você; se o seu handler não faz isso, notificações com ids alfanuméricos podem falhar.
De onde vem o data.id?+
Do parâmetro data.id da query string da URL da notificação, que coincide com o data.id do corpo JSON. Use o mesmo valor nos dois lugares e não o reformate.
Posso usar o segredo de outra aplicação?+
Não. O segredo pertence a uma aplicação: você o encontra em Suas integrações, na aplicação, em Webhooks. Se tiver várias aplicações ou ambientes, use o segredo da aplicação que enviou a notificação.
A assinatura é válida aqui, mas o meu servidor a rejeita. Por quê?+
O hash pode estar certo e o timestamp ser antigo. A proteção contra replay rejeita um ts assinado que esteja longe demais do horário atual; o servidor da useDeploy usa uma janela de cinco minutos. Ao colar uma notificação antiga, esta página mostra a idade dela em segundos e avisa você.
É seguro colar o meu segredo de webhook aqui?+
O cálculo acontece no seu navegador com a Web Crypto API e a página não faz nenhuma requisição de rede com o que você digita, o que você pode confirmar na aba de rede do navegador. Se mesmo assim preferir não colar um segredo de produção, use o de uma aplicação de teste ou gire o segredo depois.
Quais notificações trazem o header x-signature?+
As notificações de Webhooks trazem o header x-signature com ts e v1. Este validador precisa dos dois: se a sua notificação não tem o header x-signature, não há nada para validar.
useDeploy em resumo
PreçoFounder $99 ou Lifetime $199, pagamento único (sem assinatura)
LicençaCódigo-fonte completo, uso comercial, projetos ilimitados. O Founder é uma versão congelada; o Lifetime inclui todas as versões futuras.
StackFrontend em Next.js, API em Express, runtime Bun, Prisma, BetterAuth
AutenticaçãoBetterAuth: sessões, 2FA, magic links, redefinição de senha
Multi-tenancy e RBACOrganizações com membros, convites, papéis e permissões
PagamentosPolar: cobrança completa (checkout, portal do cliente, webhooks, sincronização de planos). MercadoPago: pagamentos únicos com Checkout Pro e webhooks assinados; as assinaturas ainda não são suportadas. Stripe: scaffold de adapter, ainda não cobra.
Guardrails para agentes de IACamadas de arquitetura forçadas com ESLint, hooks do Claude Code e um AGENTS.md
Reembolso14 dias
Teste: conta grátisCadastre-se grátis e explore o dashboard: organizações, papéis, cobrança, log de auditoria. A licença é comprada por dentro. https://usedeploy.dev/register
DocsDocumentação em inglês, com traduções para espanhol e português dos guias principais