Minstrel
Navegar na documentação

Webhooks

Webhooks

Receba eventos do Minstrel com assinatura HMAC verificada, gerencie endpoints pela API, rotacione o segredo sem perder evento e reenvie entregas.

Guia de integração · 17 min de leitura

Nesta página

Webhooks sao a forma correta de saber o que aconteceu com uma cobranca. Fazer polling em GET /v1/payments/{id} funciona, mas desperdica requisicao e atrasa a sua reacao.

Endpoints, entregas e eventos sao separados por ambiente: uma chave de sandbox so ve e so recebe eventos de sandbox. Leitura exige webhooks:read; cadastro, edicao, rotacao, teste e reenvio, webhooks:write; a consulta de eventos, events:read.

Cadastrar um endpoint

Pelo painel, em Webhooks, ou pela API:

cURL / Bash
curl -X POST http://localhost:3333/v1/webhooks \
  -H "Authorization: Bearer $MINSTREL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.sualoja.com.br/webhooks/minstrel",
    "description": "Confirma pedidos pagos e avisa recusas",
    "enabledEvents": ["payment.captured", "payment.failed", "invoice.*"],
    "customHeaders": { "X-Api-Key": "chave-do-seu-servidor" }
  }'

A resposta traz o segredo de assinatura em secret (whsec_...). Guarde-o num gerenciador de segredos: listagem e consulta nunca o devolvem, e mostra-lo de novo exige uma revelacao auditada.

Cada ambiente aceita ate 20 endpoints, e uma URL so pode ser cadastrada uma vez por ambiente - duas inscricoes na mesma URL entregariam cada evento em dobro. Os dois casos respondem 409.

Regras da URL

Quem dispara a requisicao e o servidor do Minstrel, entao a URL passa por regras que impedem usar o webhook para alcancar redes internas:

  • https obrigatorio. Usuario e senha na URL sao recusados; para autenticar, use um cabecalho extra.
  • Rede interna e recusada no cadastro: IP privado (10/8, 172.16/12, 192.168/16), loopback, link-local (169.254/16), CGNAT (100.64/10), multicast, IPv6 local, nome sem dominio (postgres, api) e sufixos de intranet (.local, .internal, .lan, .corp e similares).
  • E de novo na conexao, pelo IP resolvido. Um dominio publico que passe a resolver para um endereco interno depois do cadastro (DNS rebinding) e barrado na hora da entrega: basta um endereco interno entre os resolvidos para a entrega falhar com "Endereco interno bloqueado".
  • localhost so em sandbox, numa instalacao local do Minstrel - e ai http:// tambem vale. Num servidor de producao, localhost seria o proprio servidor do Minstrel, nunca a sua maquina, e e recusado mesmo em sandbox: para testar no seu computador, use um tunel (ngrok, Cloudflare Tunnel).

Eventos e curingas

enabledEvents aceita tipos exatos e curingas:

  • payment.captured - um evento especifico;
  • payment.* - todos os eventos do recurso, inclusive os que forem criados depois;
  • * - todos (util em desenvolvimento, raramente em producao).

Evento desconhecido e recusado com 422: um erro de digitacao (payment.capture) criaria um endpoint que nunca recebe nada. Tipos ja cobertos por um curinga da lista sao descartados, e * substitui todo o resto. GET /v1/webhooks/event-types devolve o catalogo agrupado por recurso, com o curinga de cada grupo.

Cabecalhos extras

customHeaders vai em toda entrega - use para a chave de API do seu lado, por exemplo. Ate 10 cabecalhos, valor em texto ASCII de ate 1.024 caracteres. Cabecalhos que o Minstrel controla (content-type, user-agent, host, content-length e afins, alem de qualquer minstrel-*) sao recusados: um cabecalho extra nunca substitui a assinatura. Nas respostas da API, o valor aparece mascarado em preview, com no maximo os 4 ultimos caracteres.

Gerenciar endpoints

EndpointO que faz
GET /v1/webhooksEndpoints do ambiente, com taxa de sucesso, entregas por hora nas ultimas 24 horas e a ultima entrega.
GET /v1/webhooks/:idUm endpoint, com os mesmos numeros, o tempo de resposta e a politica de entrega.
PATCH /v1/webhooks/:idAltera URL, descricao, eventos, cabecalhos extras ou enabled.
DELETE /v1/webhooks/:idRemocao logica: o endpoint para de receber e as entregas na fila sao canceladas.
GET /v1/webhooks/summaryEndpoints ativos, com falha e desligados; entregas e taxa de sucesso nas ultimas 24 horas contra as 24 anteriores.
GET /v1/webhooks/event-typesCatalogo de eventos inscreviveis, agrupado por recurso.

