POST /ingest/stripe/{organizationId}: webhook público do Stripe, autenticado pela assinatura HMAC do próprio Stripe (não pela sua API key).POST /ingest/custom: endpoint server-to-server (S2S), autenticado pela sua API key, para enviar o evento normalizado diretamente quando você não usa um gateway suportado.
GET / PUT /settings/stripe, para gravar e ler (mascarado) o segredo de assinatura do webhook do Stripe da sua conta.
A ingestão é a forma recomendada de registrar cobranças recorrentes. Para entender o que acontece depois (atribuição ao Afiliado, criação da Comissão e tratamento de fraude), veja Conversões e fraude.
O evento normalizado
Todo gateway é apenas um tradutor (payload do provedor → evento normalizado) mais uma verificação de assinatura. O Repass conhece um único contrato, uma união discriminada porkind:
Os eventos
charge, refund e cancellation não trazem dados de atribuição: apontam para uma Conversão existente por conversionId (ULID com prefixo conv_) ou por customerId (o id do cliente no gateway). Pelo menos um dos dois é obrigatório.
Dinheiro sempre em centavos (inteiro), nunca em float. Apenas BRL é suportado: eventos em outra moeda são ignorados na tradução.
Deduplicação por sourceEventId
A idempotência da ingestão é de negócio e permanente, indexada pelo sourceEventId de cada evento. As rotas de ingestão não usam o header Idempotency-Key: você não precisa enviá-lo. Em vez disso, todo evento carrega um sourceEventId estável, e o processamento de Conversão/Comissão garante que o mesmo sourceEventId produza um único efeito.
Isso significa que reentregas do gateway (o Stripe reenvia o mesmo webhook várias vezes, por exemplo) são absorvidas sem duplicar conversões ou comissões: o desfecho é simplesmente replayed, apontando para o efeito original.
Desfechos da ingestão
A ingestão não tem máquina de estados própria; ela apenas encaminha o evento. Cada chamada produz exatamente um desfecho terminal (outcome), que descreve como o evento foi tratado:
processed
processed
O evento gerou efeito novo: Conversão criada e atribuída, cobrança registrada com Comissão nova, refund/clawback aplicado, ou cancelamento que anulou comissões. Um cancelamento que não tinha nada a anular continua
processed, com reason: "nothing_to_void" (idempotente).replayed
replayed
O mesmo
sourceEventId já havia sido processado; nenhum efeito novo. É a reentrega idempotente.unmatched
unmatched
Uma Conversão não foi atribuída a nenhum Afiliado (
no_attribution), ou um charge/refund/cancellation por customerId não achou Conversão ativa (customer_not_attributed). Nada é persistido.skipped
skipped
Uma regra de negócio impede o efeito de forma legítima: cliente com mais de uma Conversão ativa (
ambiguous_customer), chargeback contra Conversão sem comissões (no_commissions), ou um motivo herdado da cobrança (no_rule: nenhuma regra de comissão aplicável; no_eligible_affiliate: nenhum afiliado elegível; recurrence_exhausted: recorrência da regra já esgotada).ignored
ignored
O tradutor decidiu não mapear o evento (tipo não tratado, moeda diferente de BRL, cliente ausente). O
reason carrega o motivo. Só ocorre no webhook: o /ingest/custom não aceita esse kind.Webhook do Stripe
O webhook do Stripe é autenticado pela assinatura HMAC do próprio Stripe, não pela sua API key. A sua conta é identificada no path (organizationId), e a verificação usa o segredo (whsec_...) que você gravou em /settings/stripe.
Comportamento de status
O webhook responde 200 sempre que a assinatura é válida, mesmo para eventos não tratados, sem match ou rejeitados por regra de negócio. Isso é deliberado: um 4xx faria o Stripe reentregar o evento indefinidamente. O campooutcome no corpo da resposta diz o que realmente aconteceu.
Exemplo de resposta:
Eventos do Stripe suportados
O tradutor é determinístico: tudo que não casa com uma regra explícita viraignored, e o webhook responde 200 para o Stripe parar de reentregar.
A atribuição de uma assinatura vem da metadata do objeto Stripe. O tradutor procura
repass_cid (clickId) e repass_pid (programId) na metadata da invoice, do line item e do subscription_details (incluindo o layout da API Stripe 2025+). O clickId só é aceito se prefixado clk_; o programId, se prefixado prog_.
Ingestão custom (S2S)
Quando você não usa um gateway suportado, envie o evento normalizado diretamente paraPOST /ingest/custom. Diferente do webhook, este endpoint é autenticado pela sua API key e propaga erros de negócio como 4xx normais (404/409) em vez de mascará-los como skipped.
O body é a mesma união discriminada por kind, sem a variante ignored.
- conversion
- charge
- refund
- cancellation
/ingest/custom:
Chargebacks via
charge.dispute.created entram pelo webhook quando a secretKey (sk_…) está configurada. Sem ela, o evento é ignored (dispute_requires_api_lookup) e você pode registrar o chargeback pelo /ingest/custom com "chargeback": true. Veja Refund e clawback e Integrar Stripe.Resolução de Conversão e casos de borda
Paracharge, refund e cancellation, a Conversão é resolvida assim:
1
conversionId explícito
Busca por id. Se não existir, retorna 404: a referência enviada está errada.
2
customerId
Busca Conversões ativas do cliente: zero ⇒
unmatched (customer_not_attributed); exatamente uma ⇒ usa essa; mais de uma ⇒ skipped (ambiguous_customer). Nunca chuta.Configuração do Stripe
O segredo de assinatura do webhook (whsec_...) é gravado por conta. Ele é usado apenas para a verificação HMAC dos webhooks recebidos do Stripe.
Suporte a outros gateways
O modelo do Repass é deliberadamente agnóstico de gateway: o contrato normalizado e o processamento de Conversão/Comissão são únicos, e cada provedor entra apenas como uma tradução do seu payload para o evento normalizado mais a verificação de assinatura do webhook. Na prática, isso significa que:- A atribuição, o cálculo de comissão, o clawback e o void de comissões funcionam da mesma forma, independentemente de qual gateway originou o fato financeiro.
- Enquanto o seu gateway não tiver um webhook nativo no Repass, você pode integrá-lo hoje enviando os mesmos eventos normalizados (
conversion/charge/refund/cancellation) pelo/ingest/custom. Use o id do fato financeiro do provedor comosourceEventIdpara herdar a deduplicação.
Próximos passos
Integrar Stripe
Metadata
repass_cid, Connect vs manual e checklist de atribuição.Conversões e fraude
O que acontece depois da ingestão: atribuição, criação da Conversão e filtros antifraude.
Comissões
Como uma cobrança vira Comissão, e como refund vira void ou clawback.
Conversões server-to-server
Guia prático de envio de eventos pelo
/ingest/custom.Refund e clawback
Registrar estornos e chargebacks de ponta a ponta.