C Cashbanx Webhooks
PTEN

Documentação de integração

Webhooks

Como a Cashbanx notifica o parceiro sobre o ciclo de vida de uma compra — da identificação ao pagamento do cashback.

Documento NR-001/01 Versão 1.0 — agosto de 2026 Público parceiros integrados

01Como funciona

A Cashbanx acompanha a compra que o seu usuário fez na loja parceira e avisa você a cada mudança relevante. São quatro eventos, cada um com uma URL própria no seu ambiente. Nós fazemos um POST; você responde.

  1. O usuário sai do seu ambiente para a loja por um link da Cashbanx. Esse clique é registrado e carrega o userIdentifier — o identificador do usuário no seu sistema.
  2. A rede afiliada nos informa a compra. Nós a associamos ao clique e disparamos RECOGNIZED_PURCHASE.
  3. Quando a rede confirma a compra, disparamos CONFIRMED_PURCHASE; se ela cancela, disparamos CANCELED_PURCHASE.
  4. Quando o resgate do cashback é pago, disparamos PAID_CASHBACK.
Nem toda compra percorre os quatro

Uma compra cancelada não recebe confirmação nem pagamento. E um evento sem URL configurada simplesmente não é enviado — não fica em fila esperando você configurar depois.

02O que precisamos de você

ItemDescrição
RECOGNIZED_PURCHASEURL do endpoint que recebe a compra identificada.
CONFIRMED_PURCHASEURL do endpoint que recebe a confirmação.
CANCELED_PURCHASEURL do endpoint que recebe o cancelamento.
PAID_CASHBACKURL do endpoint que recebe o pagamento do resgate.
Chave de APIUm valor secreto que enviaremos em todo POST, para você confirmar que a chamada é nossa. Até 255 caracteres.

As URLs são independentes: podem apontar para quatro endpoints distintos ou para o mesmo — o campo webhookType do corpo diz qual evento chegou. Recomendamos HTTPS em todas elas.

Cada ambiente tem sua própria configuração. As URLs e a chave de homologação não são as de produção.

03Autenticação

O padrão é uma chave estática em header. Todo POST que sai da Cashbanx carrega:

x-api-key: <a chave combinada com você>

Rejeite qualquer chamada que não traga a chave correta. Ela é o único fator que identifica a origem — não assinamos o corpo e não enviamos timestamp; a proteção contra terceiros é a chave somada ao TLS.

Variação: OAuth 2.0

Para parceiros que exigem token de acesso, a Cashbanx pode obter um token no seu endpoint de autenticação antes de cada envio e enviar o webhook com Authorization: Bearer no lugar do x-api-key. Nesse arranjo precisamos da URL de login e das credenciais, e suportamos duas formas de apresentá-las:

  • Corpo x-www-form-urlencoded — enviamos os parâmetros combinados (por exemplo grant_type, client_id, client_secret) no corpo do POST de login.
  • Authorization: Basic — enviamos a credencial no header, com corpo vazio.

Nos dois casos esperamos uma resposta JSON com o campo access_token. Este é um arranjo combinado caso a caso; a integração padrão usa apenas o x-api-key.

04A requisição

POSTa URL que você configurou para o evento
CaracterísticaValor
MétodoPOST
Content-Typeapplication/json
Autenticaçãox-api-key
Timeout30 segundos
Redirecionamentosseguidos automaticamente
Responda rápido, processe depois

Trinta segundos sem resposta contam como falha e entram na fila de reenvio. Se o seu processamento é demorado, aceite a notificação, responda 200 e trate o corpo de forma assíncrona.

05Os quatro eventos

EventoQuando disparamosObservação
RECOGNIZED_PURCHASE A rede afiliada nos informou a compra e nós a identificamos. A compra nasce pendente. Nada foi creditado ainda.
CONFIRMED_PURCHASE A rede afiliada confirmou a compra. Fim do prazo de cancelamento da loja. É aqui que o cashback deixa de ser provisório.
CANCELED_PURCHASE A rede afiliada cancelou a compra. Estado final. Nenhum outro evento sai para essa compra.
PAID_CASHBACK O resgate do cashback passou a pago. Estado final do ciclo financeiro.

06Payload

O corpo é sempre o mesmo envelope: o tipo do evento e a transação.