Na edicao, customHeaders e mesclado com o que ja existe: texto cria ou substitui, null remove, e o que nao for citado continua como esta - o valor secreto nao precisa voltar. Trocar a URL zera as falhas seguidas, que eram do endereco antigo.

Desativar ("enabled": false) cancela as entregas na fila; a resposta informa quantas em canceledDeliveries. Reativar zera as falhas seguidas. Cada endpoint traz a situacao em status:

statusSignificado
activeRecebendo normalmente.
failingRecebendo, mas a tentativa mais recente falhou (consecutiveFailures maior que zero).
disabledDesligado por alguem.
auto_disabledDesligado pelo Minstrel apos falhas seguidas (veja disabledReason).

Rotacao e revelacao do segredo

cURL / Bash
curl -X POST http://localhost:3333/v1/webhooks/whe_01HQ.../rotate-secret \
  -H "Authorization: Bearer $MINSTREL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "gracePeriod": "24h" }'

A rotacao gera um segredo novo, devolvido uma unica vez em secret:

  • "gracePeriod": "24h" (o padrao, tambem sem corpo): o segredo atual continua assinando por 24 horas junto com o novo. Durante a janela, o cabecalho de assinatura leva dois v1 - tempo para trocar a variavel de ambiente do seu servidor sem perder evento. secretRotation.previousSecretExpiresAt diz quando a janela fecha.
  • "gracePeriod": "none": o segredo atual deixa de valer na hora. Use quando ele vazou.

So existe um segredo anterior: rotacionar de novo dentro da janela descarta o mais antigo na hora.

POST /v1/webhooks/:id/reveal-secret mostra o segredo atual. Exige webhooks:write e fica registrado na trilha de auditoria como webhook_endpoint.secret_revealed, com quem pediu e de onde.

Evento de teste

cURL / Bash
curl -X POST http://localhost:3333/v1/webhooks/whe_01HQ.../test \
  -H "Authorization: Bearer $MINSTREL_API_KEY"

Cria um evento webhook_endpoint.test e o entrega na hora, assinado como qualquer outro - e o jeito de testar a sua verificacao de assinatura. A resposta e a propria entrega, com o status e o corpo devolvidos pelo seu servidor.

O evento de teste vai so para o endpoint testado, nunca para os demais inscritos (nem para os inscritos em *), e nao aceita inscricao: incluir webhook_endpoint.test em enabledEvents responde 422. Se a entrega falhar, ela segue a mesma politica de retentativa das entregas reais. Endpoint desativado responde 409: ative-o antes de testar.

Formato do envelope

json
{
  "id": "evt_01HQ8M5X7P2K3N4R5T6V7W8X9Y",
  "type": "payment.captured",
  "apiVersion": "2026-01-01",
  "createdAt": "2026-01-15T14:32:10.123Z",
  "environment": "live",
  "sequence": 48213,
  "data": {
    "object": { "object": "payment", "id": "pay_...", "status": "captured" },
    "previousAttributes": { "status": "authorized" }
  }
}

O campo sequence e monotonico por organizacao. Use-o para ordenar: com retentativa, entregas chegam fora de ordem, e aplicar um evento antigo depois de um recente corromperia o seu estado.

Cada entrega e um POST com estes cabecalhos, alem dos seus cabecalhos extras:

CabecalhoConteudo
Content-Typeapplication/json
User-AgentMinstrel-Webhooks/1.0
Minstrel-SignatureAssinatura, descrita abaixo.
Minstrel-Event-IdO id do evento.
Minstrel-Event-TypeO type do evento.
Minstrel-Delivery-AttemptNumero da tentativa desta entrega, a partir de 1.
Minstrel-VersionVersao do contrato do payload (2026-01-01).

Verificando a assinatura

Exemplo
Minstrel-Signature: t=1736899200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
  • t e o unix timestamp da assinatura;
  • v1 e o HMAC-SHA256 de ${t}.${corpo_bruto} com o segredo do endpoint.

Use o segredo inteiro como chave do HMAC, com o prefixo whsec_.

Valide contra o corpo bruto

Este e o erro mais comum ao integrar webhooks. Valide antes de qualquer parse de JSON:

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

