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.
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.
- 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. - A rede afiliada nos informa a compra. Nós a associamos ao clique e disparamos RECOGNIZED_PURCHASE.
- Quando a rede confirma a compra, disparamos CONFIRMED_PURCHASE; se ela cancela, disparamos CANCELED_PURCHASE.
- Quando o resgate do cashback é pago, disparamos PAID_CASHBACK.
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ê
| Item | Descrição |
|---|---|
| RECOGNIZED_PURCHASE | URL do endpoint que recebe a compra identificada. |
| CONFIRMED_PURCHASE | URL do endpoint que recebe a confirmação. |
| CANCELED_PURCHASE | URL do endpoint que recebe o cancelamento. |
| PAID_CASHBACK | URL do endpoint que recebe o pagamento do resgate. |
| Chave de API | Um 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 exemplogrant_type,client_id,client_secret) no corpo doPOSTde 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
| Característica | Valor |
|---|---|
| Método | POST |
| Content-Type | application/json |
| Autenticação | x-api-key |
| Timeout | 30 segundos |
| Redirecionamentos | seguidos automaticamente |
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
| Evento | Quando disparamos | Observaçã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"
}
}
}A rede confirmou. Repare em statusUpdateDate, updatedDate e no objeto withdraw, que não existiam no evento anterior.
{
"webhookType": "CONFIRMED_PURCHASE",
"transaction": {
"id": 23026,
"clickOrigin": "Android Mobile",
"voucherCode": "",
"status": "Approved",
"statusUpdateDate": "2026-09-13T04:00:11.000Z",
"type": "Identified",
"cashbackStatus": "Pending",
"amended": false,
"amendReason": "",
"createdDate": "2026-08-14T07:12:25.000Z",
"updatedDate": "2026-09-13T04:00:11.000Z",
"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": "2026-09-13T04:00:11.000Z",
"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"
},
"withdraw": {
"id": 4821,
"status": "Pending"
}
}
}A rede cancelou e alterou os valores: os campos old… guardam o que valia antes, e os atuais vão a zero. Não há withdraw.
{
"webhookType": "CANCELED_PURCHASE",
"transaction": {
"id": 23026,
"clickOrigin": "Android Mobile",
"voucherCode": "",
"status": "Declined",
"statusUpdateDate": "2026-09-02T11:20:03.000Z",
"type": "Identified",
"cashbackStatus": "Canceled",
"amended": true,
"amendReason": "Pedido cancelado pela loja",
"createdDate": "2026-08-14T07:12:25.000Z",
"updatedDate": "2026-09-02T11:20:03.000Z",
"transactionDate": "2026-08-13T23:59:00.000Z",
"paidDate": null,
"thirdPartyId": "1527912405",
"purchaseOrderNumber": "16181113",
"paymentOrderNumber": null,
"amount": 0,
"oldAmount": 350,
"currency": "BRL",
"sourceAmount": null,
"sourceCurrency": "",
"quotationValue": null,
"oldQuotationValue": null,
"commission": 0,
"oldCommission": 17.5,
"commissionPercentage": 0.05,
"commissionReceiptDate": null,
"cashbackValue": 0,
"oldCashbackValue": 10.5,
"cashbackPercentage": 0.03,
"cashbackPoints": 0,
"taxValue": 0,
"partnerValue": 0,
"companyValue": 0,
"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"
}
}
}O resgate foi pago. paidDate preenchido, cashbackStatus em Finished e withdraw.status em Confirmed.
{
"webhookType": "PAID_CASHBACK",
"transaction": {
"id": 23026,
"clickOrigin": "Android Mobile",
"voucherCode": "",
"status": "Approved",
"statusUpdateDate": "2026-09-13T04:00:11.000Z",
"type": "Identified",
"cashbackStatus": "Finished",
"amended": false,
"amendReason": "",
"createdDate": "2026-08-14T07:12:25.000Z",
"updatedDate": "2026-09-15T23:59:00.000Z",
"transactionDate": "2026-08-13T23:59:00.000Z",
"paidDate": "2026-09-15T23:59:00.000Z",
"thirdPartyId": "1527912405",
"purchaseOrderNumber": "16181113",
"paymentOrderNumber": "PO-2026-09-4471",
"amount": 350,
"oldAmount": null,
"currency": "BRL",
"sourceAmount": null,
"sourceCurrency": "",
"quotationValue": null,
"oldQuotationValue": null,
"commission": 17.5,
"oldCommission": null,
"commissionPercentage": 0.05,
"commissionReceiptDate": "2026-09-13T04:00:11.000Z",
"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"
},
"withdraw": {
"id": 4821,
"status": "Confirmed"
}
}
}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.
| Campo | Presença | Descrição |
|---|---|---|
| webhookType | sempre | Qual evento chegou. Um dos quatro valores da seção 05. |
| transaction.id | sempre | Identificador da compra na Cashbanx. Estável em todos os eventos — é a sua chave de conciliação. |
| transaction.status | sempre | Situação da compra. |
| transaction.type | sempre | Como a compra foi atribuída ao usuário. |
| transaction.cashbackStatus | sempre | Situação do cashback. |
| transaction.createdDate | sempre | Quando a compra foi criada na Cashbanx. |
| transaction.transactionDate | sempre | Quando a compra ocorreu na loja. |
| transaction.statusUpdateDate | pode vir vazio | Data da última mudança de situação. null enquanto a compra não mudou de estado. |
| transaction.updatedDate | pode vir vazio | Quando a compra foi atualizada na Cashbanx. null se nunca foi. |
| transaction.paidDate | pode vir vazio | Quando o cashback foi pago. Só tem valor no PAID_CASHBACK. |
| transaction.clickOrigin | pode vir vazio | Dispositivo de origem do clique. String vazia quando a rede não informa. |
| transaction.voucherCode | pode vir vazio | Código do cupom usado. String vazia na maioria das compras. |
| transaction.amended | pode vir vazio | true se a rede afiliada alterou a compra depois de informá-la. |
| transaction.amendReason | pode vir vazio | Motivo da alteração. String vazia quando amended é false. |
| transaction.thirdPartyId | pode vir vazio | Identificador da compra na rede afiliada. |
| transaction.purchaseOrderNumber | pode vir vazio | Número do pedido na loja. |
| transaction.paymentOrderNumber | pode vir vazio | Número da ordem de pagamento da rede afiliada. Só costuma vir depois do pagamento. |
| transaction.amount | pode vir vazio | Valor total da compra. Pode ser null — a coluna aceita nulo e algumas redes não informam o valor. |
| transaction.oldAmount | pode vir vazio | Valor anterior, quando a compra foi alterada. null se nunca houve alteração. |
| transaction.currency | pode vir vazio | Moeda da compra. |
| transaction.sourceAmount | pode vir vazio | Valor na moeda de origem, em compra com conversão. |
| transaction.sourceCurrency | pode vir vazio | Moeda de origem, em compra com conversão. |
| transaction.quotationValue | pode vir vazio | Cotação aplicada na conversão. |
| transaction.oldQuotationValue | pode vir vazio | Cotação anterior, quando houve reajuste. |
| transaction.commission | pode vir vazio | Comissão da rede afiliada sobre a compra. |
| transaction.oldCommission | pode vir vazio | Comissão anterior, quando alterada. |
| transaction.commissionPercentage | sempre | Percentual da comissão, em fração (0.05 = 5%). |
| transaction.commissionReceiptDate | pode vir vazio | Quando a comissão foi recebida da rede afiliada. |
| transaction.cashbackValue | sempre | Valor do cashback do usuário. Vai a zero numa compra cancelada. |
| transaction.oldCashbackValue | pode vir vazio | Cashback anterior, quando alterado. É onde fica o valor original de uma compra cancelada. |
| transaction.cashbackPercentage | sempre | Percentual do cashback, em fração. |
| transaction.cashbackPoints | pode faltar | O mesmo cashback convertido em pontos. Só existe para parceiros cujo programa é em pontos; nos demais a chave não aparece. |
| transaction.taxValue | sempre | Impostos retidos sobre a comissão. |
| transaction.partnerValue | sempre | Parcela da comissão devida ao parceiro. |
| transaction.companyValue | sempre | Parcela da comissão retida pela Cashbanx. |
| transaction.paidPartnerValue | sempre | true se a parcela do parceiro já foi repassada. |
| transaction.paymentDatePartnerValue | pode vir vazio | Data do repasse ao parceiro. |
| transaction.productBasket | pode vir vazio | Itens da compra. null na maioria das redes, que não os enviam. |
| transaction.photo | pode vir vazio | URL do comprovante. String vazia quando não há. |
| store | sempre | Objeto da loja. Vem como {} numa compra sem clique associado. |
| store.id | pode faltar | Identificador 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.name | pode faltar | Nome da loja. |
| store.logo | pode faltar | URL do logo retangular. |
| store.circleLogo | pode faltar | URL do logo circular. |
| user | sempre | Objeto do usuário. Vem como {} numa compra sem clique associado. |
| user.userIdentifier | pode faltar | O 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.id | pode faltar | Identificador do usuário na Cashbanx. Ausente se o usuário não estiver cadastrado do nosso lado. |
| user.name | pode faltar | Nome do usuário na Cashbanx. Ausente pelo mesmo motivo. |
| goOut | sempre | Objeto do clique. Vem como {} numa compra sem clique associado. |
| goOut.id | pode faltar | Identificador do clique que originou a compra. |
| goOut.date | pode faltar | Data e hora do clique. Formato AAAA-MM-DD HH:MM:SS, não ISO. |
| goOut.userAgent | pode faltar | User agent do navegador no momento do clique. |
| goOut.additionalProps | pode faltar | Texto livre que você enviou no clique e devolvemos aqui. Útil para campanha, origem ou qualquer correlação sua. |
| withdraw.id | pode faltar | Identificador do resgate. A chave withdraw só existe em CONFIRMED_PURCHASE e PAID_CASHBACK. |
| withdraw.status | pode faltar | Situação do resgate. |
Nenhum campo com esse nome.
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.
| Campo | Valores possíveis |
|---|---|
| transaction.status | Pending, Approved, Declined, Received |
| transaction.type | Unidentified, Identified, NoAssignment |
| transaction.cashbackStatus | Pending, Ahead, Reversed, Finished, Canceled, Analyzing |
| withdraw.status | Pending, 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. |
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:
| Tentativa | Intervalo aproximado | Acumulado |
|---|---|---|
| 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
cashbackStatusouwithdraw.statuspodem chegar diferentes do que chegariam antes — e a segunda versão é a correta. - Não garantimos ordem de chegada. Um
CONFIRMED_PURCHASEreenviado pode chegar depois de umPAID_CASHBACK. Usetransaction.status,cashbackStatuse 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.