{
  "webhookType": "RECOGNIZED_PURCHASE | CONFIRMED_PURCHASE | CANCELED_PURCHASE | PAID_CASHBACK",
  "transaction": { }
}

Exemplos por evento

A compra foi identificada e está pendente. Nada foi creditado ainda.

{
  "webhookType": "RECOGNIZED_PURCHASE",
  "transaction": {
    "id": 23026,
    "clickOrigin": "Android Mobile",
    "voucherCode": "",
    "status": "Pending",
    "statusUpdateDate": null,
    "type": "Identified",
    "cashbackStatus": "Pending",
    "amended": false,
    "amendReason": "",
    "createdDate": "2026-08-14T07:12:25.000Z",
    "updatedDate": null,
    "transactionDate": "2026-08-13T23:59:00.000Z",
    "paidDate": null,
    "thirdPartyId": "1527912405",
    "purchaseOrderNumber": "16181113",
    "paymentOrderNumber": null,
    "amount": 350,
    "oldAmount": null,
    "currency": "BRL",
    "sourceAmount": null,
    "sourceCurrency": "",
    "quotationValue": null,
    "oldQuotationValue": null,
    "commission": 17.5,
    "oldCommission": null,
    "commissionPercentage": 0.05,
    "commissionReceiptDate": null,
    "cashbackValue": 10.5,
    "oldCashbackValue": null,
    "cashbackPercentage": 0.03,
    "cashbackPoints": 350,
    "taxValue": 1.75,
    "partnerValue": 0,
    "companyValue": 5.25,
    "paidPartnerValue": false,
    "paymentDatePartnerValue": null,
    "productBasket": null,
    "photo": "",
    "store": {
      "id": 3176,
      "name": "Nike",
      "logo": "https://cashbanx.s3.amazonaws.com/retangle-logos/nike.png",
      "circleLogo": "https://cashbanx.s3.amazonaws.com/circle-logos/nike.png"
    },
    "user": {
      "id": 8842,
      "userIdentifier": "3c217db6-fa75-4252-94dd-af8e10b77454",
      "name": "Maria Souza"
    },
    "goOut": {
      "id": 1251,
      "additionalProps": "campanha-dia-das-maes",
      "date": "2026-08-13 09:56:47",
      "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148"
    }
  }
}

Dicionário de campos

A coluna presença diz com o que você pode contar. São três casos, e a diferença entre eles é o que decide se o seu código precisa de guarda:

  • sempre — a chave existe em todo envio, com valor útil. Pode usar direto.
  • pode vir vazio — a chave existe sempre, mas o valor pode ser null (campos numéricos e de data) ou string vazia (campos de texto). Nunca falta; pode não dizer nada.
  • pode faltar — a chave pode não existir no JSON. Ler sem guarda quebra.

A regra por trás disso: campo de texto sem valor chega como "", campo numérico ou de data sem valor chega como null, e o que não se aplica àquele envio desaparece em vez de vir nulo.