export function verifyMinstrelSignature(params: {
  rawBody: string; // string ou Buffer exatamente como chegou
  header: string;
  secret: string;
  toleranceSeconds?: number;
}): boolean {
  const parts = params.header.split(',').reduce<Record<string, string[]>>((acc, part) => {
    const [key, value] = part.trim().split('=', 2);
    if (!key || !value) return acc;
    (acc[key] ??= []).push(value);
    return acc;
  }, {});

  const timestamp = Number(parts.t?.[0]);
  const signatures = parts.v1 ?? [];
  if (!Number.isFinite(timestamp) || signatures.length === 0) return false;

  // Rejeita assinaturas antigas: impede replay.
  const tolerance = params.toleranceSeconds ?? 300;
  if (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > tolerance) return false;

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

  // Comparacao em tempo constante.
  return signatures.some((candidate) => {
    const a = Buffer.from(candidate, 'utf8');
    const b = Buffer.from(expected, 'utf8');
    return a.length === b.length && timingSafeEqual(a, b);
  });
}

Reserializar o JSON muda bytes - ordem de chaves, espacos, escapes unicode - e invalida a assinatura. Em Express, use express.raw({ type: 'application/json' }); em Fastify, configure rawBody: true.

Varias assinaturas no mesmo header

Durante a janela de rotacao do segredo o header carrega dois v1: o do segredo novo e o do anterior. Aceite se qualquer um casar - e assim que voce troca o segredo sem perder evento.

Retentativa

Respondemos ao seu 2xx como confirmacao. Qualquer outra resposta (inclusive redirecionamento, que nao e seguido), erro de conexao ou ausencia de resposta em 10 segundos agenda nova tentativa:

TentativaQuando
1Imediata
2~30 segundos
3~2 minutos
4~10 minutos
5~1 hora
6~6 horas
7~24 horas

Cada intervalo conta a partir da tentativa anterior e tem jitter de mais ou menos 20%. Sem isso, uma queda de cinco minutos no seu endpoint faria milhares de entregas retentarem no mesmo instante, derrubando-o justamente quando ele volta.

Apos 7 tentativas a entrega fica exhausted. Cada tentativa sem 2xx soma uma falha seguida no endpoint, que passa a aparecer como failing, e qualquer 2xx zera a contagem. O desligamento automatico exige as duas condicoes: 20 falhas seguidas e 3 dias sem nenhuma entrega bem-sucedida (contados da ultima entrega com sucesso ou, se nunca houve, do cadastro). Uma queda de minutos, mesmo com muito volume, nao desliga o endpoint. Desligado, ele fica auto_disabled, com o motivo em disabledReason, e as entregas na fila sao canceladas. Corrija o endpoint, reative-o com PATCH e reenvie o que faltou.

Entregas

Cada evento gera uma entrega por endpoint inscrito:

statusSignificado
pendingNa fila para envio.
succeededO endpoint respondeu 2xx.
failedA ultima tentativa falhou; ha nova tentativa agendada (nextRetryAt).
exhaustedAs 7 tentativas falharam.
disabledCancelada porque o endpoint foi desativado ou removido.
cURL / Bash
curl "http://localhost:3333/v1/webhooks/whe_01HQ.../deliveries?status=failed,exhausted&eventType=payment.*" \
  -H "Authorization: Bearer $MINSTREL_API_KEY"

A listagem aceita status (lista separada por virgula), eventType (exato ou curinga como payment.*), createdFrom, createdTo, search (id exato da entrega whd_... ou do evento evt_...), limit (1 a 100, padrao 25) e startingAfter.

GET /v1/webhooks/:id/deliveries/:deliveryId mostra a requisicao como ela saiu, com o corpo exato que foi assinado e os cabecalhos (os extras mascarados), e a resposta do seu endpoint, truncada em 8 KB (truncated avisa quando cortou). A assinatura nao e guardada: ela muda a cada tentativa, porque o timestamp faz parte dela.

Reenvio

cURL / Bash
curl -X POST http://localhost:3333/v1/webhooks/whe_01HQ.../deliveries/whd_01HQ.../retry \
  -H "Authorization: Bearer $MINSTREL_API_KEY"

Zera as tentativas e coloca a entrega na fila; ela sai em poucos segundos. Vale tambem para entrega que ja teve sucesso - e o caminho normal para reprocessar um evento do seu lado depois de corrigir uma indisponibilidade. Endpoint desativado responde 409: reative-o antes.

Consultar eventos

