Skip to main content
Cobrança é assíncrona: você cria a fatura, a pessoa paga minutos (ou dias) depois, em outra aba, no app do banco. Existem dois jeitos de descobrir isso — e em sandbox só um deles funciona.

Em sandbox: polling

Registrar webhook com chave sk_test_ responde:
Não é bug seu e não é intermitente: o cofre de segredos não está disponível pra tenant de sandbox, então não existe segredo pra assinar entrega. Em sandbox, o caminho é perguntar:
waitForPaid aceita intervalMs, timeoutMs, onTick (pra atualizar contador na tela) e signal. É o que você quer rodando enquanto o QR do Pix está na tela.
O que funciona em sandbox. webhooks.list() e webhooks.listDeliveries() respondem 200 (com lista vazia). Só o create — que precisa gravar segredo — é que para no 503.

Em produção: registrar o endpoint

O secret vem uma vez, na criação. Perdeu? infi.webhooks.rotateSecret(id) emite outro, e a troca é imediata: as entregas seguintes já vêm assinadas com o novo, e o anterior para de verificar na hora. Atualize o segredo no seu servidor logo em seguida, ou as entregas desse intervalo falham na verificação (e são reenviadas). Também existem list, get, patch(id, { isActive, events }), delete e listDeliveries() pra auditar o que saiu. Se você usa company as code, o mesmo endpoint pode ser declarado em webhooks[] no infi.company.ts — em sandbox o sync vai bater no mesmo 503.

Os eventos

Nomes vêm do header X-Webhook-Event-Type, não do corpo: customerId é a inscrição (ProductCustomer.id) e vem em fatura de assinatura; payerId é o cliente do tenant e vem em fatura avulsa. Um dos dois está ausente conforme o caso — por isso os dois são opcionais. O despacho casa por nome, sem allowlist: qualquer evento acima pode ser assinado, e a lista cresce. Corpo é JSON plano, decimais e uuids como string, campo opcional ausente (não null).

Verificar a assinatura

verifyWebhook joga InfiError com code:
  • invalid_webhook_signature — assinatura não bate (segredo errado, ou o corpo foi reserializado no caminho).
  • webhook_expired — timestamp fora da janela de 5min (proteção de replay). Dá pra afrouxar passando o terceiro argumento em segundos.
  • invalid_webhook — timestamp ou JSON inválido.
Não parseie antes de verificar. A assinatura é sobre os bytes exatos do corpo. Qualquer framework que faça JSON.parse e reserialize antes de você verificar invalida tudo. Leia raw.
Fora de Node/TS, o esquema é simples: HMAC-SHA256(secret, "{id}.{timestamp}.{body}") em hex, comparado em tempo constante com o header X-Webhook-Signature (que pode vir prefixado, v1=abc…). Aceite qualquer uma das assinaturas separadas por vírgula: hoje vem uma só, e o formato deixa espaço para mais.

Entrega é “pelo menos uma vez”

Trate o handler como idempotente — e a chave óbvia é a errada. Deduplicar por event.id deixa passar duas entregas distintas para a mesma fatura, que continuam sendo uma compra só. Chaveie pela fatura:
Marque antes do efeito, não depois: uma falha no meio custa um efeito perdido, que se recupera. A ordem inversa custa um efeito duplicado — num fluxo de crédito, saldo de graça. Reentrega depois de um 5xx seu é comportamento esperado, não anomalia.

Testar no sandbox

O que o sandbox é de verdade, e onde o loop fecha.

SDK

Cliente, inscrição, medição de uso.