CampoPresençaDescrição
webhookTypesempreQual evento chegou. Um dos quatro valores da seção 05.
transaction.idsempreIdentificador da compra na Cashbanx. Estável em todos os eventos — é a sua chave de conciliação.
transaction.statussempreSituação da compra.
transaction.typesempreComo a compra foi atribuída ao usuário.
transaction.cashbackStatussempreSituação do cashback.
transaction.createdDatesempreQuando a compra foi criada na Cashbanx.
transaction.transactionDatesempreQuando a compra ocorreu na loja.
transaction.statusUpdateDatepode vir vazioData da última mudança de situação. null enquanto a compra não mudou de estado.
transaction.updatedDatepode vir vazioQuando a compra foi atualizada na Cashbanx. null se nunca foi.
transaction.paidDatepode vir vazioQuando o cashback foi pago. Só tem valor no PAID_CASHBACK.
transaction.clickOriginpode vir vazioDispositivo de origem do clique. String vazia quando a rede não informa.
transaction.voucherCodepode vir vazioCódigo do cupom usado. String vazia na maioria das compras.
transaction.amendedpode vir vaziotrue se a rede afiliada alterou a compra depois de informá-la.
transaction.amendReasonpode vir vazioMotivo da alteração. String vazia quando amended é false.
transaction.thirdPartyIdpode vir vazioIdentificador da compra na rede afiliada.
transaction.purchaseOrderNumberpode vir vazioNúmero do pedido na loja.
transaction.paymentOrderNumberpode vir vazioNúmero da ordem de pagamento da rede afiliada. Só costuma vir depois do pagamento.
transaction.amountpode vir vazioValor total da compra. Pode ser null — a coluna aceita nulo e algumas redes não informam o valor.
transaction.oldAmountpode vir vazioValor anterior, quando a compra foi alterada. null se nunca houve alteração.
transaction.currencypode vir vazioMoeda da compra.
transaction.sourceAmountpode vir vazioValor na moeda de origem, em compra com conversão.
transaction.sourceCurrencypode vir vazioMoeda de origem, em compra com conversão.
transaction.quotationValuepode vir vazioCotação aplicada na conversão.
transaction.oldQuotationValuepode vir vazioCotação anterior, quando houve reajuste.
transaction.commissionpode vir vazioComissão da rede afiliada sobre a compra.
transaction.oldCommissionpode vir vazioComissão anterior, quando alterada.
transaction.commissionPercentagesemprePercentual da comissão, em fração (0.05 = 5%).
transaction.commissionReceiptDatepode vir vazioQuando a comissão foi recebida da rede afiliada.
transaction.cashbackValuesempreValor do cashback do usuário. Vai a zero numa compra cancelada.
transaction.oldCashbackValuepode vir vazioCashback anterior, quando alterado. É onde fica o valor original de uma compra cancelada.
transaction.cashbackPercentagesemprePercentual do cashback, em fração.
transaction.cashbackPointspode faltarO mesmo cashback convertido em pontos. Só existe para parceiros cujo programa é em pontos; nos demais a chave não aparece.
transaction.taxValuesempreImpostos retidos sobre a comissão.
transaction.partnerValuesempreParcela da comissão devida ao parceiro.
transaction.companyValuesempreParcela da comissão retida pela Cashbanx.
transaction.paidPartnerValuesempretrue se a parcela do parceiro já foi repassada.
transaction.paymentDatePartnerValuepode vir vazioData do repasse ao parceiro.
transaction.productBasketpode vir vazioItens da compra. null na maioria das redes, que não os enviam.
transaction.photopode vir vazioURL do comprovante. String vazia quando não há.
storesempreObjeto da loja. Vem como {} numa compra sem clique associado.
store.idpode faltarIdentificador da loja no catálogo do seu programa — o mesmo id que as rotas de loja da API devolvem, não um id global.
store.namepode faltarNome da loja.
store.logopode faltarURL do logo retangular.
store.circleLogopode faltarURL do logo circular.
usersempreObjeto do usuário. Vem como {} numa compra sem clique associado.
user.userIdentifierpode faltarO identificador do usuário no seu sistema, como você o enviou no clique. É por ele que você reconhece de quem é a compra. Pode vir string vazia numa compra não identificada.
user.idpode faltarIdentificador do usuário na Cashbanx. Ausente se o usuário não estiver cadastrado do nosso lado.
user.namepode faltarNome do usuário na Cashbanx. Ausente pelo mesmo motivo.
goOutsempreObjeto do clique. Vem como {} numa compra sem clique associado.
goOut.idpode faltarIdentificador do clique que originou a compra.
goOut.datepode faltarData e hora do clique. Formato AAAA-MM-DD HH:MM:SS, não ISO.
goOut.userAgentpode faltarUser agent do navegador no momento do clique.
goOut.additionalPropspode faltarTexto livre que você enviou no clique e devolvemos aqui. Útil para campanha, origem ou qualquer correlação sua.
withdraw.idpode faltarIdentificador do resgate. A chave withdraw só existe em CONFIRMED_PURCHASE e PAID_CASHBACK.
withdraw.statuspode faltarSituação do resgate.
Campos ausentes não vêm como null

Quando um valor não se aplica — cashbackPoints num programa em cashback, withdraw numa compra sem resgate, user.id num usuário que não temos cadastrado — a chave desaparece do JSON. Trate ausência e null como equivalentes, e não dependa da presença de nenhuma chave opcional.

Pelo mesmo motivo, seu parser deve ignorar campos que não conhece: campos novos podem aparecer sem aviso, e isso não é considerado quebra de contrato.

Domínio dos enums

Todos os enums trafegam pelo nome, em texto — nunca pelo número.