GET /v1/events lista os eventos do ambiente, do mais novo para o mais antigo pela sequence, no mesmo envelope entregue aos webhooks. Serve para depurar sem endpoint ("o evento foi gerado? com que dados?") e para reconciliar depois de uma indisponibilidade:

cURL / Bash
curl "http://localhost:3333/v1/events?objectId=pay_01HQ...&type=payment.*" \
  -H "Authorization: Bearer $MINSTREL_API_KEY"
ParametroEfeito
typeTipo exato ou curinga (payment.*).
objectType, objectIdTodos os eventos de um recurso (pay_..., sub_...).
createdFrom, createdToPeriodo.
searchId exato do evento ou do objeto.
limit, startingAfterPagina (1 a 100, padrao 25) e cursor: o id do ultimo evento da pagina anterior.

GET /v1/events/:id traz o payload completo. Com o escopo webhooks:read, a lista inclui o resumo das entregas de cada evento e o detalhe traz cada entrega com o endpoint e o status - inclusive as de endpoints ja removidos (endpointDeleted: true). Sem esse escopo, as entregas ficam de fora, porque revelariam os endpoints cadastrados.

Idempotencia do seu lado

Entrega duplicada e esperada - preferimos entregar duas vezes a perder um evento. Guarde o event.id e ignore os repetidos:

ts
const alreadyProcessed = await db.processedEvents.findUnique({
  where: { id: event.id },
});
if (alreadyProcessed) return reply.code(200).send();

Catalogo de eventos

GET /v1/webhooks/event-types devolve o catalogo completo, agrupado por recurso, com o curinga de cada grupo e a descricao de cada tipo. Os mais usados:

EventoQuando acontece
payment.capturedValor capturado. E o que confirma a venda.
payment.failedRecusado e encerrado. Inclui a classificacao ABECS em data.object.decline. No checkout transparente so sai quando o pagamento acabou de fato (recusa irreversivel, fim das tentativas de cartao ou prazo); data.object.checkout.endedBy diz qual. Veja Nova tentativa de cartao.
payment.attempt_declinedCheckout transparente: cartao recusado por motivo reversivel. O pagamento voltou para requires_payment_method e o portador pode informar outro cartao, com o mesmo clientSecret, ate o prazo e o limite de tentativas. Veja Nova tentativa de cartao.
payment.checkout_not_configuredCheckout transparente: a conta do conector esta mal configurada e a tokenizacao nao abriu. O portador recebeu o erro checkout_not_configured; o motivo completo vem em data.object.error. Veja Checkout sem configuracao.
payment.refundedEstornado integralmente.
payment.authorization_expiringPre-autorizacao perto do fim do prazo de captura (Mastercard 7 dias, demais bandeiras 15). Traz o prazo em data.object.authorizationExpiresAt e a acao tomada em data.object.expiryAction: notify (so avisa), capture ou void.
payment.fraud_review_resolvedFim da revisao de fraude do adquirente (Cielo). O resultado vem em data.object.fraudReview.status: accepted, rejected ou merchant_decided. Veja Fim da revisao de fraude.
antifraud.assessment_completedAnalise de antifraude concluida, pelo no Antifraude do fluxo (origin: "flow_node") ou pelo adquirente na autorizacao (origin: "acquirer"). Veja Analise de antifraude concluida.
payment_method.verifiedCartao validado sem cobranca (Zero Auth). O resultado vem em data.object.verification.status: valid, invalid ou unavailable (servico fora do ar ou nao habilitado, o que nao diz nada sobre o cartao).
invoice.payment_failedCobranca de fatura falhou. Traz a decisao de retentativa.
subscription.canceled_by_issuerEmissor determinou a suspensao. Nao retente.
retry.exhaustedPolitica de retentativa esgotada sem aprovacao.
recipient.updatedDados de um recebedor de split alterados.
flow.notificationEmitido por um no "Notificar webhook" do fluxo.

Alguns tipos do catalogo ainda nao sao emitidos nesta versao: a inscricao e aceita, mas nenhuma entrega acontece por enquanto. Sao eles payment.attempt.created, payment_method.expiring, invoice.finalized, invoice.uncollectible, dispute.*, chargeback.received, payout.*, flow.published, connector_account.health_changed e communication.*.

O webhook_endpoint.test fica fora dos grupos de event-types (vem a parte, em testEventType) e nao aceita inscricao: vai so para o endpoint testado.

Pre-autorizacao perto de vencer

payment.authorization_expiring sai 24 horas antes do prazo de captura de uma pre-autorizacao (pagamento authorized, sem captura). A acao nesse momento vem da configuracao Pre-autorizacao perto de vencer da conta do conector (Plugins, conta, Recursos), e a que foi aplicada chega em expiryAction:

expiryActionO que o Minstrel fez
notifySo avisou (padrao). Capture ou cancele do seu lado, antes do prazo.
captureCapturou o valor autorizado.
voidCancelou a autorizacao e liberou o limite do portador.
json
{
  "type": "payment.authorization_expiring",
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01HQ...",
      "status": "authorized",
      "authorizationExpiresAt": "2026-10-24T14:30:00.000Z",
      "expiryAction": "notify"
    }
  }
}

Com notify, o aviso e o momento de agir: depois do prazo a autorizacao expira e a captura responde 409 payment_not_capturable (Transacoes).

Pagamentos com split

Os eventos de um pagamento com split levam as parcelas no data.object.splits: payment.authorized, payment.captured, payment.voided, payment.refunded e payment.partially_refunded. Cada parcela traz o que o adquirente executou:

json
{
  "type": "payment.captured",
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01HQ...",
      "status": "captured",
      "splits": [
        {
          "recipientId": "rcp_vendedor",
          "amount": 6000,
          "type": "percentage",
          "liableForChargeback": true,
          "commissionRateBps": 500,
          "commissionFixedAmount": 30,
          "netAmount": 5670,
          "feeAmount": 330,
          "capturedAmount": 6000,
          "refundedAmount": 0
        }
      ]
    },
    "previousAttributes": { "status": "authorized" }
  }
}
  • amount e a parcela bruta; netAmount e feeAmount sao o liquido e o desconto como o adquirente informou (feeAmount = amount - netAmount), null e 0 enquanto ele nao liquida a divisao.
  • capturedAmount e refundedAmount acumulam por parcela: uma captura parcial ou um estorno parcial divide o valor entre os recebedores, e o evento sai com os valores ja gravados.
  • A divisao e executada no adquirente. Um pagamento que nao encontra conta capaz de executa-la nao e autorizado: o evento e payment.failed, com data.object.error.code = "split_not_supported" no roteamento direto (veja Catalogo de erros).

Nova tentativa de cartao

No checkout transparente, uma recusa reversivel do emissor nao encerra o pagamento: ele volta para requires_payment_method e o portador informa outro cartao, com o mesmo paymentId e clientSecret. Quem avisa isso e payment.attempt_declined, no lugar de payment.failed:

json
{
  "type": "payment.attempt_declined",
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01HQ...",
      "status": "requires_payment_method",
      "actionExpiresAt": "2026-10-19T14:02:11.000Z",
      "decline": {
        "reason": "INSUFFICIENT_FUNDS",
        "label": "Saldo insuficiente",
        "reversibility": "REVERSIBLE",
        "retryAction": "RETRY_LATER",
        "consumerMessage": "SALDO INSUFICIENTE. TENTE OUTRO CARTAO.",
        "rawCode": "51"
      },
      "checkout": { "attemptsUsed": 1, "attemptsMax": 3, "attemptsRemaining": 2 }
    },
    "previousAttributes": { "status": "processing" }
  }
}
  • Nao cancele o pedido neste evento. O pagamento continua aberto, ate actionExpiresAt. O fim vem como payment.captured/payment.authorized (o portador achou um cartao que passa), payment.failed ou payment.canceled.
  • payment.failed so sai quando o pagamento acabou de fato: recusa irreversivel, ultima tentativa de cartao (padrao: 3) ou prazo vencido. data.object.checkout.endedBy diz qual: irreversible, attempt_limit, expired ou not_issuer_decline (falha tecnica, antifraude ou regra do fluxo, que nao reabrem o pagamento).
  • Recusa irreversivel (regra da ABECS: o emissor nunca aprovara) encerra o pagamento mesmo com tentativas sobrando. Isso nao e configuravel.
  • Cada cartao tentado e uma tentativa do pagamento (attempts), e cada uma roda o fluxo de novo. Pagamento com cartao no corpo, cobranca do lojista, assinatura, Pix e boleto nao usam payment.attempt_declined: a recusa deles continua sendo payment.failed.
  • Se o seu sistema ja trata payment.failed como "cancele o pedido", ele continua certo: no checkout transparente passa a sair um pouco mais tarde, so quando nao ha mais o que tentar.

Checkout sem configuracao