CampoValores possíveis
transaction.statusPending, Approved, Declined, Received
transaction.typeUnidentified, Identified, NoAssignment
transaction.cashbackStatusPending, Ahead, Reversed, Finished, Canceled, Analyzing
withdraw.statusPending, Confirmed, Disapproved, Waiting

Datas seguem ISO 8601 em UTC (2026-08-14T07:12:25.000Z). Uma exceção herdada: goOut.date vem no formato AAAA-MM-DD HH:MM:SS.

07Valores esperados por evento

Os valores não são livres — é justamente a situação da compra que decide qual webhook sai. Use esta matriz para validar o que recebe:

Evento status cashbackStatus withdraw.status
RECOGNIZED_PURCHASE Pending Pending, Analyzing, Ahead ausente
CONFIRMED_PURCHASE Approved Pending, Analyzing, Ahead Pending ou Waiting
CANCELED_PURCHASE Declined Canceled ausente
PAID_CASHBACK Approved ou Received Finished Confirmed

Em CONFIRMED_PURCHASE, o objeto withdraw aparece quando já existe um resgate para a compra — o que depende da configuração do seu programa. Havendo resgate criado e movimentado antes da confirmação, withdraw.status reflete o estado real do momento e pode trazer outro valor do domínio.

08Sua resposta

O que decide o destino da notificação é o código HTTP que você devolve. O corpo da sua resposta não é interpretado.

Você responde Registramos O que acontece
200–299 SENT Entregue. Não notificamos este evento de novo para esta compra.
422 CANCELED Recebido e recusado por decisão sua. Não reenviamos, e não notificamos de novo. Use quando não quiser este evento para esta compra.
outros FAILED Qualquer outro código, timeout ou erro de rede. Entra na fila de reenvio.
Erro de negócio não é 200

Responder 200 encerra a notificação em definitivo. Se o processamento falhou do seu lado e você quer outra tentativa, responda um código de erro — 500, por exemplo. E reserve o 422 para a recusa deliberada, porque ele também é definitivo.

09Reenvio

Uma notificação que falhou é reenviada até 3 vezes, com intervalos crescentes:

TentativaIntervalo aproximadoAcumulado
1º reenvio~5 minutos~5 min após a falha
2º reenvio~15 minutos~20 min
3º reenvio~45 minutos~1 h 05 min

Os intervalos têm uma variação aleatória de até 20% para os dois lados, de modo que uma indisponibilidade que derrubou muitas notificações de uma vez não devolva todas elas no mesmo instante. Esgotadas as três tentativas, paramos.

Uma rotina de recuperação retoma reenvios que ficaram pendentes por interrupção do nosso lado. Por causa dela, uma notificação pode chegar horas depois da falha original — o que reforça o ponto da próxima seção.

10Idempotência e ordem

  • Deduplique por webhookType + transaction.id. Esse par identifica a notificação. Entregamos cada um deles uma única vez com sucesso por compra, mas uma resposta que se perdeu no caminho pode nos fazer reenviar algo que você já processou.
  • O reenvio remonta o corpo do zero. Ele reflete o estado da compra no momento da retentativa, não no do primeiro envio. Valores como cashbackStatus ou withdraw.status podem chegar diferentes do que chegariam antes — e a segunda versão é a correta.
  • Não garantimos ordem de chegada. Um CONFIRMED_PURCHASE reenviado pode chegar depois de um PAID_CASHBACK. Use transaction.status, cashbackStatus e as datas para decidir, nunca a ordem em que as requisições chegaram.

11Entrega com efeito

Para alguns programas — combinado caso a caso, e informado no seu contrato de integração — uma resposta de sucesso no CONFIRMED_PURCHASE significa que o parceiro já creditou o usuário. Nesse arranjo a Cashbanx marca o resgate como pago no mesmo instante, e o PAID_CASHBACK sai em seguida.

Se este é o seu caso, responda 2xx ao CONFIRMED_PURCHASE somente depois de o crédito estar efetivado do seu lado. Um 200 otimista encerra o pagamento na Cashbanx sem que o usuário tenha recebido nada.

12Suporte

Dúvidas de integração, mudança de URL, rotação de chave ou reenvio manual de uma notificação: fale com o seu contato comercial na Cashbanx ou escreva para suporte@cashbanx.com, informando o transaction.id e o webhookType envolvidos.