payment.checkout_not_configured registra, para voce, o motivo que o portador nao pode ver. Quando a conta do conector esta mal configurada (por exemplo, uma conta Cielo sem as credenciais do Silent Order Post), a pagina do portador recebe o erro checkout_not_configured e o pagamento segue requires_payment_method; o motivo completo vem aqui, e aparece tambem na linha do tempo do pagamento no painel:

json
{
  "type": "payment.checkout_not_configured",
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01HQ...",
      "status": "requires_payment_method",
      "error": {
        "code": "connector_credentials_invalid",
        "message": "Silent Order Post nao configurado nesta conta: informe o ClientId e o ClientSecret ...",
        "stage": "tokenization_session",
        "connectorAccount": { "id": "ca_01HQ...", "name": "Cielo matriz" }
      }
    }
  }
}

Sai uma vez por motivo e por pagamento (a pagina pode pedir a sessao varias vezes). Corrija a conta e crie um pagamento novo.

Fim da revisao de fraude

payment.fraud_review_resolved sai uma vez por pagamento, quando a revisao de fraude do adquirente termina. O data.object e o pagamento, ja com o resultado em fraudReview.status, e previousAttributes traz o estado anterior (pending):

json
{
  "type": "payment.fraud_review_resolved",
  "data": {
    "object": {
      "object": "payment",
      "id": "pay_01HQ...",
      "status": "captured",
      "fraudReview": { "status": "accepted" }
    },
    "previousAttributes": { "fraudReview": { "status": "pending" } }
  }
}
fraudReview.statusO que aconteceu
acceptedO provedor aceitou. A venda foi capturada ou, com captura manual, segue authorized para voce capturar.
rejectedO provedor recusou e a autorizacao foi cancelada (voided).
merchant_decidedVoce capturou ou cancelou antes de o provedor decidir.

Quando a revisao termina junto com uma mudanca de estado, o evento dessa mudanca (payment.captured ou payment.voided) sai primeiro, com a revisao ja fechada no payload, e este vem logo depois. Com accepted e captura manual nao ha evento de estado: so este. Use-o para liberar o pedido quando o resultado for accepted, mas confira o status do pagamento: ele diz se a venda ja foi capturada.

Analise de antifraude concluida

antifraud.assessment_completed sai a cada analise registrada no pagamento, com data.object no mesmo formato para as duas origens:

json
{
  "type": "antifraud.assessment_completed",
  "data": {
    "object": {
      "object": "antifraud_assessment",
      "id": "afa_01HQ...",
      "paymentId": "pay_01HQ...",
      "origin": "acquirer",
      "provider": "cybersource",
      "providerStatus": "review",
      "recommendation": "review",
      "score": 62,
      "triggeredRules": ["B", "D"]
    }
  }
}
CampoConteudo
originflow_node: o no Antifraude do fluxo, que o Minstrel chama antes de autorizar. acquirer: a analise que o adquirente (Cielo) faz dentro da autorizacao.
providerQuem analisou. No flow_node, o conector (konduto, clearsale); no acquirer, o provedor do adquirente (cybersource, clearsale).
providerStatusSo no acquirer: accept, reject, review, unfinished, provider_error, aborted, unknown ou skipped. null no flow_node.
recommendationapprove, review, decline ou error. Na analise do adquirente, skipped e os demais sem decisao saem como error.
scoreDe 0 a 100, ou null quando o provedor decide sem score.
triggeredRulesRegras acionadas; na Cybersource, os codigos de fator.

O evento sai tambem quando a analise do adquirente e dispensada (skipped, por falta de dado do cliente) e quando o veredito e uma recusa: nesse caso o pagamento chega separadamente como payment.failed. Antes desta versao o tipo estava no catalogo mas nunca era entregue.

Cartao validado

payment_method.verified sai a cada validacao sem cobranca (Zero Auth), seja pelo no Validacao de cartao ou por verify ao salvar o cartao:

json
{
  "type": "payment_method.verified",
  "data": {
    "object": {
      "object": "payment_method",
      "id": "pm_01HQ...",
      "verification": { "status": "valid", "verifiedAt": "2026-10-17T14:02:11.000Z" }
    }
  }
}

unavailable quer dizer que o servico nao validou (fora do ar, bandeira sem suporte ou recurso desligado na conta), o que nao diz nada sobre o cartao: nao trate como cartao ruim. So invalid justifica pedir outro cartao.

As opções são independentes e podem ser alteradas a qualquer momento no rodapé. Sua escolha vale por até 180 dias.

Necessários Sempre ativos

Lembram sua escolha de privacidade e permitem as funções essenciais.

Ler a política de cookies