# Documentação da Rapid > Documentação de integração da Rapid, com prevenção de disputas, alertas de chargeback, envio de transações, webhooks e captura de evidência. Página: https://doc.rapidchargeback.com/ ## Os produtos ### Prevenção Quando o banco emissor abre a consulta, a Rapid responde com os dados do pedido para a disputa não nascer. [Visão geral](https://doc.rapidchargeback.com/produtos/prevencao/visao-geral/) · [Integração](https://doc.rapidchargeback.com/produtos/prevencao/integracao/) ### Alerta O emissor sinaliza a disputa antes de virar chargeback e você responde a tempo de estornar ou suspender o acesso. [Visão geral](https://doc.rapidchargeback.com/produtos/alerta/visao-geral/) · [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/) ### Disputa Com o chargeback já aberto, a Rapid monta e submete a contestação dentro do prazo da bandeira. [Visão geral](https://doc.rapidchargeback.com/produtos/disputa/visao-geral/) ## Comece por aqui - [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/): As credenciais, onde pegar e como enviar em cada canal. - [Enviar transações](https://doc.rapidchargeback.com/canais/transactions/visao-geral/): O canal de entrada que alimenta a Prevenção e a Disputa. - [Receber webhooks](https://doc.rapidchargeback.com/canais/webhook/visao-geral/): Como a Rapid entrega alertas e eventos no seu sistema. - [Responder um alerta](https://doc.rapidchargeback.com/callback/visao-geral/): O callback de status, com os valores aceitos e o prazo de cada provedor. - [Capturar evidência](https://doc.rapidchargeback.com/canais/capture/visao-geral/): O snippet de checkout e os dois canais de evento. - [Exemplos canônicos](https://doc.rapidchargeback.com/referencia/exemplos-canonicos/): Os IDs e valores fixos usados em todos os exemplos daqui. --- # Primeira integração > Do zero ao primeiro alerta respondido: credenciais, webhook com assinatura validada, primeira transação e o callback de status, com os comandos prontos. Página: https://doc.rapidchargeback.com/primeira-integracao/ O caminho mais curto até a integração funcionando. Ao fim deste guia a sua aplicação recebe alertas com a assinatura validada, envia transações e responde alertas pela API. Cada passo aponta para a página com o detalhe completo. ## 1. Pegue as credenciais No painel da Rapid, em **Configurações › API**, gere o `client_id` e o `client_secret`. O segredo aparece **uma única vez**: copie na hora. Se perder, gere de novo no mesmo lugar (as credenciais anteriores deixam de valer no mesmo instante). Guarde as duas em variáveis de ambiente, nunca no código: ```bash export RAPID_CLIENT_ID="seu_client_id" export RAPID_CLIENT_SECRET="seu_client_secret" ``` Detalhes em [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ## 2. Confirme que a credencial funciona Liste o alerta mais recente da sua empresa: ```bash curl -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts?per_page=1" ``` | Resposta | O que significa | |---|---| | `200` com `data` e `meta` | Credencial certa. `data` pode vir vazio se ainda não chegou nenhum alerta | | `401 UNAUTHORIZED` | `client_id` ou `client_secret` errado | | `403 COMPANY_BLOCKED` | A empresa está bloqueada na Rapid: fale com o suporte | ## 3. Cadastre o webhook Em **Configurações › Webhook**, cadastre a URL que vai receber os eventos. Ela precisa ser **HTTPS** e de **endereço público de internet**: o painel recusa `http://`, `localhost` e IP de rede local. Ao salvar, a Rapid gera a **chave de assinatura** e mostra uma única vez. Guarde em `RAPID_WEBHOOK_SECRET`. Para receber na sua máquina durante o desenvolvimento, exponha o servidor local com um túnel HTTPS (ver [Boas práticas](https://doc.rapidchargeback.com/canais/webhook/boas-praticas/#use-um-endereço-público-de-internet)). ## 4. Valide a assinatura Toda entrega traz `X-Webhook-Signature` e `X-Webhook-Timestamp`. O seu endpoint confere a assinatura **antes** de processar qualquer coisa. Copie o endpoint pronto da sua linguagem (Node.js, Python ou PHP) em [Autenticação do webhook](https://doc.rapidchargeback.com/canais/webhook/autenticacao/#exemplos). Os três seguem as mesmas regras: - a assinatura é calculada sobre o **corpo bruto**: não leia como JSON antes de validar - entrega com mais de 5 minutos é recusada (proteção contra reenvio) - qualquer entrega que não passe recebe `401` Responda `2xx` rápido e processe depois, numa fila: a Rapid espera até 30 segundos e, sem resposta, tenta de novo. Use o `alert_id` para não processar o mesmo alerta duas vezes. Ver [Boas práticas](https://doc.rapidchargeback.com/canais/webhook/boas-praticas/). ## 5. Envie a primeira transação Se você usa a **Prevenção** ou a **Disputa**, elas trabalham com as transações de venda que você envia. Cada transação diz de qual merchant (loja, marca ou vendedor) ela é, pelo `merchant_id`. Veja os seus: ```bash curl -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ "https://api.rapidchargeback.com/api/v1/merchants" ``` O `id` de cada item da resposta é o `merchant_id` (ver [Listar merchants](https://doc.rapidchargeback.com/canais/merchants/listar-merchants/)). Com ele, a transação mínima: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions \ -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "transaction_id": "cob_8f2a91c4", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_bin": "424242", "card_last4": "4242", "items": [ { "product_description": "Assinatura Premium - Mensal", "unit_price": 150.00 } ] }' ``` - O `transaction_id` é o identificador da cobrança no seu gateway de pagamento. É por ele que um chargeback futuro encontra a transação: sem ele a defesa sai sem histórico. - A resposta é `201` com o `id` da transação na Rapid: guarde. Se perder, dá para achar a transação [pelo `external_id`](https://doc.rapidchargeback.com/canais/transactions/consultar-transacao/#pelo-id-do-seu-sistema). - Se vier a chave `warnings`, a transação foi criada, mas faltam campos que melhoram a proteção. Todos os campos em [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/). Para volume, use o [envio em lote](https://doc.rapidchargeback.com/canais/transactions/envio-em-lote/). ## 6. Responda o primeiro alerta Quando chegar um alerta de **Mastercard**, você tem **24 horas** para responder. Com o `alert_id` recebido no webhook: ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/00000000-0000-0000-0000-000000000099/status \ -u "$RAPID_CLIENT_ID:$RAPID_CLIENT_SECRET" \ -H "Content-Type: application/json" \ -d '{ "status": "account_suspended" }' ``` | Status | Quando usar | |---|---| | `notfound` | A transação não existe no seu sistema | | `account_suspended` | A transação existe e já está resolvida (estorno feito, acesso cortado) | | `other` | A transação existe, mas ainda não está resolvida | Alerta de **Visa** chega com o estorno já feito e não tem prazo. Ver [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/). ## Antes de ir para produção - [ ] Credenciais e chave de assinatura em variáveis de ambiente ou cofre de segredos - [ ] Webhook valida a assinatura e a janela de 5 minutos, e recusa com `401` - [ ] Webhook responde `2xx` em menos de 30 segundos e processa em fila - [ ] O mesmo `alert_id` processado duas vezes não gera efeito duplicado - [ ] Alerta de Mastercard respondido em até 24 horas, de forma automática ou por alguém de plantão - [ ] Transações com `transaction_id` preenchido, se você usa a Disputa - [ ] `429` tratado esperando o `Retry-After` (ver [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/#rate-limit)) ## Próximos passos - [Payload do webhook](https://doc.rapidchargeback.com/canais/webhook/payload/): todos os campos de cada evento. - [Ferramentas para devs](https://doc.rapidchargeback.com/referencia/ferramentas-para-devs/): a documentação no seu assistente de IA e a coleção do Postman. --- # Prevenção > Como a Prevenção encerra a disputa antes do chargeback, respondendo ao banco emissor com os dados do pedido a partir das transações que você já envia. Página: https://doc.rapidchargeback.com/produtos/prevencao/visao-geral/ **Prevenção** é a solução da Rapid para deflexão de disputas em tempo real. Quando um banco emissor abre uma consulta sobre uma compra, a Rapid responde na hora com os dados do pedido original, e a disputa não chega a virar chargeback. Você não chama nenhum endpoint da Prevenção: ela funciona a partir das transações que você já envia. O trabalho de integração é **enviar as transações com os campos certos**, descritos em [Integração](https://doc.rapidchargeback.com/produtos/prevencao/integracao/). ## Como funciona 1. Você envia as transações de venda para a Rapid pela [API de Transações](https://doc.rapidchargeback.com/canais/transactions/visao-geral/) 2. Quando o banco emissor consulta uma transação em disputa, a Rapid localiza automaticamente a transação correspondente entre as que você enviou 3. A Rapid responde com os dados do pedido: merchant, itens comprados, endereço de entrega e dados do comprador 4. Com isso o banco pode encerrar a disputa antes que ela se torne um chargeback ## Tipos de proteção As duas acontecem sozinhas. Você não escolhe uma nem outra: a Rapid usa a que os dados da transação permitirem, e as duas podem valer para a mesma compra. ### Reconhecimento da compra Mostra ao portador do cartão, pelo banco dele, os detalhes do pedido: o que foi comprado, quando e de quem. Resolve a disputa que nasce porque a pessoa **não reconheceu** a cobrança. Funciona com os campos mínimos da transação. ### Proteção contra fraude Comprova que quem comprou é o próprio dono do cartão, com sinais da compra: IP, aparelho, conta do cliente no seu sistema e endereço de entrega. Pode encerrar automaticamente uma disputa de **fraude**. Exige dois sinais, descritos em [Integração](https://doc.rapidchargeback.com/produtos/prevencao/integracao/#para-a-proteção-contra-fraude). --- # Integração > O que enviar para ativar a Prevenção: dados do merchant, campos mínimos da transação e os que habilitam a proteção contra fraude. Página: https://doc.rapidchargeback.com/produtos/prevencao/integracao/ Para integrar a Prevenção, você precisa enviar suas transações de venda para a Rapid via **API de Transações**. Consulte a [documentação da API de Transações](https://doc.rapidchargeback.com/canais/transactions/visao-geral/) para detalhes completos dos endpoints. ## Dados do merchant Antes de enviar transações, certifique-se de que seu merchant está cadastrado com as informações completas. Os seguintes campos do merchant são **obrigatórios** para a Prevenção funcionar: | Campo | Descrição | |---|---| | `name` | Nome do merchant | | `merchant_url` | URL do site do merchant | | `contact_phone` | Telefone de contato | | `store_name` | Nome da loja | ## Campos mínimos da transação Além dos campos obrigatórios da API de Transações, a Prevenção precisa dos seguintes para funcionar: | Campo | Por quê | |---|---| | `items[]` com `product_description` | Descrição dos produtos comprados. Sem ela não há o que mostrar ao banco emissor | | `order_number` | Identificação do pedido na resposta ao banco emissor (recomendado) | ## Campos recomendados Quanto mais dados você enviar, maior a chance de deflectir disputas. A tabela abaixo mostra os campos recomendados e o impacto de cada um: ### Para o reconhecimento da compra | Campo | Impacto | |---|---| | `card_bin` | Aumenta a precisão do match com a transação em disputa | | `auth_code` | Melhora a identificação da transação | | `customer.first_name` e `customer.last_name` | Ajuda o portador a reconhecer a compra | | `customer.email` | Ajuda o portador a reconhecer a compra | ### Para a proteção contra fraude A proteção contra fraude atende disputas de **fraude**. Ela precisa de **dois sinais** de que quem comprou é o dono do cartão: um identificador da compra (a âncora) e mais um dado que confirme a pessoa. Para qualificar uma transação, envie uma das 3 combinações abaixo. A âncora (`ip_address`, `device_id` ou `device_fingerprint`) é **obrigatória**; ao lado dela, envie **ao menos um** campo da coluna de complementos. | Formato | Âncora obrigatória | Pelo menos um dos complementos | |---|---|---| | **Opção 1** | `ip_address` | `customer.account_id`, `addresses` (shipping), `device_id` ou `device_fingerprint` | | **Opção 2** | `device_id` | `customer.account_id`, `addresses` (shipping) ou `ip_address` | | **Opção 3** | `device_fingerprint` | `customer.account_id`, `addresses` (shipping) ou `ip_address` | #### Campos: formato e restrições | Campo | Requisitos | |---|---| | `ip_address` | IP público do comprador no momento da compra. Texto claro, não pode ser hash. Formatos IPv4 ou IPv6 | | `device_id` | Identificador único do dispositivo (ex: IMEI). Texto claro, mín. 15 caracteres, não pode ser hash | | `device_fingerprint` | Fingerprint derivada de atributos do dispositivo (SO, modelo, versão, etc.). Mín. 20 caracteres. Pode ser hash | | `customer.account_id` | Identificador de autenticação do comprador no seu sistema (email, username). Um único valor | | `addresses` (type: shipping) | Endereço de entrega completo: `street` (address1), `city`, `state` (region), `postal_code`, `country`. Não pode ser endereço de loja | > **Você não escolhe a opção.** Envie o máximo de campos que tiver: a Rapid usa automaticamente a combinação que a sua transação cobre. Por exemplo, se você envia `ip_address + device_id + account_id`, sua transação se qualifica tanto para a Opção 1 quanto para a Opção 2, a combinação com mais campos maximiza a chance de deflexão. #### Digital goods: não envie endereço de entrega Se sua empresa vende **bens digitais** (software, SaaS, streaming, ebooks, cursos online, serviços sem entrega física), **não envie `addresses` com type `shipping`**. As regras da bandeira proíbem quem vende bem digital de informar endereço de entrega, e o envio pode **suspender a proteção contra fraude** da sua conta. Para digital goods, foque nestes complementos: | Opção | Âncora | Complementos práticos | |---|---|---| | 1 | `ip_address` | `customer.account_id`, `device_id`, `device_fingerprint` | | 2 | `device_id` | `customer.account_id`, `ip_address` | | 3 | `device_fingerprint` | `customer.account_id`, `ip_address` | `customer.account_id` e `ip_address` tendem a ser os campos mais naturais de capturar em e-commerce digital. ## Exemplo de transação completa ```json { "merchant_id": "00000000-0000-0000-0000-000000000001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "192.168.1.100", "device_id": "041C226BBD5A80020040105118304404", "external_source": "shopify", "external_id": "TXN-2026-001", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00 } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com", "account_id": "joao@exemplo.com" }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ] } ``` Este exemplo inclui todos os campos recomendados para máxima cobertura de deflexão. --- # Alerta > Como o Alerta avisa a disputa antes de virar chargeback, como o alerta chega à sua empresa e o que responder em cada bandeira. Página: https://doc.rapidchargeback.com/produtos/alerta/visao-geral/ **Alerta** é a solução da Rapid para **notificação antecipada de disputas**. (Nome anterior: *Chargeback Alert*. O caminho da API continua `/chargeback-alert/...`.) Quando um portador de cartão abre uma disputa junto ao banco emissor, a rede (Mastercard ou Visa) sinaliza o evento para provedores antes que ele se torne um chargeback formal. A Rapid recebe esses sinais e te entrega o alerta em tempo hábil para você tomar uma ação. Em payloads e respostas da API, os provedores são identificados pelos slugs `ethoca_alerts` (Mastercard) e `verifi_rdr` (Visa). Dependendo da bandeira, a ação do cliente é diferente: - **Mastercard** (via Ethoca): você tem até 24 horas para confirmar se vai estornar, indicar que a transação já foi resolvida, ou que não encontrou a transação. A sua resposta volta para o Ethoca e pode evitar que a disputa evolua para chargeback. - **Visa** (via Verifi RDR): o estorno já foi feito automaticamente pela adquirente quando o alerta chegou. Não há prazo de resposta; o status é usado apenas para organização interna. ## Como funciona 1. O portador abre uma disputa no banco emissor 2. A bandeira sinaliza a disputa para o provedor (Ethoca para Mastercard, Verifi RDR para Visa) 3. O provedor entrega o alerta para a Rapid 4. A Rapid associa o alerta à sua empresa via `descriptor` (Ethoca) ou BIN+CAID (Verifi) 5. A Rapid entrega o alerta para sua aplicação via webhook 6. Sua aplicação processa o alerta e (no caso Ethoca) retorna um status via API de callback Para receber alertas, sua empresa precisa ter: - Um **webhook ativo** configurado no painel (ver [canal Webhook](https://doc.rapidchargeback.com/canais/webhook/visao-geral/)) - Ao menos um **descriptor cadastrado** (Ethoca) ou **BIN+CAID** (Verifi) associado à sua empresa ## Provedores ### Ethoca (Mastercard) Alertas são associados à sua empresa pelo `descriptor`, o nome que aparece na fatura do portador. Quando o descriptor do alerta casa com um dos seus cadastrados, o alerta é entregue. Você tem 24 horas para retornar um status via [callback](https://doc.rapidchargeback.com/callback/visao-geral/). Se não responder no prazo, o alerta expira automaticamente (status `expired`) e pode evoluir para chargeback. ### Verifi RDR (Visa) Alertas são associados pelo BIN + CAID. O estorno já foi aplicado automaticamente quando o alerta chegou. O cliente pode atualizar o status apenas para organizar seu próprio fluxo, mas não há prazo. ## Próximos passos - [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/): detalhes de prazo por bandeira. - [Canal Webhook](https://doc.rapidchargeback.com/canais/webhook/visao-geral/): como configurar a entrega. - [Callback de status](https://doc.rapidchargeback.com/callback/visao-geral/): como atualizar o status do alerta. --- # Regras e prazos > Os status de um alerta, o prazo de resposta de cada bandeira, a conversão de other para account_suspended e quando o alerta expira. Página: https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/ ## Status possíveis Todo alerta nasce com status `pending` e evolui conforme a resposta do cliente ou o passar do tempo. ### Status que você pode enviar via callback | Status | Quando usar | |---|---| | `notfound` | A transação não foi encontrada no seu sistema | | `account_suspended` | A transação foi encontrada e já está resolvida (ex: conta suspensa, reembolso feito) | | `other` | A transação foi encontrada, mas ainda não está resolvida | Ver [Atualizar status](https://doc.rapidchargeback.com/callback/atualizar-status/) para detalhes do endpoint. ### Status visíveis no payload do webhook Além dos três acima que você envia, o status do alerta no webhook pode aparecer como: | Status | Significado | |---|---| | `pending` | Status inicial de todo alerta recebido | | `expired` | Alerta Ethoca cujo prazo passou sem resposta | --- ## Prazos por provedor ### Ethoca (Mastercard) **Prazo para responder: 24 horas** a partir do recebimento. - Você deve enviar `notfound`, `account_suspended` ou `other` via [callback](https://doc.rapidchargeback.com/callback/atualizar-status/) dentro desse prazo - Se o prazo passar sem resposta, o alerta vira `expired` automaticamente. O Ethoca entende como inação e a disputa segue o caminho normal (geralmente vira chargeback). **Conversão `other → account_suspended`: até 6 dias** - Se você enviou `other` inicialmente porque ainda estava investigando, pode depois atualizar para `account_suspended` em até 6 dias do alerta original - Essa é a única transição permitida após uma resposta inicial **Status definitivos não podem ser alterados:** - `notfound` é definitivo - `account_suspended` é definitivo - `expired` é definitivo ### Verifi RDR (Visa) **Sem prazo obrigatório.** - O estorno já foi executado automaticamente pela adquirente antes mesmo do alerta chegar - O status que você envia serve apenas para organização interna no painel - Você pode enviar qualquer um dos três status (`notfound`, `account_suspended`, `other`) a qualquer momento --- ## Expiração A Rapid marca alertas Ethoca como `expired` automaticamente após 24h sem resposta. Alertas Verifi RDR **não expiram**: ficam disponíveis no painel indefinidamente. --- ## Reenvio Em caso de falha de entrega do webhook, a Rapid faz até **4 tentativas** (1 inicial + 3 retentativas) com intervalos de 5, 15 e 30 minutos (ver [Retries e logs](https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/)). Se todas as tentativas falharem, o alerta continua disponível no painel e pode ser reenviado manualmente pela equipe da Rapid. Alertas reenviados mantêm o mesmo `alert_id`, por isso sua aplicação precisa ser idempotente. --- # Disputa > Como a Disputa monta e submete a contestação do chargeback, o que a Rapid precisa de você e o corte de acesso em disputa de fraude. Página: https://doc.rapidchargeback.com/produtos/disputa/visao-geral/ **Disputa** é a solução da Rapid para **defesa automatizada de chargeback**. Enquanto a [Prevenção](https://doc.rapidchargeback.com/produtos/prevencao/visao-geral/) responde ao banco para a disputa não nascer e o [Alerta](https://doc.rapidchargeback.com/produtos/alerta/visao-geral/) avisa antes de virar chargeback, a Disputa atua depois: quando o chargeback já entrou, a Rapid monta e submete a contestação (*second presentment*) no prazo da bandeira. A defesa é construída com o que você já manda: a transação, as provas registradas e os sinais capturados no checkout. Quanto mais material, maior a chance de ganhar. ## Como funciona 1. **Você** envia a transação, com o id da cobrança no gateway, e as provas da venda 2. **Gateway** registra o chargeback quando o portador abre a disputa 3. **Gateway → Rapid** avisa a Rapid na hora, porque a sua conta do gateway está conectada à Rapid (ver abaixo) 4. **Rapid** cruza a disputa com a sua transação, pelo id da cobrança 5. **Rapid → Você** avisa pelo webhook, se a razão for fraude, para você cortar o acesso do comprador 6. **Rapid** avalia o caso, monta o dossiê com as provas e submete a contestação 7. **Gateway → Rapid** devolve o desfecho, que aparece no painel O seu trabalho está nos passos 1 e 5, em destaque: o material que você envia antes de tudo acontecer e o corte de acesso. O resto é da Rapid. ## O que a Rapid precisa de você | O que | Por quê | Onde | |---|---|---| | A sua conta do gateway de pagamento conectada à Rapid | é por ela que a disputa chega; sem a conexão, nenhuma disputa aparece | Painel, em **Configurações › Integrações**: é só autorizar, sem código | | A transação, com o id da cobrança no gateway | sem ela a disputa chega sem histórico e sem prova | [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/) | | Provas do que sustenta a venda | é o conteúdo da defesa | [Evidência](https://doc.rapidchargeback.com/canais/evidence/visao-geral/) e [Captura](https://doc.rapidchargeback.com/canais/capture/visao-geral/) | | Um endpoint para o corte de acesso | é exigência de regra de bandeira | [Webhook](https://doc.rapidchargeback.com/canais/webhook/visao-geral/) | O ponto que mais derruba integração é o da transação. A disputa encontra a transação pelo identificador da cobrança no gateway, então o campo `transaction_id` (ou `external_source` mais `external_id`) tem que carregar esse valor. Transação não encontrada significa defesa sem os dados de autenticação, sem evidência anexada e sem histórico do pedido. ## Corte de acesso em disputa de fraude Quando a disputa é de fraude, as bandeiras exigem que o lojista tente revogar o produto ou serviço entregue e tenha processo para evitar reincidência. Para isso a Rapid dispara o evento `dispute.fraud.revoke_access` no seu webhook, com as ações exigidas e o prazo. É o único ponto da Disputa em que a Rapid chama o seu sistema. Trate de forma automática se possível: quanto mais rápido o corte, menor o prejuízo. O formato está em [Payload do webhook](https://doc.rapidchargeback.com/canais/webhook/payload/#evento-disputefraudrevoke_access). Se a entrega falhar, a pendência aparece no painel para alguém do seu time confirmar à mão. ## Situações da disputa | Situação | O que significa | |---|---| | `received` | chegou e está em avaliação | | `submitted` | contestação enviada ao gateway, aguardando o desfecho | | `won` | disputa ganha | | `lost` | disputa perdida | | `accepted` | o caso não foi contestado | | `needs_review` | a Rapid não conseguiu identificar o vendedor, e a equipe está revisando | Nem todo chargeback é contestado. A Rapid avalia caso a caso: quando não há direito de contestação pela regra da bandeira, ou quando o material disponível não sustenta a defesa, o caso é marcado como não contestado em vez de gastar prazo com uma submissão perdida. ## Requisitos de configuração - produto **Disputa** ativo na sua empresa - a conta do seu gateway de pagamento conectada no painel, em Configurações - um webhook ativo, se você quer receber o corte de acesso A conexão do gateway é feita no painel, sem código: você cria uma chave restrita na plataforma de pagamento, cola no painel e registra o endereço que o painel mostrar. O suporte da Rapid acompanha esse passo. ## Próximos passos - [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/): o que mandar para a disputa achar a transação - [Visão geral da evidência](https://doc.rapidchargeback.com/canais/evidence/visao-geral/): como registrar prova - [Visão geral da captura](https://doc.rapidchargeback.com/canais/capture/visao-geral/): como capturar sinais no checkout - [Payload do webhook](https://doc.rapidchargeback.com/canais/webhook/payload/): o formato do corte de acesso --- # Listar merchants > Lista os merchants da sua empresa, paginado, com o merchant_id que criar transação e enviar evento de captura pedem. Página: https://doc.rapidchargeback.com/canais/merchants/listar-merchants/ Lista os merchants (lojas, marcas ou vendedores) da sua empresa. É daqui que sai o `merchant_id` que [criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/) e [enviar evento pelo servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) pedem. Só leitura: cadastrar e editar merchant é pelo painel. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/merchants ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Query params Todos opcionais. | Param | Tipo | Default | Descrição | |---|---|---|---| | `page` | int (≥ 1) | `1` | Página | | `per_page` | int (1–100) | `20` | Itens por página | | `merchant_ref` | string (até 100) | - | O ID do vendedor no **seu** sistema, o mesmo `merchant_ref` aceito em [criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/). Devolve 0 ou 1 item | | `status` | enum | - | `active` ou `inactive` | A lista vem sempre paginada, em ordem de cadastro (o mais antigo primeiro). Para percorrer todos, avance `page` até `page` chegar a `total_pages`: merchant cadastrado no meio do caminho entra no fim, sem fazer você pular ou repetir item. --- ## Exemplos ### Todos os merchants ```bash curl -G "https://api.rapidchargeback.com/api/v1/merchants" \ --data-urlencode "per_page=100" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Pelo ID do vendedor no seu sistema ```bash curl -G "https://api.rapidchargeback.com/api/v1/merchants" \ --data-urlencode "merchant_ref=seller-77" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Resposta ### Sucesso ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000001", "name": "Loja Exemplo", "merchant_ref": null, "status": "active", "created_at": "2026-03-10T12:00:00.000Z" } ], "meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 } } ``` | Campo | Descrição | |---|---| | `id` | O `merchant_id` que as outras APIs pedem | | `name` | Nome do merchant no painel | | `merchant_ref` | O ID do vendedor no seu sistema, quando o merchant foi criado por `merchant_ref`. `null` nos cadastrados pelo painel | | `status` | `active` ou `inactive`. Merchant inativo não recebe alertas | | `created_at` | Quando foi cadastrado | São só esses campos: dados de contato, endereço e termos do merchant ficam no painel. ### Sem resultados ```json { "data": [], "meta": { "page": 1, "per_page": 20, "total": 0, "total_pages": 0 } } ``` ### Parâmetro inválido (ex: `per_page=500`) ```json { "error": { "code": "VALIDATION_ERROR", "message": "Number must be less than or equal to 100" } } ``` --- ## Notas - **Só os merchants da sua empresa.** A empresa vem da credencial; não há parâmetro para escolher outra. - **Empresa bloqueada** recebe `403 COMPANY_BLOCKED`, como nas outras APIs. - **Auth, rate limit, códigos de erro:** ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/) e [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/). --- # Visão geral > Envie, consulte, atualize e remova as transações de venda que alimentam a Prevenção e a Disputa, com Basic Auth e JSON. Página: https://doc.rapidchargeback.com/canais/transactions/visao-geral/ A API de Transações permite que você envie, consulte, atualize e remova transações de venda da sua empresa na plataforma Rapid. Essas transações são utilizadas pelas soluções contratadas para proteger seu negócio contra disputas e chargebacks. ## Como funciona 1. Sua aplicação envia as transações de venda via HTTPS para a API da Rapid 2. A Rapid armazena os dados da transação (itens, cliente, endereços, pagamentos, reembolsos) 3. As soluções ativas utilizam esses dados automaticamente quando necessário ## Endpoints disponíveis | Método | Endpoint | Descrição | |---|---|---| | POST | `/api/v1/transactions` | Criar uma transação | | POST | `/api/v1/transactions/batch` | Criar múltiplas transações (até 1000) | | GET | `/api/v1/transactions/:id` | Consultar uma transação | | GET | `/api/v1/transactions?external_id=` | Achar uma transação pelo ID do seu sistema | | PATCH | `/api/v1/transactions/:id` | Atualizar uma transação | | DELETE | `/api/v1/transactions/:id` | Deletar uma transação | ## Base URL ``` https://api.rapidchargeback.com/api/v1 ``` ## Autenticação Todas as requisições exigem autenticação via **Basic Auth**: ``` Authorization: Basic base64(client_id:client_secret) ``` | Credencial | Descrição | |---|---| | `client_id` | ID da sua empresa (fornecido pela Rapid) | | `client_secret` | Chave secreta da sua empresa (fornecida pela Rapid) | Exemplo de header: ``` Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ= ``` ## Limites | Limite | Valor | |---|---| | Requisições por minuto | 100 por IP | | Transações por requisição (batch) | 1000 | ## Proteção de imutabilidade Transações que já foram utilizadas por alguma solução (ex: consultadas pela **Prevenção**) não podem ser alteradas ou deletadas. Nesse caso, a API retorna `409 Conflict`. Transações que ainda não foram utilizadas podem ser livremente atualizadas ou deletadas. --- # Criar transação > Cria uma única transação de venda. Para criar várias transações de uma vez, consulte a página Envio em lote. Página: https://doc.rapidchargeback.com/canais/transactions/criar-transacao/ Cria uma única transação de venda. Para criar várias transações de uma vez, consulte a página [Envio em lote](https://doc.rapidchargeback.com/canais/transactions/envio-em-lote/). ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/transactions ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Campos obrigatórios | Campo | Tipo | Descrição | |---|---|---| | `merchant_id` **ou** `merchant_ref` | string | Informe **exatamente um**: `merchant_id` (UUID do merchant na Rapid, deve pertencer à sua empresa) **ou** `merchant_ref` (ID do vendedor no **seu** sistema, até 100 caracteres, para canais/plataformas com vários vendedores). Se `merchant_ref` for desconhecido, o merchant é **criado** automaticamente com `merchant_name` (opcional, até 255 caracteres; ignorado quando o merchant já existe). Enviar os dois → `422 VALIDATION_ERROR`. Os seus merchants e os `merchant_id` estão em [Listar merchants](https://doc.rapidchargeback.com/canais/merchants/listar-merchants/). | | `external_id` | string | ID da transação no sistema de origem | | `amount` | number | Valor da transação (deve ser positivo) | | `currency` | string | Código ISO 4217 com 3 letras maiúsculas (ex: `USD`, `BRL`) | | `transaction_date` | string | Data da transação em formato ISO 8601 (ex: `2026-04-01T15:30:00Z`) | | `card_last4` | string | Últimos 4 dígitos do cartão (exatamente 4 dígitos numéricos) | | `items` | array | Ao menos 1 item (veja campos do item abaixo) | ## Campos do item ### Obrigatórios | Campo | Tipo | Descrição | |---|---|---| | `product_description` | string | Descrição do produto (até 1000 caracteres; acima disso a requisição falha) | | `unit_price` | number | Preço unitário | ### Opcionais | Campo | Tipo | Descrição | |---|---|---| | `product_name` | string | Nome do produto | | `quantity` | number | Quantidade | | `unit_of_measure` | string | Unidade de medida | | `category` | string | Categoria do produto | --- ## Campos opcionais | Campo | Tipo | Descrição | |---|---|---| | `external_source` | string | Sistema de origem (default: `custom`) | | `order_number` | string | Número do pedido | | `transaction_id` | string | ID da transação no gateway de pagamento. Ver a nota abaixo | | `arn` | string | Acquirer Reference Number | | `banknet_ref` | string | Referência Banknet (Mastercard) | | `auth_code` | string | Código de autorização | | `network` | string | Bandeira: `visa`, `mastercard`, `amex`, `discover`, `other` | | `card_bin` | string | BIN do cartão (6 a 8 dígitos numéricos) | | `ip_address` | string | Endereço IP do comprador | | `clearing_datetime` | string | Data de compensação (ISO 8601) | | `mcc` | string | Merchant Category Code | | `eci` | string | Electronic Commerce Indicator | | `pos_entry_mode` | string | Modo de entrada POS | | `descriptor` | string | Descritor de cobrança | | `correlation_id` | string | ID de correlação | | `device_id` | string | ID do dispositivo (mín. 15 caracteres) | | `device_fingerprint` | string | Fingerprint do dispositivo (mín. 20 caracteres) | | `customer` | object | Dados do comprador (veja abaixo) | | `addresses` | array | Endereços de entrega e/ou cobrança (veja abaixo) | | `payments` | array | Dados de pagamento (veja abaixo) | | `refunds` | array | Dados de reembolso (veja abaixo) | ### Limites de tamanho Todo campo de texto tem teto. Acima dele a resposta é `422 VALIDATION_ERROR` apontando o campo, nunca um erro de servidor. | Limite | Campos | |---|---| | 1000 | `product_description` | | 255 | `descriptor`, `merchant_name`, `product_name`, `device_fingerprint`, `street`, `reason` (refund) | | 200 | `billing_name` | | 100 | `external_id`, `order_number`, `transaction_id`, `arn`, `banknet_ref`, `correlation_id`, `merchant_ref`, `device_id`, `first_name`, `last_name`, `city`, `state`, `category` | | 64 | `method_masked`, `reference_number` | | 45 | `ip_address` (cabe IPv6) | | 50 | `external_source`, `auth_code`, `account_id` | | 32 | `unit_of_measure` | | 30 | `phone`, `postal_code`, `wallet_indicator` | | 20 | `number` (endereço) | | 16 | `payment_type` | | 10 | `mcc`, `pos_entry_mode` | | 7 | `card_expiry` | | 5 | `eci` | | 2 | `cvv2_presence_indicator`, `avs_result` | `email` segue o limite de 255 e precisa ter formato válido. `currency`, `card_bin`, `card_last4`, `country` e `network` têm formato fixo, descrito na tabela de campos. ### Nota sobre `transaction_id` É opcional, mas preencha sempre que a cobrança passou por um gateway de pagamento: é por esse campo que a Rapid liga um chargeback futuro à transação. Mande o identificador da cobrança no gateway, não o seu número de pedido (esse é o `order_number`). Se você usa um gateway cujas disputas chegam à Rapid e o campo vem vazio, o chargeback ainda é recebido, mas sem transação associada: sem histórico, sem evidência anexada e sem os dados de autenticação, que é justamente o material da defesa. Alternativa equivalente: enviar `external_source` com o nome do gateway e `external_id` com o id da cobrança. --- ## Objeto `customer` (todos opcionais) | Campo | Tipo | Descrição | |---|---|---| | `first_name` | string | Primeiro nome | | `last_name` | string | Sobrenome | | `email` | string | E-mail (formato válido) | | `billing_name` | string | Nome no cartão | | `account_id` | string | ID da conta do comprador no seu sistema | | `phone` | string | Telefone | ## Objeto `address` (dentro do array `addresses`) | Campo | Tipo | Obrigatório | Descrição | |---|---|---|---| | `type` | string | Sim | `shipping` ou `billing` | | `street` | string | Não | Rua | | `number` | string | Não | Número | | `city` | string | Não | Cidade | | `state` | string | Não | Estado/Região | | `postal_code` | string | Não | CEP | | `country` | string | Não | Código do país ISO 3166-1, 2 ou 3 letras maiúsculas (`BR`/`BRA`, `US`/`USA`). Recomendado alpha-3. | ## Campos de autenticação do pagamento (raiz, todos opcionais) Insumos da [proteção contra fraude](https://doc.rapidchargeback.com/produtos/prevencao/integracao/#para-a-proteção-contra-fraude) e de 3-DS. Quanto mais preencher, mais forte a deflexão e a defesa. | Campo | Tipo | Descrição | |---|---|---| | `cvv2_presence_indicator` | string | Indicador de presença do CVV2 na autorização | | `cvv2_result` | string | Resultado da verificação do CVV2: `M`, `N`, `P`, `S`, `U` ou `Y`, como veio na resposta da autorização | | `avs_result` | string | Resultado do AVS (verificação de endereço) | | `cardholder_verification_approved` | boolean | 3-DS/verificação do portador aprovada | | `authentication_response_type` | string | Tipo de resposta da autenticação 3-DS: `attempt` (tentativa) ou `confirm` (autenticação confirmada) | | `wallet_indicator` | string | Carteira digital usada (ex.: Apple Pay, Google Pay) | ### Conta do comprador (dentro de `customer`, todos opcionais) Dizem se a compra foi feita por uma conta conhecida, e desde quando ela existe. São o material mais forte da defesa em disputa de fraude: comprador com conta antiga e logado é difícil de contestar como "não reconheço". | Campo | Tipo | Descrição | |---|---|---| | `registered_at` | string (ISO 8601) | Quando a conta do comprador foi criada no seu sistema | | `registered_at_source` | string | De onde vem `registered_at`: `merchant_api` (registro da conta no seu sistema) ou `client_declared` (declaração sua, sem esse registro) | | `account_authenticated` | boolean | O comprador estava logado na conta ao comprar | | `account_authenticated_source` | string | Como você sabe disso: `per_account` (verificado nesta compra) ou `onboarding_flag` (regra da sua loja, por exemplo, toda compra exige login) | | `account_authenticated_at` | string (ISO 8601) | Quando foi o login | | `auth_method` | string | Como o comprador entrou: `password`, `otp`, `2fa`, `biometric`, `oauth` ou `other` | | `account_source_method` | string | De onde vêm os dados de conta: `merchant_api` ou `client_declared` | | `checkout_type` | string | Como a compra foi feita: `guest` (sem conta), `authenticated` (conta existente, logado) ou `registered_at_checkout` (conta criada durante a compra) | Valor fora das listas responde `422 VALIDATION_ERROR`. ## Objeto `payment` (todos opcionais) | Campo | Tipo | Descrição | |---|---|---| | `payment_type` | string | Tipo de pagamento (credit, debit, pix, etc.) | | `method_masked` | string | Número mascarado | | `matched_payment` | boolean | Se este pagamento foi o utilizado (default: true) | | `card_bin` | string | BIN (6-8 dígitos) | | `card_last4` | string | Últimos 4 dígitos (4 dígitos numéricos) | | `installments` | integer | Número de parcelas | | `card_expiry` | string | Validade (MM/YYYY) | ## Objeto `refund` | Campo | Tipo | Obrigatório | Descrição | |---|---|---|---| | `amount` | number | Sim | Valor do reembolso (positivo) | | `currency` | string | Sim | Moeda (3 letras maiúsculas, ISO 4217) | | `reference_number` | string | Não | Identificador do reembolso | | `reason` | string | Não | Motivo do reembolso | | `refund_datetime` | string | Não | Data do reembolso (ISO 8601) | --- ## Validações - `transaction_date` deve estar em ISO 8601 com timezone - `currency` deve ser um código ISO 4217 (3 letras maiúsculas) - `amount` deve ser maior que zero - `card_last4` deve ter exatamente 4 dígitos numéricos - `card_bin` deve ter 6 a 8 dígitos numéricos - `device_id` deve ter no mínimo 15 caracteres - `device_fingerprint` deve ter no mínimo 20 caracteres - A combinação `external_source + external_id` não pode duplicar transação existente da sua empresa ## Warnings A API retorna avisos (sem bloquear a criação) quando campos opcionais importantes estão ausentes: | Quando | Aviso | |---|---| | Sem `card_bin` | `card_bin missing: reduces match accuracy` | | Sem `order_number` | `order_number missing: recommended to identify the order in dispute responses` | | Sem `ip_address`, `device_id` **e** `device_fingerprint` | `ip_address, device_id and device_fingerprint missing: recommended, fraud protection relies on them` | Basta **um** dos três identificadores para o último aviso sumir: o IP não é obrigatório. E não há aviso de endereço de propósito: quem vende bem digital não deve enviar endereço de entrega (ver [proteção contra fraude](https://doc.rapidchargeback.com/produtos/prevencao/integracao/#digital-goods-não-envie-endereço-de-entrega)). A chave `warnings` **só aparece** na resposta quando há ao menos um aviso. Não conte com `warnings: []`. --- ## Exemplo de requisição As credenciais vêm de variáveis de ambiente (`RAPID_CLIENT_ID` e `RAPID_CLIENT_SECRET`), nunca escritas no código. **cURL** ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00 } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com" }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ] }' ``` **Node.js** ```javascript const credenciais = Buffer.from(`${process.env.RAPID_CLIENT_ID}:${process.env.RAPID_CLIENT_SECRET}`).toString('base64') const resposta = await fetch('https://api.rapidchargeback.com/api/v1/transactions', { method: 'POST', headers: { Authorization: `Basic ${credenciais}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ merchant_id: '00000000-0000-0000-0000-000000000001', external_source: 'shopify', external_id: 'TXN-2026-001', transaction_date: '2026-04-01T15:30:00Z', amount: 150.0, currency: 'USD', card_last4: '4242', card_bin: '424242', order_number: 'ORD-001', auth_code: 'AUTH999', network: 'visa', descriptor: 'LOJA EXEMPLO', ip_address: '203.0.113.10', items: [ { product_description: 'Assinatura Premium - Mensal', product_name: 'Plano Premium', quantity: 1, unit_price: 150.0, }, ], customer: { first_name: 'João', last_name: 'Silva', email: 'joao@exemplo.com', }, addresses: [ { type: 'shipping', street: 'Rua das Flores', number: '123', city: 'São Paulo', state: 'SP', postal_code: '01001000', country: 'BRA', }, ], }), }) const corpo = await resposta.json() if (!resposta.ok) throw new Error(`${resposta.status} ${corpo.error.code}: ${corpo.error.message}`) console.log('Transação criada:', corpo.data.id) for (const aviso of corpo.warnings ?? []) console.warn('Aviso:', aviso) ``` **Python** ```python import os import requests resposta = requests.post( "https://api.rapidchargeback.com/api/v1/transactions", auth=(os.environ["RAPID_CLIENT_ID"], os.environ["RAPID_CLIENT_SECRET"]), json={ "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "shopify", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T15:30:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "order_number": "ORD-001", "auth_code": "AUTH999", "network": "visa", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "items": [ { "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": 150.00, } ], "customer": { "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com", }, "addresses": [ { "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA", } ], }, timeout=30, ) corpo = resposta.json() if not resposta.ok: raise RuntimeError(f"{resposta.status_code} {corpo['error']['code']}: {corpo['error']['message']}") print("Transação criada:", corpo["data"]["id"]) for aviso in corpo.get("warnings", []): print("Aviso:", aviso) ``` **PHP** ```php '00000000-0000-0000-0000-000000000001', 'external_source' => 'shopify', 'external_id' => 'TXN-2026-001', 'transaction_date' => '2026-04-01T15:30:00Z', 'amount' => 150.00, 'currency' => 'USD', 'card_last4' => '4242', 'card_bin' => '424242', 'order_number' => 'ORD-001', 'auth_code' => 'AUTH999', 'network' => 'visa', 'descriptor' => 'LOJA EXEMPLO', 'ip_address' => '203.0.113.10', 'items' => [ [ 'product_description' => 'Assinatura Premium - Mensal', 'product_name' => 'Plano Premium', 'quantity' => 1, 'unit_price' => 150.00, ], ], 'customer' => [ 'first_name' => 'João', 'last_name' => 'Silva', 'email' => 'joao@exemplo.com', ], 'addresses' => [ [ 'type' => 'shipping', 'street' => 'Rua das Flores', 'number' => '123', 'city' => 'São Paulo', 'state' => 'SP', 'postal_code' => '01001000', 'country' => 'BRA', ], ], ]; $ch = curl_init('https://api.rapidchargeback.com/api/v1/transactions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_USERPWD => getenv('RAPID_CLIENT_ID') . ':' . getenv('RAPID_CLIENT_SECRET'), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($transacao), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $bruto = curl_exec($ch); if ($bruto === false) { throw new RuntimeException('Falha de rede: ' . curl_error($ch)); } $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $corpo = json_decode($bruto, true); if ($status >= 400) { throw new RuntimeException("$status {$corpo['error']['code']}: {$corpo['error']['message']}"); } echo 'Transação criada: ', $corpo['data']['id'], PHP_EOL; foreach ($corpo['warnings'] ?? [] as $aviso) { echo 'Aviso: ', $aviso, PHP_EOL; } ``` --- ## Exemplos de resposta ### Sucesso ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "company_id": "...", "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "amount": 150.00, "currency": "USD", "transaction_date": "2026-04-01T15:30:00.000Z", "card_last4": "4242", "created_at": "2026-04-01T15:31:00.000Z", "transaction_items": [...], "transaction_customers": [...], "transaction_addresses": [...] } } ``` ### Duplicata ```json { "error": { "code": "TRANSACTION_DUPLICATE", "message": "Transaction already exists" } } ``` ### Erro de validação ```json { "error": { "code": "VALIDATION_ERROR", "message": "card_last4 must be exactly 4 digits" } } ``` --- # Envio em lote > Cria múltiplas transações em uma única requisição (até 1000 por chamada). Página: https://doc.rapidchargeback.com/canais/transactions/envio-em-lote/ Cria múltiplas transações em uma única requisição (até 1000 por chamada). Use o envio em lote quando você precisa sincronizar grandes volumes (ex: carga inicial, reprocessamento de um dia inteiro). O processamento é por transação: o sucesso de uma não depende do sucesso das outras. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/transactions/batch ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Corpo da requisição | Campo | Tipo | Descrição | |---|---|---| | `transactions` | array | Lista de transações (mín. 1, máx. 1000) | Cada item do array segue o mesmo schema de [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/): mesmos campos obrigatórios, opcionais, aninhados e validações. --- ## Validações - O array `transactions` deve ter entre 1 e 1000 itens. Problema **no envelope** (array ausente, vazio ou acima de 1000) rejeita a requisição inteira - O corpo da requisição pode ter até **5 MB**, o que cobre 1000 transações com todos os campos preenchidos. Acima disso a resposta é `413 PAYLOAD_TOO_LARGE` e nada é criado: divida em lotes menores - Dentro do array, **cada transação é validada individualmente**: campo inválido, campo obrigatório ausente, texto acima do limite, duplicata, merchant inexistente. Tudo isso vira erro daquela linha - Erro em uma linha **não** bloqueia as outras: as válidas são criadas e a resposta diz quais falharam - Duplicata dentro do próprio lote (mesmo `external_source` e `external_id` duas vezes) cria a primeira e falha a segunda --- ## Exemplo de requisição ```bash curl -X POST https://api.rapidchargeback.com/api/v1/transactions/batch \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transactions": [ { "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "custom", "external_id": "TXN-2026-001", "transaction_date": "2026-04-01T10:00:00Z", "amount": 150.00, "currency": "USD", "card_last4": "4242", "items": [{ "product_description": "Item A", "unit_price": 150.00 }] }, { "merchant_id": "00000000-0000-0000-0000-000000000001", "external_source": "custom", "external_id": "TXN-2026-002", "transaction_date": "2026-04-01T11:00:00Z", "amount": 200.00, "currency": "BRL", "card_last4": "1234", "items": [{ "product_description": "Item B", "unit_price": 200.00 }] } ] }' ``` --- ## Exemplos de resposta O lote responde **`200`**, e não `201`: numa chamada que cria algumas linhas e falha outras, o status sozinho não diz o resultado. Quem diz é o corpo. Confira sempre `failed` e `errors`, nunca só o código HTTP. ### Resultados mistos (200) ```json { "data": { "created": 1, "failed": 1, "results": [ { "external_id": "TXN-2026-001", "tx_id": "00000000-0000-0000-0000-000000000042", "warnings": ["card_bin missing: reduces match accuracy"] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 409, "error": "Transaction already exists" } ] } } ``` Cada item em `results` contém: - `external_id`: identifica a transação no seu sistema. - `tx_id`: UUID gerado pela Rapid (guarde para operações futuras). - `warnings`: avisos de campos ausentes (não bloqueiam a criação). Cada item em `errors` contém: - `index`: posição da linha no array que você enviou, começando em zero. É por aqui que você localiza a linha quando o campo inválido é justamente o `external_id`. - `external_id`: identifica qual transação falhou, ou string vazia se o valor enviado não era válido. - `status`: código HTTP equivalente do erro (`422` validação, `404` merchant inexistente, `409` duplicata). - `error`: mensagem descritiva. `created + failed` é sempre o total de linhas enviadas. `results` e `errors` saem na ordem de entrada. ### Todas criadas com sucesso (200) ```json { "data": { "created": 2, "failed": 0, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] }, { "external_id": "TXN-2026-002", "tx_id": "uuid-2", "warnings": [] } ], "errors": [] } } ``` ### Linha com campo inválido (200) Uma linha reprovada na validação não derruba as outras: ela aparece em `errors` com `status: 422`. ```json { "data": { "created": 1, "failed": 1, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 422, "error": "Currency must be 3 uppercase letters (ISO 4217)" } ] } } ``` ### Erro de validação do batch (fora do array) Se o array `transactions` estiver vazio, faltando ou exceder 1000 itens, a requisição inteira é rejeitada: ```json { "error": { "code": "VALIDATION_ERROR", "message": "Array must contain at most 1000 element(s)" } } ``` --- ## Comportamentos do lote que vale conhecer - `merchant_ref` **desconhecido cria o vendedor** (com `merchant_name`, se enviado) e não retorna 404. - Duplicata **dentro do mesmo lote** (mesmo `external_source`/`external_id` duas vezes) falha na segunda linha com `TRANSACTION_DUPLICATE`; a primeira é criada. - A ordem de `results` é a ordem de entrada. --- # Consultar transação > Retorna os dados completos de uma transação, pelo ID da Rapid ou pelo ID do seu sistema, incluindo itens, cliente, endereços, pagamentos e reembolsos. Página: https://doc.rapidchargeback.com/canais/transactions/consultar-transacao/ Retorna os dados completos de uma transação, incluindo itens, cliente, endereços, pagamentos e reembolsos. Dá para buscar pelo ID que a Rapid devolveu na criação ou, se você não guardou, [pelo ID do seu sistema](#pelo-id-do-seu-sistema). ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Parâmetro de URL | Parâmetro | Tipo | Descrição | |---|---|---| | `id` | string (UUID) | ID da transação | --- ## Exemplo de requisição ```bash curl -X GET https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Exemplos de resposta ### Sucesso ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "company_id": "00000000-0000-0000-0000-0000000000c1", "merchant_id": "00000000-0000-0000-0000-000000000001", "external_id": "TXN-2026-001", "external_source": "shopify", "order_number": "ORD-001", "auth_code": "AUTH999", "arn": null, "network": "visa", "amount": "150.00", "currency": "USD", "transaction_date": "2026-04-01T15:30:00.000Z", "card_bin": "424242", "card_last4": "4242", "descriptor": "LOJA EXEMPLO", "ip_address": "203.0.113.10", "created_at": "2026-04-01T15:31:00.000Z", "updated_at": "2026-04-01T15:31:00.000Z", "transaction_items": [ { "id": "...", "product_description": "Assinatura Premium - Mensal", "product_name": "Plano Premium", "quantity": 1, "unit_price": "150.00" } ], "transaction_customers": [ { "id": "...", "first_name": "João", "last_name": "Silva", "email": "joao@exemplo.com" } ], "transaction_addresses": [ { "id": "...", "type": "shipping", "street": "Rua das Flores", "number": "123", "city": "São Paulo", "state": "SP", "postal_code": "01001000", "country": "BRA" } ], "transaction_payments": [], "transaction_refunds": [] } } ``` ### Transação não encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` --- ## Pelo ID do seu sistema Se você não guardou o `id` que a Rapid devolveu na criação, ache a transação pelo identificador que **você** enviou: `external_source` mais `external_id`. É a mesma combinação que impede duplicata na criação, então a resposta tem **no máximo uma** transação. ``` GET https://api.rapidchargeback.com/api/v1/transactions?external_source=shopify&external_id=TXN-2026-001 ``` | Param | Tipo | Obrigatório | Descrição | |---|---|---|---| | `external_id` | string (até 100) | Sim | O `external_id` enviado na criação | | `external_source` | string (até 50) | Não | O `external_source` enviado na criação. Sem ele, vale `custom`, o mesmo padrão da criação | Isto **não** é uma listagem de transações: sem `external_id` a resposta é `422`. Com o `id` em mãos, [atualizar](https://doc.rapidchargeback.com/canais/transactions/atualizar-transacao/) e [deletar](https://doc.rapidchargeback.com/canais/transactions/deletar-transacao/) funcionam normalmente. ### Exemplo ```bash curl -G "https://api.rapidchargeback.com/api/v1/transactions" \ --data-urlencode "external_source=shopify" \ --data-urlencode "external_id=TXN-2026-001" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Achou `200` com uma lista de um item, no mesmo formato da consulta por ID: ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000042", "external_source": "shopify", "external_id": "TXN-2026-001", "...": "demais campos, como na consulta por ID" } ] } ``` ### Não achou `200` com a lista vazia. Transação de outra empresa também volta vazia: a busca é sempre dentro da sua. ```json { "data": [] } ``` ### Sem `external_id` ```json { "error": { "code": "VALIDATION_ERROR", "message": "external_id is required" } } ``` --- # Atualizar transação > Atualiza uma transação existente. Todos os campos são opcionais, envie apenas o que deseja alterar. Página: https://doc.rapidchargeback.com/canais/transactions/atualizar-transacao/ Atualiza uma transação existente. Todos os campos são opcionais, envie apenas o que deseja alterar. Quando child records são enviados (`items`, `addresses`, `payments`, `refunds`, `customer`), eles **substituem completamente** os registros existentes. ## Endpoint ``` PATCH https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Parâmetro de URL | Parâmetro | Tipo | Descrição | |---|---|---| | `id` | string (UUID) | ID da transação (retornado no campo `id` da resposta de criação) | Não guardou o `id`? Ache a transação [pelo ID do seu sistema](https://doc.rapidchargeback.com/canais/transactions/consultar-transacao/#pelo-id-do-seu-sistema). --- ## Campos aceitos Todos os campos aceitos por [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/) podem ser enviados aqui, todos opcionais: - Campos enviados substituem o valor atual - Campos omitidos mantêm o valor atual - Child records enviados (`items`, `addresses`, etc.) substituem completamente os existentes --- ## Validações - Se `merchant_id` for alterado, o novo merchant deve pertencer à sua empresa - Se `external_id` ou `external_source` forem alterados, a combinação não pode duplicar outra transação existente - Se a transação já foi utilizada por alguma solução (ex: consultada pela **Prevenção**), a atualização é bloqueada com `409 Conflict` --- ## Exemplo de requisição ### Atualizar apenas o ARN e auth_code ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "arn": "74537119547024600128228", "auth_code": "AUTH999" }' ``` ### Atualizar items (substitui todos os itens existentes) ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "amount": 300.00, "items": [ { "product_description": "Plano Premium", "unit_price": 150.00 }, { "product_description": "Taxa de Setup", "unit_price": 150.00 } ] }' ``` --- ## Exemplos de resposta ### Sucesso ```json { "data": { "id": "00000000-0000-0000-0000-000000000042", "merchant_id": "00000000-0000-0000-0000-000000000001", "amount": 300.00, "transaction_items": [ { "product_description": "Plano Premium", "unit_price": 150.00 }, { "product_description": "Taxa de Setup", "unit_price": 150.00 } ] } } ``` ### Transação não encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` ### Transação imutável (já utilizada por uma solução) ```json { "error": { "code": "TRANSACTION_IMMUTABLE", "message": "Transaction cannot be modified, it has been used by a network event" } } ``` ### Duplicata de external_id ```json { "error": { "code": "TRANSACTION_DUPLICATE", "message": "Another transaction with this external_source/external_id already exists" } } ``` --- # Deletar transação > Deleta uma transação e todos os seus dados relacionados (itens, cliente, endereços, pagamentos, reembolsos). Página: https://doc.rapidchargeback.com/canais/transactions/deletar-transacao/ Deleta uma transação e todos os seus dados relacionados (itens, cliente, endereços, pagamentos, reembolsos). ## Endpoint ``` DELETE https://api.rapidchargeback.com/api/v1/transactions/:id ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Parâmetro de URL | Parâmetro | Tipo | Descrição | |---|---|---| | `id` | string (UUID) | ID da transação | Não guardou o `id`? Ache a transação [pelo ID do seu sistema](https://doc.rapidchargeback.com/canais/transactions/consultar-transacao/#pelo-id-do-seu-sistema). --- ## Validações - Se a transação já foi utilizada por alguma solução (ex: consultada pela **Prevenção**), a exclusão é bloqueada com `409 Conflict` --- ## Exemplo de requisição ```bash curl -X DELETE https://api.rapidchargeback.com/api/v1/transactions/00000000-0000-0000-0000-000000000042 \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Exemplos de resposta ### Sucesso ``` HTTP/1.1 204 No Content ``` Sem corpo na resposta. ### Transação não encontrada ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transaction not found" } } ``` ### Transação imutável ```json { "error": { "code": "TRANSACTION_IMMUTABLE", "message": "Transaction cannot be modified, it has been used by a network event" } } ``` --- # Códigos de erro > Os status HTTP e os códigos de erro da API de Transações, com as mensagens exatas e o formato dos erros no envio em lote. Página: https://doc.rapidchargeback.com/canais/transactions/codigos-de-erro/ ## Códigos HTTP | Código | Significado | |---|---| | 200 | Sucesso (GET, PATCH, batch) | | 201 | Transação criada (POST single) | | 204 | Transação deletada (DELETE) | | 401 | Credenciais ausentes ou inválidas | | 403 | Empresa bloqueada | | 404 | Transação ou merchant não encontrado | | 409 | Conflito (duplicata ou transação imutável) | | 422 | Erro de validação (campos inválidos) | | 429 | Muitas requisições (limite: 100 por minuto por IP) | | 500 | Erro interno do servidor | --- ## Formato das respostas de erro Todas as respostas de erro seguem o mesmo formato: ```json { "error": { "code": "ERROR_CODE", "message": "Descrição do erro" } } ``` --- ## Códigos de erro possíveis ### Autenticação | Código | HTTP | Mensagem | |---|---|---| | `UNAUTHORIZED` | 401 | `Missing or invalid Authorization header` | | `UNAUTHORIZED` | 401 | `Invalid Basic Auth format` | | `UNAUTHORIZED` | 401 | `Missing client_id or client_secret` | | `UNAUTHORIZED` | 401 | `Invalid credentials` | | `COMPANY_BLOCKED` | 403 | `Company is blocked` | ### Validação | Código | HTTP | Mensagem | |---|---|---| | `VALIDATION_ERROR` | 422 | Mensagem do validador (ex: `card_last4 must be exactly 4 digits`) | ### Transações | Código | HTTP | Mensagem | |---|---|---| | `TRANSACTION_NOT_FOUND` | 404 | `Transaction not found` | | `TRANSACTION_DUPLICATE` | 409 | `Transaction already exists` | | `TRANSACTION_DUPLICATE` | 409 | `Another transaction with this external_source/external_id already exists` | | `TRANSACTION_IMMUTABLE` | 409 | `Transaction cannot be modified: it has been used by a network event` | | `MERCHANT_NOT_FOUND` | 404 | `Merchant not found` | ### Rate limit | Código | HTTP | Mensagem | |---|---|---| | `RATE_LIMIT_EXCEEDED` | 429 | `Rate limit exceeded, retry in X seconds` | --- ## Erros no envio em lote No endpoint de batch, erros individuais são retornados no array `errors` dentro de `data`, sem interromper o processamento das demais transações: ```json { "data": { "created": 1, "failed": 2, "results": [ { "external_id": "TXN-2026-001", "tx_id": "uuid-1", "warnings": [] } ], "errors": [ { "index": 1, "external_id": "TXN-2026-002", "status": 409, "error": "Transaction already exists" }, { "index": 2, "external_id": "TXN-2026-003", "status": 404, "error": "Merchant not found" } ] } } ``` Cada erro inclui: - `external_id`: identifica qual transação falhou. - `status`: código HTTP equivalente do erro. - `error`: mensagem descritiva. --- # Boas práticas > Como enviar transações de forma confiável: o que enviar, formato dos dados, segurança das credenciais, tratamento de respostas e imutabilidade. Página: https://doc.rapidchargeback.com/canais/transactions/boas-praticas/ ## Envio de dados - **Envie todos os campos disponíveis.** Quanto mais dados você fornecer, maior a eficácia das soluções contratadas. Campos como `card_bin`, `order_number`, `ip_address` e `addresses` são especialmente importantes. - **Use envio em lote para grandes volumes.** Em vez de enviar uma transação por requisição, agrupe até 1000 transações no endpoint `/transactions/batch` para reduzir overhead de rede. - **Mantenha `external_source` e `external_id` consistentes.** Esses campos são usados para detecção de duplicatas. Use identificadores únicos e estáveis do seu sistema de origem. - **Envie transações o mais rápido possível.** Quanto mais próximo do momento da venda, melhor a cobertura das soluções de prevenção. ## Formato dos dados - **`transaction_date` em ISO 8601.** Use o formato completo com timezone (ex: `2026-04-01T15:30:00Z`). - **`currency` em maiúsculas.** Use o código ISO 4217 com 3 letras maiúsculas (ex: `USD`, `BRL`, `EUR`). - **`card_last4` como string.** Envie como string de exatamente 4 dígitos (ex: `"0042"`, não `42`). - **`merchant_id` como UUID.** Use o UUID do merchant conforme retornado pela API ou painel. ## Segurança - **Nunca exponha seu `client_secret`.** Trate como senha. Não inclua em código frontend, repositórios públicos ou logs. - **Use sempre HTTPS.** Todas as requisições devem ser feitas via HTTPS. - **Implemente retry com espera progressiva.** Em erro 500 (erro interno), aguarde antes de tentar novamente: 1s, 2s e depois 4s entre tentativas. No `429` não precisa chutar, a resposta traz o header `Retry-After` com os segundos exatos até a janela virar (ver [Rate limit](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/#rate-limit)). ## Tratamento de respostas - **Transação única:** verifique o campo `data` para os dados da transação criada e `warnings` para avisos. - **Envio em lote:** itere sobre `results` (sucessos com `tx_id` e `warnings`) e `errors` (falhas com `external_id`, `status` e mensagem). - **Atente-se aos `warnings`.** Não bloqueiam a criação, mas indicam campos ausentes que impactam a eficácia das soluções. - **Guarde o `id` retornado.** Você precisará dele para consultar, atualizar ou deletar a transação. ## Imutabilidade - **Corrija erros antes da primeira consulta.** Transações utilizadas pelas soluções (ex: consultadas pela **Prevenção**) se tornam imutáveis. Use PATCH para corrigir dados enquanto a transação ainda não foi utilizada. --- # Visão geral > Como a Rapid entrega alertas e eventos no seu sistema por webhook HTTPS: cadastro da URL, chave de assinatura e fluxo de entrega. Página: https://doc.rapidchargeback.com/canais/webhook/visao-geral/ A Rapid entrega alertas e eventos para o sistema do cliente via **webhook HTTPS POST**. Sua aplicação expõe uma URL, a Rapid envia requisições para ela cada vez que houver um alerta a notificar. Webhook é o mecanismo universal de entrega. Hoje dois produtos usam o canal: - **Alerta**: `chargeback_alert.received`: um alerta novo chegou. - **Disputa**: `dispute.fraud.revoke_access`: chegou uma disputa de fraude e a bandeira exige cortar o acesso do portador. A URL é uma só; o campo `event` (e o header `X-Webhook-Event`) diz qual evento chegou. Qualquer produto futuro usa o mesmo canal. Internamente os provedores são identificados por slugs em payloads e respostas: `ethoca_alerts` (Mastercard) e `verifi_rdr` (Visa). ## Fluxo resumido 1. Você cadastra a URL do seu endpoint no painel da Rapid; a Rapid gera a chave de assinatura e mostra uma única vez 2. Quando um alerta é recebido e associado à sua empresa, a Rapid enfileira a entrega 3. A Rapid faz `HTTP POST` para sua URL com o payload do evento 4. Sua aplicação valida a assinatura do header `X-Webhook-Signature`, processa o evento e retorna `200` ou `204` 5. Se sua aplicação retornar erro ou não responder, a Rapid tenta novamente (ver [Retries e logs](https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/)) ## Configuração - Cada empresa pode ter **um webhook ativo por vez**. - A chave de assinatura (`secret`) é gerada pela Rapid no cadastro, mostrada **uma única vez** e usada para validar a assinatura HMAC-SHA256. Perdeu? Peça uma nova ao suporte (a anterior deixa de valer). - Se o webhook estiver inativo, os eventos continuam sendo armazenados e ficam visíveis no painel, mas não são entregues. Uma revogação de acesso não entregue aparece como pendência na disputa, para tratamento manual. ## Próximos passos - [Payload](https://doc.rapidchargeback.com/canais/webhook/payload/): estrutura completa do body enviado. - [Autenticação](https://doc.rapidchargeback.com/canais/webhook/autenticacao/): como validar `X-Webhook-Signature`. - [Retries e logs](https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/): política de retentativas. - [Boas práticas](https://doc.rapidchargeback.com/canais/webhook/boas-praticas/): idempotência, timeout, resposta rápida. --- # Payload > Os eventos que a Rapid envia por webhook: headers, campos de cada corpo, exemplos completos e a diferença entre os formatos v2 e legacy. Página: https://doc.rapidchargeback.com/canais/webhook/payload/ A Rapid envia `HTTP POST` com `Content-Type: application/json` para a URL configurada. O corpo é um objeto JSON e o campo `event` (também no header `X-Webhook-Event`) diz o que aconteceu. ## Eventos | Evento | Produto | Quando dispara | Corpo | |---|---|---|---| | `chargeback_alert.received` | Alerta | Um alerta foi recebido e associado à sua empresa | [Alerta recebido](#evento-chargeback_alertreceived) | | `dispute.fraud.revoke_access` | Disputa | Chegou uma disputa de **fraude** (Visa 10.4 / Mastercard 4837) e a bandeira exige que você corte o acesso do portador | [Revogação de acesso](#evento-disputefraudrevoke_access) | A mesma URL recebe todos os eventos: use `event` (ou o header) para rotear. Se você só trata um deles, responda `200` para os demais mesmo sem processar. Existem **dois formatos**, definidos pela Rapid na sua conta: - **`v2`**: padrão para contas novas. Descrito nesta página (headers, assinatura, corpo). - **`legacy`**: contas migradas do sistema anterior. Mesmo corpo e headers do sistema antigo, **sem assinatura**. Descrito na seção [Formato legacy](#formato-legacy) no fim da página. O formato `legacy` vale **apenas** para `chargeback_alert.received`: os outros eventos saem sempre em `v2`, mesmo nessas contas. Para saber/alterar o formato da sua conta, fale com o suporte da Rapid. ## Método e headers (formato `v2`) ``` POST https://seu-sistema.com/webhooks/rapid Content-Type: application/json X-Webhook-Signature: sha256= X-Webhook-Timestamp: 1790000000 X-Webhook-Event: chargeback_alert.received X-Webhook-Reference-Id: ``` - `X-Webhook-Signature`: HMAC-SHA256 de `${X-Webhook-Timestamp}.${body}` com a sua chave de assinatura. Ver [Autenticação](https://doc.rapidchargeback.com/canais/webhook/autenticacao/). - `X-Webhook-Timestamp`: quando a Rapid assinou, em segundos desde a epoch. Entra na assinatura (anti-replay) e deve ser conferido contra uma janela de tolerância de 5 minutos. - `X-Webhook-Event`: tipo do evento (ver [Eventos](#eventos)). Use para roteamento. - `X-Webhook-Reference-Id`: ID de referência do evento: `alert_id` em `chargeback_alert.received`, `dispute_id` em `dispute.fraud.revoke_access`. Permite deduplicação sem parsear o body. > Os headers `clientid`/`clientkey` **não** são enviados no formato `v2`: quem autentica a entrega é a assinatura. Eles seguem indo apenas no formato `legacy` (ver [Formato legacy](#formato-legacy)). --- ## Evento `chargeback_alert.received` ### Estrutura do corpo | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `event` | string | `chargeback_alert.received` | Sim | | `alert_id` | string (UUID) | ID único do alerta na Rapid, use para chamar os endpoints de consulta e atualização de status | Sim | | `provider_alert_id` | string | ID do alerta no sistema do provedor. Útil para cross-referência em caso de suporte direto com o provedor | Sim | | `provider` | string | Origem do alerta: `ethoca_alerts` ou `verifi_rdr` | Sim | | `amount` | number \| null | Valor da transação disputada (pode vir `null` quando o provedor não informa) | Sim | | `currency` | string | Código ISO 4217 com 3 letras maiúsculas | Sim | | `card_last4` | string | Últimos 4 dígitos do cartão | Sim | | `card_bin` | string | BIN do cartão (6-8 dígitos) | Sim | | `transaction_date` | string | Data da transação original (ISO 8601, `"2026-04-01T00:00:00.000Z"`) | Sim | | `descriptor` | string | Nome exibido na fatura do portador | Sim | | `arn` | string | Acquirer Reference Number | Não | | `caid` | string | Card Acceptor ID | Não | | `auth_code` | string | Código de autorização da transação | Não | | `alert_type` | string | Tipo do alerta (ex: `fraud`, `dispute`) | Não | | `reason_code` | string | Código do motivo da disputa | Não | | `issuer` | string | Banco emissor do cartão | Não | | `installment_number` | number \| null | Parcela atual | Não | | `installment_count` | number \| null | Total de parcelas | Não | | `status` | string | Status inicial do alerta. Sempre `pending` no recebimento | Sim | | `received_at` | string | Quando a Rapid recebeu o alerta (ISO 8601) | Sim | | `expires_at` | string \| null | Prazo para resposta (ISO 8601), aplicável apenas a Ethoca | Não | | `merchant` | object \| null | Dados do merchant associado (veja abaixo); `null` se o alerta ainda não foi associado | Sim | #### Objeto `merchant` | Campo | Tipo | Descrição | |---|---|---| | `id` | string (UUID) | ID do merchant na Rapid | | `name` | string | Nome do merchant | --- ### Exemplo de payload ```json { "event": "chargeback_alert.received", "alert_id": "00000000-0000-0000-0000-000000000099", "provider_alert_id": "2UBOD4MKAI42RPXEYU4UVQPS", "provider": "ethoca_alerts", "amount": 150.00, "currency": "USD", "card_last4": "4242", "card_bin": "424242", "transaction_date": "2026-04-01T00:00:00.000Z", "descriptor": "LOJA EXEMPLO", "arn": "74537119547024600128228", "caid": "123456789", "auth_code": "123456", "alert_type": "fraud", "reason_code": "4853", "issuer": "Chase Bank", "installment_number": null, "installment_count": null, "status": "pending", "received_at": "2026-04-14T10:00:00Z", "expires_at": "2026-04-15T10:00:00Z", "merchant": { "id": "00000000-0000-0000-0000-000000000001", "name": "Minha Loja" } } ``` --- ## Evento `dispute.fraud.revoke_access` Disparado quando a Rapid recebe uma disputa de **fraude**. As bandeiras exigem que o lojista tente revogar o produto ou serviço entregue ao portador e tenha processo para evitar reincidência (Visa Core Rules §10.4.4.3). Quanto mais rápido o corte, menor o prejuízo: trate este evento de forma automática se possível. O campo `merchant` diz **qual das suas lojas** vendeu: a entrega é sempre no webhook único da empresa, você roteia internamente. ### Estrutura do corpo | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `event` | string | `dispute.fraud.revoke_access` | Sim | | `dispute_id` | string (UUID) | ID da disputa na Rapid. Use como chave de idempotência; a disputa aparece no painel, em Disputas | Sim | | `merchant` | object \| null | Loja associada (`id`, `name`); `null` se a disputa ainda não foi associada | Sim | | `network` | string | Bandeira: `visa`, `mastercard`, … | Sim | | `condition` | string \| null | Condição/reason da bandeira (ex.: `10.4`, `4837`) | Não | | `transaction_id` | string \| null | ID da transação na rede, quando informado pela adquirente | Não | | `customer_ref` | string \| null | Identificador do cliente que você enviou na transação (`account_id`), quando existir | Não | | `order_ref` | string | Referência do pedido: número do pedido, seu ID externo ou, na falta deles, o `dispute_id` | Sim | | `reason` | string | Sempre `fraud_dispute_received` | Sim | | `is_account_takeover` | boolean | `true` quando há indício de conta tomada (dispositivo e IP divergem do histórico do cliente) | Sim | | `required_actions` | string[] | Ações exigidas: `revoke_access`, `prevent_reoccurrence` e, em conta tomada, `re_authenticate` | Sim | | `citation` | object | Regra que fundamenta a exigência (`section`, `visa_id`, `page`, `quote_en`, `ruleset_version`) | Sim | | `emitted_at` | string | Quando a Rapid emitiu o evento (ISO 8601) | Sim | | `deadline_hint` | string | Prazo de resposta da disputa (ISO 8601) ou `as_soon_as_possible` quando não há prazo conhecido | Sim | ### Exemplo de payload ```json { "event": "dispute.fraud.revoke_access", "dispute_id": "00000000-0000-0000-0000-0000000000d1", "merchant": { "id": "00000000-0000-0000-0000-000000000001", "name": "Minha Loja" }, "network": "visa", "condition": "10.4", "transaction_id": "ch_3Qx0000000", "customer_ref": "acct-8842", "order_ref": "PED-5078", "reason": "fraud_dispute_received", "is_account_takeover": false, "required_actions": ["revoke_access", "prevent_reoccurrence"], "citation": { "section": "10.4.4.3", "visa_id": "0030642", "page": 634, "quote_en": "An Acquirer must ensure that its Merchant attempts to revoke provision of goods or services from the Cardholder after a Dispute category 10 (Fraud) Dispute and that the Merchant has a process in place to prevent reoccurrence by the Cardholder.", "ruleset_version": "visa-core-rules-2026-04-18" }, "emitted_at": "2026-09-30T14:25:00.000Z", "deadline_hint": "2026-10-14T14:20:00.000Z" } ``` ### Confirmando o que você fez (opcional) Responder `200` já encerra a entrega. Se quiser registrar o que foi feito, retorne no corpo um JSON com os campos abaixo. Ele aparece no painel, na disputa, como confirmação da sua integração. Chave desconhecida invalida o corpo inteiro (a entrega continua válida, só não registra a confirmação). | Campo | Tipo | Descrição | |---|---|---| | `status` | string | `done`, `partial`, `refused`, `not_applicable` ou `accepted` | | `actions_taken` | string[] | Quais das `required_actions` você executou | | `revoked_at` | string | Quando o acesso foi cortado (ISO 8601) | | `note` | string | Observação livre, até 500 caracteres | ```json { "status": "done", "actions_taken": ["revoke_access", "prevent_reoccurrence"], "revoked_at": "2026-09-30T14:25:03Z", "note": "conta suspensa e cartao bloqueado para novas compras" } ``` **Idempotência:** a Rapid emite **um** evento por disputa (`dispute_id` é único). Retentativas repetem o mesmo `dispute_id`, então trate pela chave em vez de contar chamadas. Se não conseguirmos entregar, a disputa aparece no painel com a pendência de revogação, e o cliente confirma manualmente ali. --- ## Resposta esperada Sua aplicação deve retornar um dos seguintes códigos para confirmar o recebimento: | Código | Significado | |---|---| | `2xx` | Sucesso. `200`, `201`, `202` e `204` valem igual; o corpo é opcional | Qualquer outro código (incluindo `4xx` e `5xx`) é tratado como falha e dispara retentativa. Cadastre a URL final: um `301`, `302` ou `303` na sua URL conta como falha (ver [Redirecionamento](https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/#redirecionamento)). Ver [Retries e logs](https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/). Em `dispute.fraud.revoke_access` o corpo do `200` pode trazer a confirmação do que você executou (ver [acima](#confirmando-o-que-você-fez-opcional)). Nos demais eventos o corpo é ignorado. --- ## Campos que podem evoluir Novos campos podem ser adicionados ao payload no futuro. Sua aplicação deve **ignorar campos desconhecidos** em vez de falhar. Nunca altere ou remova campos ao processar, apenas leia. --- ## Formato legacy Contas migradas do sistema anterior recebem o **mesmo POST de antes**. Headers: `Content-Type: application/json`, `x-source: rapid`, `clientid`, `clientkey`, e **sem** `X-Webhook-Signature`, `X-Webhook-Event` ou `X-Webhook-Reference-Id`. | Campo | Tipo | Descrição | |---|---|---| | `alert_id` | string | **ID do alerta no provedor** (não é o UUID da Rapid). É o valor a usar em `POST /chargeback-alert/get` e no alias `POST /chargeback-alert/update/status` | | `merchant` | string | Nome do merchant | | `provider` | string | `ethoca` ou `verifi-rdr` | | `descriptor` | string | Nome na fatura do portador | | `transaction_date` | string | Data da transação (ISO 8601) | | `currency` | string | ISO 4217 | | `amount` | number \| null | Valor da transação | | `card_number` | string \| null | `BIN******LAST4`, ou `null` quando o provedor não informou BIN e final | | `created_at` | string | Quando a Rapid recebeu o alerta | | `arn` | string \| null | Acquirer Reference Number | | `authorization_code` | string \| null | Código de autorização | | `issuer` | string \| null | Banco emissor | | `type` | string \| null | Tipo do alerta | | `global` | boolean | `true` para alerta internacional | | `reason_code`, `status_code`, `mcc`, `tier`, `caid` | string \| null | Campos do provedor, quando existirem | | `installment_number`, `total_installment_count` | number \| null | Parcelamento | Não há campo `event`, `status` nem `expires_at` neste formato. Retentativas, timeout e logs são os mesmos do `v2`. --- # Autenticação > Como validar a assinatura HMAC-SHA256 dos webhooks da Rapid, com proteção contra replay e exemplos prontos em Node.js, Python e PHP. Página: https://doc.rapidchargeback.com/canais/webhook/autenticacao/ No formato **`v2`** a Rapid assina cada webhook com **HMAC-SHA256** usando a sua chave de assinatura (o `secret`). A Rapid **gera** essa chave quando você cadastra o webhook e a mostra **uma única vez** no painel, em `Configurações > Webhook`; guarde na hora. Não há como recuperar a chave depois: se perder, peça uma nova ao suporte da Rapid (a anterior deixa de valer no mesmo instante). Sua aplicação deve validar essa assinatura antes de processar o payload, é assim que você confirma que o POST veio da Rapid. > Contas no formato **`legacy`** (migradas do sistema anterior) **não recebem assinatura**: a autenticação é feita pelos headers `clientid`/`clientkey`, como antes. Veja qual é o seu formato em [Payload](https://doc.rapidchargeback.com/canais/webhook/payload/). ## Header de assinatura ``` X-Webhook-Signature: sha256= ``` Onde `` é o HMAC-SHA256, em hexadecimal, da string `${timestamp}.${corpo_bruto}`, ou seja o valor do header `X-Webhook-Timestamp` (segundos desde a epoch), um ponto, e o **corpo bruto da requisição** (o JSON recebido, byte a byte), usando a sua chave de assinatura. O timestamp entra na assinatura para dar **proteção contra replay**: sem ele, um POST válido capturado poderia ser reenviado indefinidamente com assinatura correta. Rejeite requisições cujo `X-Webhook-Timestamp` esteja fora de uma janela de tolerância (recomendamos **5 minutos**). --- ## Como validar 1. Leia o corpo bruto da requisição. **Não parse como JSON antes de validar**: a assinatura é calculada sobre os bytes exatos recebidos. 2. Monte `signed = timestamp + "." + raw_body`, calcule `HMAC-SHA256(secret, signed)` e codifique em hexadecimal 3. Compare com o valor em `X-Webhook-Signature` (após o prefixo `sha256=`) 4. Use comparação timing-safe para evitar timing attacks ### Exemplos Um endpoint completo em cada linguagem: lê o corpo bruto, valida a assinatura e a janela de tempo, e só então lê o JSON. Responde `401` para qualquer entrega que não passe, inclusive sem os headers. A chave vem da variável de ambiente `RAPID_WEBHOOK_SECRET`. **Node.js** ```javascript import crypto from 'node:crypto' import express from 'express' const TOLERANCIA_SEGUNDOS = 5 * 60 function validaAssinatura(corpoBruto, assinatura, timestamp, secret) { // 1. Janela de tolerância (anti-replay). Sem isto, um POST antigo capturado // continua passando pra sempre. const idade = Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) if (!Number.isFinite(idade) || idade > TOLERANCIA_SEGUNDOS) return false // 2. Assina `timestamp.corpo_bruto` (o corpo recebido, sem reserializar). const esperada = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${corpoBruto}`).digest('hex') const a = Buffer.from(esperada) const b = Buffer.from(assinatura ?? '') return a.length === b.length && crypto.timingSafeEqual(a, b) } const app = express() // express.raw, e não express.json: a assinatura é calculada sobre o corpo bruto. app.post('/webhooks/rapid', express.raw({ type: 'application/json' }), (req, res) => { const corpoBruto = req.body.toString('utf8') const ok = validaAssinatura( corpoBruto, req.get('X-Webhook-Signature'), req.get('X-Webhook-Timestamp'), process.env.RAPID_WEBHOOK_SECRET, ) if (!ok) return res.status(401).end() const evento = JSON.parse(corpoBruto) // Processe o `evento` (de preferência numa fila) e responda rápido. res.status(200).end() }) app.listen(process.env.PORT ?? 3000) ``` **Python** ```python import hashlib import hmac import os import time from flask import Flask, request TOLERANCIA_SEGUNDOS = 5 * 60 def valida_assinatura(corpo_bruto: bytes, assinatura: str, timestamp: str, secret: str) -> bool: # 1. Janela de tolerância (anti-replay). try: idade = abs(int(time.time()) - int(timestamp)) except (TypeError, ValueError): return False if idade > TOLERANCIA_SEGUNDOS or not assinatura: return False # 2. Assina `timestamp.corpo_bruto` (os bytes recebidos, sem reserializar). assinado = timestamp.encode() + b"." + corpo_bruto esperada = "sha256=" + hmac.new(secret.encode(), assinado, hashlib.sha256).hexdigest() return hmac.compare_digest(esperada.encode(), assinatura.encode()) app = Flask(__name__) @app.post("/webhooks/rapid") def webhook_rapid(): # get_data(), e não get_json(): a assinatura é calculada sobre o corpo bruto. corpo_bruto = request.get_data() ok = valida_assinatura( corpo_bruto, request.headers.get("X-Webhook-Signature", ""), request.headers.get("X-Webhook-Timestamp", ""), os.environ["RAPID_WEBHOOK_SECRET"], ) if not ok: return "", 401 evento = request.get_json() # Processe o `evento` (de preferência numa fila) e responda rápido. return "", 200 ``` **PHP** ```php TOLERANCIA_SEGUNDOS) { return false; } // 2. Assina `timestamp.corpo_bruto` (os bytes recebidos, sem reserializar). $esperada = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $corpoBruto, $secret); return hash_equals($esperada, $assinatura); } // php://input, e não json_decode antes: a assinatura é calculada sobre o corpo bruto. $corpoBruto = file_get_contents('php://input'); $ok = validaAssinatura( $corpoBruto, $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '', $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '', getenv('RAPID_WEBHOOK_SECRET') ); if (!$ok) { http_response_code(401); exit; } $evento = json_decode($corpoBruto, true); // Processe o $evento (de preferência numa fila) e responda rápido. http_response_code(200); ``` --- ## Rotação de secret A rotação é feita pelo suporte da Rapid, a pedido. A partir dela os webhooks novos já saem assinados com a chave nova, **sem período de overlap**: quem validar com a anterior passa a recusar. Combine a troca nos seus servidores e a rotação em sequência, de preferência em janela de baixo tráfego. Salvar uma **URL** nova não mexe na chave. --- ## Headers legados No formato `legacy`, a Rapid envia os headers `clientid` e `clientkey` e **não** envia assinatura, exatamente como o sistema anterior. ``` clientid: clientkey: ``` No formato `v2` esses headers **não existem**: validar por `clientid`/`clientkey` significaria receber a credencial de acesso à API em cada request (menos seguro que assinar o payload), então a autenticação da entrega é só `X-Webhook-Signature`. Quem está em `legacy` continua recebendo os headers por tempo indeterminado, para não quebrar integrações existentes. --- # Retries e logs > Quando a Rapid tenta entregar o webhook de novo, em que intervalos, o que conta como sucesso e como ler o log de entregas. Página: https://doc.rapidchargeback.com/canais/webhook/retries-e-logs/ ## Política de retentativa Se sua aplicação responder com qualquer código diferente de `2xx`, ou não responder dentro do timeout, a Rapid considera a tentativa como falha e reenvia o webhook. | Tentativa | Atraso em relação à anterior | |---|---| | 1ª | envio imediato após enfileirar | | 2ª | 5 minutos | | 3ª | 15 minutos | | 4ª | 30 minutos | Total: **4 tentativas** (1 inicial + 3 retentativas). Depois da 4ª falha a entrega é encerrada e o alerta fica disponível apenas no painel para ação manual. ## Timeout Cada tentativa tem **timeout de 30 segundos**. Se sua aplicação não responder nesse prazo, a tentativa é considerada falha. ## O que conta como sucesso Qualquer código **`2xx`**: `200`, `201`, `202`, `204` e os demais da faixa. O corpo da resposta é opcional. Qualquer outro código (incluindo `4xx` e `5xx`) dispara retentativa. ### Redirecionamento Cadastre a **URL final**. A Rapid trata redirecionamento assim: | Resposta da sua URL | O que acontece | |---|---| | `301`, `302`, `303` | **Falha.** Esses códigos trocam o POST por `GET` e descartam o corpo, então segui-los seria entregar nada. A tentativa entra na retentativa e o log mostra para onde a sua URL redireciona. | | `307`, `308` para o **mesmo** domínio | Seguido, com o POST, o corpo e os headers intactos. Até 3 redirecionamentos seguidos. | | `307`, `308` para **outro** domínio | **Falha.** O payload assinado não sai do domínio que você cadastrou. | Os casos comuns são o servidor acrescentar `/` no fim do caminho e redirecionar `http` para `https`. No log de entregas o motivo aparece começando com `[redirecionamento]`, junto com o endereço de destino. Se o alerta não deve ser processado pelo seu lado, ainda assim retorne `200` para evitar retentativas desnecessárias. ## Endereço que não é público Se o endereço cadastrado não resolve para um endereço público de internet (aponta para rede local ou privada, ou o domínio não existe), a entrega **falha sem nenhuma requisição** e entra no fluxo normal de retentativas. No log de entregas o motivo aparece começando com `[destino]`. Corrija a URL ou o DNS do domínio; veja [Use um endereço público de internet](https://doc.rapidchargeback.com/canais/webhook/boas-praticas/#use-um-endereço-público-de-internet). Se o motivo começa com `[assinatura]`, a falha é do lado da Rapid: a entrega não sai sem assinatura, e é tentada de novo automaticamente. Não é preciso fazer nada no seu sistema. ## Empresas bloqueadas Se a empresa está bloqueada por inadimplência na Rapid, **o fluxo de webhooks continua normal**: alertas seguem sendo recebidos dos provedores, armazenados e entregues à URL configurada. O painel continua disponível. O que o bloqueio corta é a **API por credencial** (leitura e escrita: `GET/PATCH /chargeback-alert/alerts`, transações, merchants, aliases legados), que passa a responder `403 COMPANY_BLOCKED`, e a defesa de novas disputas. Para interromper o recebimento de novos alertas, é necessário desativar o cadastro diretamente no provedor (ação operada pela equipe da Rapid). ## Logs de entrega Toda tentativa é registrada internamente com: - Evento entregue (`chargeback_alert.received`, `dispute.fraud.revoke_access`) - Data/hora da tentativa - URL de destino - Código HTTP da resposta - Corpo da resposta (truncado em 1000 caracteres) - Número da tentativa Você pode consultar esses logs no painel da Rapid, em **Atividade**, aba **Webhooks**, para depurar falhas de entrega. (A tela `Configurações > Webhook` é a do cadastro da URL; ela não mostra as entregas.) ## Reenvio manual Quando todas as tentativas automáticas falham, o alerta fica visível no painel. Você pode solicitar reenvio manual pela equipe da Rapid: alertas reenviados chegam como um novo webhook com o mesmo `alert_id`, por isso [idempotência](https://doc.rapidchargeback.com/canais/webhook/boas-praticas/#idempotência) é essencial. --- # Boas práticas > O que um endpoint de webhook precisa fazer: validar a assinatura, responder rápido, ser idempotente, usar HTTPS e endereço público. Página: https://doc.rapidchargeback.com/canais/webhook/boas-praticas/ ## Valide a assinatura antes de tudo Calcule e confira `X-Webhook-Signature` **antes** de parsear o JSON ou acessar o banco. Qualquer requisição com assinatura inválida deve ser descartada. Ver [Autenticação](https://doc.rapidchargeback.com/canais/webhook/autenticacao/). ## Responda rápido Retorne `200` ou `204` o quanto antes, idealmente em menos de 1 segundo. Se você precisa processar o alerta (ex: atualizar banco, chamar API do gateway), faça isso de forma assíncrona depois de responder. O timeout é de 30 segundos por tentativa. Qualquer atraso consome esse orçamento e pode disparar retentativa desnecessária. ## Idempotência A Rapid pode reenviar o mesmo alerta: - Quando a tentativa anterior falhou (retentativa automática) - Quando um alerta é reenviado manualmente pela equipe da Rapid - Em casos raros de falha de rede entre a resposta do seu servidor e a confirmação no lado da Rapid Seu processamento deve ser **idempotente por `alert_id`**: 1. Ao receber um webhook, confira se já existe um registro com esse `alert_id` no seu sistema 2. Se existir, retorne `200` imediatamente, não processe novamente 3. Se não existir, processe e armazene ## Ignore campos desconhecidos O payload pode evoluir com novos campos. Sua deserialização deve **tolerar campos extras** em vez de falhar. Nunca remova ou altere campos ao processar. ## Retorne 200 mesmo em erro de validação Se o payload chega mas você não consegue processar (ex: merchant não existe no seu lado), **ainda assim retorne 200**. Retornar erro dispara retentativa inútil. Registre a falha no seu lado (log, alerta interno, fila de erros) e trate offline. ## Use sempre HTTPS A URL do webhook precisa ser `https://`: o painel não aceita salvar uma URL `http://`, e a Rapid não entrega em HTTP puro. A assinatura prova que a requisição veio da Rapid, mas não cifra o conteúdo, e o payload leva dados do cartão (BIN e últimos 4 dígitos) e da compra. ## Use um endereço público de internet A URL precisa apontar para um servidor alcançável pela internet. A Rapid não entrega em endereço de rede local ou privada: `localhost`, `127.0.0.1`, `10.x`, `172.16.x` a `172.31.x`, `192.168.x` e equivalentes em IPv6. O painel já recusa esses endereços no cadastro, e um nome de domínio que resolva para um deles falha na hora da entrega. Para testar a integração na sua máquina, exponha o servidor local com um túnel HTTPS (como ngrok ou Cloudflare Tunnel) e cadastre o endereço público que ele gera. ## Proteja o secret O `secret` usado para validar `X-Webhook-Signature` deve ser tratado como credencial sensível: - Não comitar em repositório - Não logar - Armazenar em variável de ambiente ou cofre de segredos ## Monitoramento Recomendamos instrumentar: - Taxa de webhooks recebidos (se cair, algo pode estar errado na Rapid ou na rede) - Taxa de assinaturas inválidas (se subir, pode indicar rotação de secret não propagada ou tentativa de forjamento) - Latência de processamento (para garantir que está abaixo do timeout de 30s) - Taxa de retentativas entregues (indica problemas no seu lado) --- # Visão geral > Como a Rapid registra, na hora em que acontecem, os sinais que sustentam uma venda: aceite de termos, aparelho, acesso, entrega e uso. Página: https://doc.rapidchargeback.com/canais/capture/visao-geral/ A captura registra, no momento em que acontecem, os sinais que sustentam uma venda: o aceite dos termos no checkout, o aparelho usado na compra, o acesso ao produto, a confirmação de entrega, o uso do serviço. São dois canais para a mesma coisa, e dá para usar os dois juntos: | Canal | Quem chama | Autenticação | |---|---|---| | **Navegador** | o snippet no seu checkout, ou o seu próprio código | token publicável na URL | | **Servidor** | o seu backend | Basic Auth, igual às outras APIs | ## Fluxo resumido 1. Você ativa o SDK de captura no painel e recebe o token publicável do merchant 2. [Instala o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) no checkout, ou chama o endpoint direto 3. A cada fato relevante, envia um evento com o `order_ref` do pedido 4. A Rapid correlaciona o evento com a transação e guarda o registro 5. Se aquela transação virar disputa, os registros entram na defesa ## Como o evento vira evidência O evento **não** é anexado a nada na hora em que chega. Ele entra numa fila e só vira evidência quando casa com uma transação real do merchant dono do token, pelo campo `order_ref`. Isso tem uma consequência prática que vale entender: token vazado gera ruído, nunca dado. Quem tiver o seu token publicável consegue mandar eventos, mas eles morrem na fila se não corresponderem a um pedido seu de verdade. Por isso: - enviar evento antes da transação existir é normal, a correlação acontece depois, dentro de uma janela de cerca de 68 horas - `order_ref` tem que ser o mesmo identificador que você usa na transação (`external_id`) - a resposta de sucesso é `202 Accepted`, não `201`: a Rapid aceitou o evento, o processamento é assíncrono - `order_ref` errado não devolve erro. O evento é aceito e descartado depois, em silêncio ## Diferença entre captura e evidência | | Captura | [Evidência](https://doc.rapidchargeback.com/canais/evidence/visao-geral/) | |---|---|---| | Quando usar | no momento do fato, sem saber se vira disputa | quando você já tem a transação na Rapid | | Referência | `order_ref` (o seu identificador) | `transaction_id` ou `transaction_ref` | | Transação precisa existir | não | sim, senão `404` | | Campos do payload | lista fechada | formato livre, teto de 32 KB | | Resposta | `202`, assíncrono | `201`, já gravado | ## Autenticação - **Navegador:** o token vai na URL (`/capture/{token}/events`). É publicável, pode ficar no HTML. - **Servidor:** Basic Auth com `client_id:client_secret`. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). O token da captura é gerado no painel, em **Configurações › Integrações**, ao ativar o SDK de captura do merchant. ## Endpoints | Endpoint | Canal | O que faz | |---|---|---| | [`POST /capture/{token}/events`](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) | navegador | Envia um evento do checkout | | [`POST /capture/events`](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) | servidor | Envia um evento pelo seu backend | | [`GET /capture/{token}/config`](https://doc.rapidchargeback.com/canais/capture/config-do-snippet/) | navegador | Configuração que o snippet lê ao carregar | ## Próximos passos - [Instalar o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) - [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/) - [Enviar evento pelo navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) - [Enviar evento pelo servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) --- # Instalar o snippet > O snippet é a forma mais curta de capturar evidência: duas tags no seu checkout e uma chamada por evento. Ele conversa com o canal navegador por você. Página: https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/ O snippet é a forma mais curta de capturar evidência: duas tags no seu checkout e uma chamada por evento. Ele conversa com o [canal navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) por você. Se o seu checkout é renderizado no servidor, ou se você prefere não carregar script de terceiro, pule esta página e chame o endpoint direto. ## Onde pegar o token No painel, em **Configurações › Integrações**, no cartão do SDK de captura. Ative e o painel mostra o snippet pronto, já com o token do merchant selecionado. O cartão aparece para quem tem o produto de disputa ativo. O token é **publicável**: ele fica no HTML da sua loja e não precisa de proteção. Com ele só é possível enviar evento, nunca ler dado. Evento que não corresponde a um pedido seu é descartado. ## Instalação ```html ``` Duas coisas importam na ordem acima: 1. o `init` tem que vir depois do carregamento do script, por isso a tag não leva `async` nem `defer` 2. o `init` já começa a identificar o aparelho, então chame-o o quanto antes na página, não só na hora do pagamento O script tem cerca de 5 KB, não tem dependência e não bloqueia a página. ## Chamadas ```js // Compra finalizada. Captura também os dados do aparelho. rapid('checkout', { order_ref: 'TXN-2026-001' }) // Cliente aceitou os termos. rapid('terms', { order_ref: 'TXN-2026-001' }) // Cliente acessou o produto. rapid('track', 'access_log', { order_ref: 'TXN-2026-001' }) // Cliente usou o produto ou serviço. rapid('track', 'usage_log', { order_ref: 'TXN-2026-001' }) ``` | Chamada | Evento gerado | Payload que o snippet monta | |---|---|---| | `rapid('checkout', …)` | `checkout` | identificação do aparelho | | `rapid('terms', …)` | `terms_acceptance` | a URL da página | | `rapid('track', 'access_log', …)` | `access_log` | a URL da página | | `rapid('track', 'usage_log', …)` | `usage_log` | a URL da página | O `order_ref` é obrigatório em todas. É o identificador do pedido no seu sistema, o mesmo que você manda em `external_id` ao criar a transação. Ver [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/). Chamada sem `order_ref` é ignorada, não gera evento nem erro visível. ## Fire and forget O snippet nunca quebra o checkout, e isso tem um custo que vale conhecer: - toda chamada é silenciosa. Ele não lança exceção, não devolve promessa e não lê a resposta - erro de validação (tipo errado, `order_ref` longo demais) não aparece no console - falha de rede não é retentada no navegador Para **testar** a integração, chame o [endpoint do navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) direto com curl, onde você vê o status e a mensagem. Depois de validado, o snippet faz o mesmo em produção. O envio usa `navigator.sendBeacon` quando disponível, com `fetch` em modo `keepalive` como alternativa. Os dois sobrevivem à navegação para a página seguinte, então o evento de checkout não se perde no redirecionamento do pagamento. ## Identificação do aparelho No `checkout`, o snippet identifica o aparelho antes de enviar o evento. Ele tenta o Fingerprint, com teto de 2 segundos, e cai numa identificação própria se não conseguir (identificador em `localStorage` mais um hash de atributos do navegador). O resultado vai no campo `fp` do payload: | `fp` | Significa | |---|---| | `pro` | identificação do Fingerprint, validada do lado servidor | | `fallback` | identificação própria do snippet | A diferença é prática: só a identificação validada preenche aparelho e IP da transação e gera o registro de verificação. Ver [O evento `checkout`](https://doc.rapidchargeback.com/canais/capture/payload/#o-evento-checkout). Se o seu site tem CSP restritiva, o Fingerprint é carregado de `https://fpjscdn.net`. Bloqueado ele, a captura continua funcionando em modo `fallback`. ## Como saber se está funcionando O mesmo cartão do painel mostra se a conta já recebeu evento e quando foi o último. Depois de instalar, faça uma compra de teste e confira ali. ## Próximos passos - [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/) - [Enviar evento pelo navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) - [Enviar evento pelo servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) --- # Enviar evento pelo navegador > Registra um evento de captura usando o token publicável. É o endpoint que o snippet chama, e você pode chamá-lo direto se preferir não carregar o script. Página: https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/ Registra um evento de captura usando o token publicável. É o endpoint que o [snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) chama, e você pode chamá-lo direto se preferir não carregar o script. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/capture/{token}/events ``` ## Autenticação Nenhuma. O token publicável na URL identifica o merchant. ``` Content-Type: application/json ``` O token não é segredo e pode ficar no HTML da sua loja. Ele só permite escrever, e o evento só vira evidência se corresponder a um pedido real seu. ## Parâmetros de URL | Campo | Tipo | Descrição | |---|---|---| | `token` | string | Token publicável do merchant, gerado no painel | ## Corpo da requisição | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `type` | string (enum) | `checkout`, `terms_acceptance`, `access_log` ou `usage_log` | Sim | | `order_ref` | string | Identificador do pedido no seu sistema, até 100 caracteres | Sim | | `event_id` | string | Identificador do evento, gerado por você, até 64 caracteres | Sim | | `payload` | objeto | Dados do fato, com campos de lista fechada | Não | A referência completa dos valores aceitos está em [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/). Dois pontos específicos deste canal: - `event_id` é obrigatório aqui. Gere um UUID por evento - `captured_at` enviado no corpo é ignorado. A Rapid registra o horário de chegada. Para informar o horário do fato, use o [canal servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) Os tipos `delivery_confirmation`, `scan` e `delivery_gps` não existem neste canal: são fatos da sua operação, não do navegador do comprador. ## Limite de chamadas 120 requisições por minuto, por IP de origem. É folgado para um checkout real e aperta quem estiver usando o token fora do seu site. ## Validações | Regra | Resposta | |---|---| | Token desconhecido, inativo ou sem merchant | `404 NOT_FOUND` | | `type` ausente, ou fora dos quatro aceitos neste canal | `422 VALIDATION_ERROR`: *invalid_type* | | `order_ref` ausente, vazio ou acima de 100 caracteres | `422 VALIDATION_ERROR`: *invalid_order_ref* | | `event_id` ausente, vazio ou acima de 64 caracteres | `422 VALIDATION_ERROR`: *invalid_event_id* | | Campo de texto do `payload` acima de 512 caracteres | `422 VALIDATION_ERROR`: *payload_too_large* | | Acima de 120 requisições por minuto | `429 Too Many Requests` | Não existe erro para `order_ref` inexistente. O evento é aceito, fica na fila e é descartado se nenhuma transação corresponder dentro da janela de correlação. Ver [Janela de correlação](https://doc.rapidchargeback.com/canais/capture/payload/#janela-de-correlação). ## Exemplo de requisição ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/seu_token_publicavel/events \ -H "Content-Type: application/json" \ -d '{ "type": "terms_acceptance", "order_ref": "TXN-2026-001", "event_id": "019b0000-1111-7000-8000-000000000001", "payload": { "url": "https://loja.exemplo.com/checkout" } }' ``` Evento de checkout com identificação do aparelho: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/seu_token_publicavel/events \ -H "Content-Type: application/json" \ -d '{ "type": "checkout", "order_ref": "TXN-2026-001", "event_id": "019b0000-1111-7000-8000-000000000002", "payload": { "device_id": "8kJ2mQvR1nZxYb0T", "device_fingerprint": "8kJ2mQvR1nZxYb0T", "fp": "pro", "fp_request_id": "1712059781234.Xk9Lp2" } }' ``` ## Exemplos de resposta ### Sucesso (202) ```json { "accepted": true } ``` `202` quer dizer que o evento entrou na fila, não que já virou evidência. A correlação com a transação acontece depois. ### Erro: token desconhecido (404) ```json { "error": { "code": "NOT_FOUND" } } ``` ### Erro: tipo não disponível neste canal (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_type" } } ``` ### Erro: `event_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_event_id" } } ``` ### Erro: campo de payload longo demais (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "payload_too_large" } } ``` ## Próximos passos - [Instalar o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) - [Enviar evento pelo servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) - [Configuração do snippet](https://doc.rapidchargeback.com/canais/capture/config-do-snippet/) --- # Enviar evento pelo servidor > Registre eventos de captura pelo seu backend: entrega confirmada, rastreio, uso do serviço e eventos com data retroativa. Página: https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/ Registra um evento de captura pelo seu backend, com as mesmas credenciais das outras APIs. É o canal para fatos que não acontecem no navegador: entrega confirmada, leitura de rastreio, coordenada de entrega, e para qualquer evento que você precise reenviar ou datar. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/capture/events ``` ## Autenticação Basic Auth com `client_id:client_secret`. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` Não use o token publicável aqui. A empresa vem da credencial, por isso este canal pode gravar dado de aparelho sem a validação exigida no navegador. ## Corpo da requisição | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `merchant_id` | string (UUID) | Merchant a que o evento pertence, dentro da sua empresa (ver [Listar merchants](https://doc.rapidchargeback.com/canais/merchants/listar-merchants/)) | Sim | | `type` | string (enum) | Os quatro tipos do navegador mais `delivery_confirmation`, `scan` e `delivery_gps` | Sim | | `order_ref` | string | Identificador do pedido no seu sistema, até 100 caracteres | Sim | | `event_id` | string | Identificador do evento, até 64 caracteres. Omitido, a Rapid gera um | Não | | `payload` | objeto | Dados do fato, com campos de lista fechada | Não | | `captured_at` | string (ISO 8601) | Quando o fato aconteceu. Omitido, vale o horário da chamada | Não | A referência completa dos valores aceitos está em [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/). Três diferenças em relação ao canal navegador: - `merchant_id` é obrigatório, porque a credencial identifica a empresa e não o merchant - `captured_at` é respeitado, então uma rotina em lote pode informar o horário real de cada fato - `event_id` é opcional, mas mande o seu: é o que torna o reenvio seguro ## Idempotência Reenviar a mesma chamada com o mesmo `event_id` não duplica a evidência. É o comportamento esperado em retentativa por timeout ou resposta perdida. Se você omitir o `event_id`, cada chamada gera um identificador novo, e a mesma chamada repetida vira dois registros. ## Validações | Regra | Resposta | |---|---| | Credencial ausente ou inválida | `401 UNAUTHORIZED` | | `merchant_id` ausente | `422 VALIDATION_ERROR`: *merchant_id required* | | `type` ausente ou fora do enum | `422 VALIDATION_ERROR`: *invalid_type* | | `order_ref` ausente, vazio ou acima de 100 caracteres | `422 VALIDATION_ERROR`: *invalid_order_ref* | | `event_id` acima de 64 caracteres | `422 VALIDATION_ERROR`: *invalid_event_id* | | Campo de texto do `payload` acima de 512 caracteres | `422 VALIDATION_ERROR`: *payload_too_large* | `merchant_id` de outra empresa não acusa erro na chamada: o evento é aceito e descartado na correlação, porque a transação é procurada dentro da sua empresa. O mesmo vale para `order_ref` inexistente. ## Exemplo de requisição Entrega confirmada: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/events \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "type": "delivery_confirmation", "order_ref": "TXN-2026-001", "event_id": "entrega-TXN-2026-001", "payload": { "carrier": "correios", "tracking": "AA123456789BR" }, "captured_at": "2026-04-03T11:20:00Z" }' ``` Coordenada da entrega: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/capture/events \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "merchant_id": "00000000-0000-0000-0000-000000000001", "type": "delivery_gps", "order_ref": "TXN-2026-001", "event_id": "gps-TXN-2026-001", "payload": { "lat": -23.5614, "lng": -46.6559 }, "captured_at": "2026-04-03T11:20:00Z" }' ``` ## Exemplos de resposta ### Sucesso (202) ```json { "accepted": true } ``` `202` quer dizer que o evento entrou na fila. A correlação com a transação acontece depois, pelo `order_ref`. ### Erro: credencial ausente (401) ```json { "error": { "code": "UNAUTHORIZED", "message": "Missing or invalid Authorization header" } } ``` ### Erro: `merchant_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "merchant_id required" } } ``` ### Erro: tipo inválido (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "invalid_type" } } ``` ## Captura ou evidência Os dois canais registram fato numa transação, e a escolha é simples: | Situação | Use | |---|---| | A transação já está na Rapid e você tem o UUID dela | [`POST /evidence`](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/) | | Você tem só o seu identificador de pedido, ou o fato acontece antes do envio da transação | este endpoint | | O fato precisa de campo fora da lista fechada de payload | [`POST /evidence`](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/), que aceita payload livre | ## Próximos passos - [Tipos e payload](https://doc.rapidchargeback.com/canais/capture/payload/) - [Instalar o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) - [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/) --- # Tipos e payload > Referência dos valores aceitos nos dois canais de captura. Vale para POST /capture/{token}/events e POST /capture/events. Página: https://doc.rapidchargeback.com/canais/capture/payload/ Referência dos valores aceitos nos dois canais de captura. Vale para [`POST /capture/{token}/events`](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) e [`POST /capture/events`](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/). ## Campos do evento | Campo | Tipo | Limite | Obrigatório | |---|---|---|---| | `type` | string (enum) | ver tabela abaixo | Sim | | `order_ref` | string | 100 caracteres | Sim | | `event_id` | string | 64 caracteres | Sim no navegador, opcional no servidor | | `payload` | objeto | ver campos aceitos | Não | | `captured_at` | string (ISO 8601) | - | Não, e só o canal servidor usa | | `merchant_id` | string (UUID) | - | Só no canal servidor | ### `order_ref` É o identificador do pedido no **seu** sistema, e é a única coisa que liga o evento a uma transação. A Rapid procura, dentro da sua empresa e do merchant informado: 1. uma transação com `external_id` igual ao `order_ref` 2. se não achar, uma transação com `order_number` igual ao `order_ref` Mande sempre o mesmo valor que você usou no `external_id` ao [criar a transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/). `order_ref` errado não gera erro na chamada: o evento é aceito, não acha transação e é descartado depois da janela de correlação. ### `event_id` Identificador do evento, gerado por você. Serve de chave de idempotência: reenviar o mesmo `event_id` para o mesmo merchant não cria evidência duplicada. No canal navegador ele é **obrigatório** (o snippet gera um UUID por evento). No canal servidor, se você omitir, a Rapid gera um. Mande o seu quando puder reenviar a mesma chamada, é o que garante a idempotência. Não use `:` no `event_id`. O caractere é removido antes do uso interno, o que faria dois ids diferentes colidirem. ### `captured_at` Quando o fato aconteceu, em ISO 8601. | Canal | Comportamento | |---|---| | Navegador | ignorado. A Rapid registra o horário em que o evento chegou | | Servidor | usado como enviado. Omitido, vale o horário da chamada | Se o fato aconteceu antes da chamada (um processamento em lote à noite, por exemplo), use o canal servidor e informe `captured_at`. ## Valores de `type` | Valor | O que registra | Navegador | Servidor | |---|---|---|---| | `checkout` | Finalização da compra, com os dados do aparelho | Sim | Sim | | `terms_acceptance` | Aceite de termos, política ou contrato | Sim | Sim | | `access_log` | Acesso ao produto ou à área logada | Sim | Sim | | `usage_log` | Uso efetivo do produto ou serviço | Sim | Sim | | `delivery_confirmation` | Entrega confirmada | Não | Sim | | `scan` | Leitura de código de rastreio em trânsito | Não | Sim | | `delivery_gps` | Coordenada da entrega | Não | Sim | Os três últimos existem só no canal servidor: são fatos da sua operação, não do navegador do comprador. Usá-los no canal navegador responde `422 invalid_type`. ## Campos de `payload` O `payload` tem **lista fechada** de campos. Chave fora da lista é descartada em silêncio, sem erro, então confira a grafia. | Campo | Tipo | Usar em | |---|---|---| | `device_id` | string | `checkout` | | `device_fingerprint` | string | `checkout` | | `fp` | string | `checkout`, indica a origem da identificação (`pro` ou `fallback`) | | `fp_request_id` | string | `checkout`, exigido para validar a identificação | | `url` | string | `terms_acceptance`, `access_log`, `usage_log` | | `note` | string | qualquer tipo | | `carrier` | string | `delivery_confirmation`, `scan` | | `tracking` | string | `delivery_confirmation`, `scan` | | `lat` | número | `delivery_gps` | | `lng` | número | `delivery_gps` | Regras: - só valores escalares (string, número, booleano). Objeto e lista são descartados - string acima de **512 caracteres** responde `422 payload_too_large` - `payload` ausente ou vazio é aceito ## O evento `checkout` O `checkout` é o único tipo que grava dados direto na transação, e não apenas como registro anexo. Ele preenche aparelho e IP da transação **somente quando os campos estão vazios**: captura anterior nunca é sobrescrita. O que cada canal pode gravar: | Dado da transação | Navegador | Servidor | |---|---|---| | `device_id` | não grava | grava | | `device_fingerprint` | só com identificação validada | grava | | `ip_address` | só com identificação validada | grava | A diferença existe porque o token do navegador é publicável: qualquer pessoa com ele pode mandar eventos. Dado não validado não encosta nos campos que sustentam a defesa. **Identificação validada** quer dizer: você mandou `fp_request_id` e `device_id` no payload, e a Rapid confirmou o par contra o Fingerprint do lado servidor. Nesse caso o evento também gera um registro de verificação de aparelho, com os sinais de bot, VPN e janela anônima. Sem `fp_request_id`, o evento continua valendo como registro, apenas sem a parte de aparelho. Cada `fp_request_id` vale para **uma** transação. O mesmo par reaproveitado em outro pedido é tratado como repetição e ignorado. ## Janela de correlação O evento pode chegar antes da transação existir. Ele fica na fila e é retentado por cerca de **68 horas**, em intervalos crescentes. Passada a janela sem transação correspondente, o evento é descartado. Na prática: mandar o `checkout` no exato momento da compra funciona, mesmo que a sua rotina só envie a transação à Rapid horas depois. ## Próximos passos - [Instalar o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) - [Enviar evento pelo navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) - [Enviar evento pelo servidor](https://doc.rapidchargeback.com/canais/capture/enviar-evento-servidor/) --- # Configuração do snippet > Endpoint que devolve a configuração de identificação da conta, lido pelo snippet ao carregar. Só é preciso se você escrever o próprio coletor. Página: https://doc.rapidchargeback.com/canais/capture/config-do-snippet/ Devolve a configuração de identificação da conta. O [snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) chama este endpoint ao carregar, antes do primeiro evento. Você só precisa dele se escrever o seu próprio coletor no navegador. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/capture/{token}/config ``` ## Autenticação Nenhuma. O token publicável na URL identifica o merchant. ## Parâmetros de URL | Campo | Tipo | Descrição | |---|---|---| | `token` | string | Token publicável do merchant, gerado no painel | ## Validações | Regra | Resposta | |---|---| | Token desconhecido, inativo ou sem merchant | `404 NOT_FOUND` | ## Cache A resposta vem com `cache-control: public, max-age=300`. Respeite o cache: a configuração muda raras vezes e o snippet não precisa consultá-la a cada página. ## Exemplo de requisição ```bash curl https://api.rapidchargeback.com/api/v1/capture/seu_token_publicavel/config ``` ## Exemplos de resposta ### Sucesso (200), com Fingerprint ativo ```json { "data": { "fp_public_key": "pk_exemplo_123456", "fp_region": "us" } } ``` | Campo | Descrição | |---|---| | `fp_public_key` | Chave pública do Fingerprint a usar no navegador. `null` quando a identificação não está ativa | | `fp_region` | Região do Fingerprint: `us`, `eu` ou `ap` | Com a chave, o coletor carrega o agente do Fingerprint e obtém dois valores: o identificador do visitante e o identificador da consulta. Mande-os no evento de `checkout` como `device_id` e `fp_request_id`, que a Rapid valida o par do lado servidor. Ver [O evento `checkout`](https://doc.rapidchargeback.com/canais/capture/payload/#o-evento-checkout). ### Sucesso (200), sem Fingerprint ativo ```json { "data": { "fp_public_key": null, "fp_region": "us" } } ``` `fp_public_key` nulo não impede a captura. O evento continua sendo registrado, apenas sem a parte de identificação validada do aparelho. ### Erro: token desconhecido (404) ```json { "error": { "code": "NOT_FOUND" } } ``` ## Próximos passos - [Instalar o snippet](https://doc.rapidchargeback.com/canais/capture/instalar-o-snippet/) - [Enviar evento pelo navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/) --- # Visão geral > A API de Evidência anexa a uma transação já enviada os fatos que sustentam a defesa: aceite, acesso, entrega, uso e conversa com o cliente. Página: https://doc.rapidchargeback.com/canais/evidence/visao-geral/ A API de Evidência registra, numa transação já enviada à Rapid, os fatos que sustentam uma defesa: aceite de termos, acesso ao produto, confirmação de entrega, uso e comunicação com o cliente. É um canal de **entrada**: você chama a Rapid. O registro fica anexado à transação e é usado na montagem da defesa quando aquela transação vira disputa. ## O que ela não é - **Não é upload de arquivo.** Cada evidência é um registro JSON com teto de 32 KB. Comprovante em PDF, print e contrato ficam na biblioteca de evidências do painel, não aqui. - **Não cria transação.** A transação precisa existir antes, enviada pela [API de Transações](https://doc.rapidchargeback.com/canais/transactions/visao-geral/). Se não existir, a chamada volta `404 TRANSACTION_NOT_FOUND`. ## Fluxo resumido 1. Você envia a transação de venda pela API de Transações 2. No seu sistema acontece algo que sustenta a venda: o cliente aceitou os termos, acessou o produto, recebeu a entrega 3. Você registra esse fato com `POST /evidence`, apontando para a transação 4. Se aquela transação virar disputa, a Rapid usa os registros na defesa ## Autenticação Basic Auth com `client_id:client_secret`, igual aos outros canais. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ## Endpoints | Endpoint | O que faz | |---|---| | [`POST /evidence`](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/) | Registra uma evidência numa transação | | [`GET /evidence`](https://doc.rapidchargeback.com/canais/evidence/consultar-evidencias/) | Lista as evidências de uma transação | ## Próximos passos - [Registrar evidência](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/) - [Consultar evidências](https://doc.rapidchargeback.com/canais/evidence/consultar-evidencias/) --- # Registrar evidência > Anexa um registro de evidência a uma transação já enviada à Rapid. Página: https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/ Anexa um registro de evidência a uma transação já enviada à Rapid. ## Endpoint ``` POST https://api.rapidchargeback.com/api/v1/evidence ``` ## Autenticação Basic Auth com `client_id:client_secret`. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` ## Corpo da requisição | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `transaction_id` | string (UUID) | ID da transação na Rapid, devolvido quando você a criou | Sim, ou `transaction_ref` | | `transaction_ref` | objeto | Alternativa ao `transaction_id`: aponta a transação pelo **seu** identificador. Ver abaixo | Sim, ou `transaction_id` | | `type` | string (enum) | Natureza do fato registrado. Valores aceitos abaixo | Sim | | `payload` | objeto | Os dados do fato. Formato livre, teto de 32 KB | Sim | | `captured_at` | string (ISO 8601 com offset) | Quando o fato aconteceu no seu sistema, não quando você o envia | Sim | Informe **um** dos dois: `transaction_id` ou `transaction_ref`. Se faltarem os dois, a resposta é `422`. ### Campo `transaction_ref` | Campo | Tipo | Descrição | Obrigatório | |---|---|---|---| | `external_source` | string | A mesma origem que você usou ao criar a transação (ex: `"shopify"`) | Sim | | `external_id` | string | O mesmo ID do seu sistema que você usou ao criar a transação | Sim | ### Valores de `type` | Valor | Quando usar | |---|---| | `terms_acceptance` | Cliente aceitou termos, política ou contrato | | `access_log` | Cliente acessou o produto ou a área logada | | `delivery_confirmation` | Entrega confirmada | | `usage_log` | Uso efetivo do produto ou serviço | | `communication` | Troca com o cliente (e-mail, chat, ticket) | | `other` | Qualquer fato que não se encaixe nos anteriores | ### Campo `payload` Formato livre: você decide as chaves. A única regra é o **teto de 32 KB** no JSON serializado: evidência é registro, não arquivo. Sugestões por tipo, não obrigatórias: ```json // terms_acceptance { "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2", "ip": "203.0.113.10" } // access_log { "first_access_at": "2026-04-01T16:02:11Z", "sessions": 3 } // delivery_confirmation { "carrier": "correios", "tracking": "AA123456789BR", "delivered_at": "2026-04-03T11:20:00Z" } ``` ## Validações | Regra | Resposta | |---|---| | Nem `transaction_id` nem `transaction_ref` | `422 VALIDATION_ERROR`: *transaction_id ou transaction_ref é obrigatório* | | `type` fora do enum | `422 VALIDATION_ERROR` com a lista dos valores aceitos | | `captured_at` sem offset de fuso | `422 VALIDATION_ERROR`: *Invalid datetime* | | `payload` serializado acima de 32 KB | `422 VALIDATION_ERROR`: *payload excede 32KB: evidência é registro, não arquivo* | | Transação não existe, ou não é da sua empresa | `404 TRANSACTION_NOT_FOUND` | | Credencial ausente ou inválida | `401 UNAUTHORIZED` | A transação é sempre resolvida **dentro da sua empresa**. ID de transação de outra empresa responde `404`, nunca `403`: não confirmamos a existência de dado alheio. ## Exemplo de requisição ```bash curl -X POST https://api.rapidchargeback.com/api/v1/evidence \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transaction_id": "00000000-0000-0000-0000-000000000042", "type": "terms_acceptance", "payload": { "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2", "ip": "203.0.113.10" }, "captured_at": "2026-04-01T15:29:41Z" }' ``` Pelo seu próprio identificador, sem guardar o UUID da Rapid: ```bash curl -X POST https://api.rapidchargeback.com/api/v1/evidence \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "transaction_ref": { "external_source": "shopify", "external_id": "TXN-2026-001" }, "type": "access_log", "payload": { "first_access_at": "2026-04-01T16:02:11Z", "sessions": 3 }, "captured_at": "2026-04-01T16:02:12Z" }' ``` ## Exemplos de resposta ### Sucesso (201) ```json { "data": { "id": "00000000-0000-0000-0000-0000000000e1", "transaction_id": "00000000-0000-0000-0000-000000000042", "type": "terms_acceptance" } } ``` O `id` devolvido é o da evidência. Guarde-o só se você for referenciá-la; para listar, a chave é a transação. ### Erro: referência da transação ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "transaction_id ou transaction_ref é obrigatório" } } ``` ### Erro: `type` inválido (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid enum value. Expected 'terms_acceptance' | 'access_log' | 'delivery_confirmation' | 'usage_log' | 'communication' | 'other', received 'nao_existe'" } } ``` ### Erro: transação não encontrada (404) ```json { "error": { "code": "TRANSACTION_NOT_FOUND", "message": "Transação não encontrada" } } ``` ### Erro: payload acima do teto (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "payload excede 32KB: evidência é registro, não arquivo" } } ``` ## Próximos passos - [Consultar evidências](https://doc.rapidchargeback.com/canais/evidence/consultar-evidencias/) - [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/) --- # Consultar evidências > Lista as evidências registradas numa transação, da mais antiga para a mais recente. Página: https://doc.rapidchargeback.com/canais/evidence/consultar-evidencias/ Lista as evidências registradas numa transação, da mais antiga para a mais recente. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/evidence?transaction_id= ``` ## Autenticação Basic Auth com `client_id:client_secret`. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ## Query params | Param | Tipo | Descrição | Obrigatório | |---|---|---|---| | `transaction_id` | string (UUID) | Transação cujas evidências você quer ver | Sim | Diferente do `POST`, aqui **não** existe busca por `transaction_ref`: a consulta é só pelo UUID da Rapid. ## Validações | Regra | Resposta | |---|---| | `transaction_id` ausente | `422 VALIDATION_ERROR`: *transaction_id é obrigatório* | | Credencial ausente ou inválida | `401 UNAUTHORIZED` | Transação de outra empresa, ou inexistente, devolve **lista vazia**, porque a consulta é filtrada pela sua empresa, não dá erro. ## Exemplo de requisição ```bash curl "https://api.rapidchargeback.com/api/v1/evidence?transaction_id=00000000-0000-0000-0000-000000000042" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ## Exemplos de resposta ### Sucesso (200) ```json { "data": [ { "id": "00000000-0000-0000-0000-0000000000e1", "type": "terms_acceptance", "payload": { "ip": "203.0.113.10", "accepted_at": "2026-04-01T15:29:40Z", "terms_version": "v3.2" }, "captured_at": "2026-04-01T15:29:41.000Z", "created_at": "2026-04-01T15:32:36.027Z" } ] } ``` | Campo | Descrição | |---|---| | `id` | ID da evidência | | `type` | O tipo informado no registro | | `payload` | O objeto que você enviou, como enviou. A ordem das chaves não é preservada | | `captured_at` | Quando o fato aconteceu, como você informou | | `created_at` | Quando a Rapid recebeu o registro | ### Sem evidências (200) ```json { "data": [] } ``` ### Erro: `transaction_id` ausente (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "transaction_id é obrigatório" } } ``` ## Próximos passos - [Registrar evidência](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/) - [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/) --- # Visão geral > Após receber um alerta via webhook, sua aplicação retorna um status para a Rapid informando o resultado da análise: Página: https://doc.rapidchargeback.com/callback/visao-geral/ Após receber um alerta via webhook, sua aplicação retorna um **status** para a Rapid informando o resultado da análise: - **Ethoca (Mastercard)**: obrigatório em até 24h. A resposta volta para o Ethoca e pode evitar que a disputa vire chargeback. - **Verifi RDR (Visa)**: opcional. O estorno já foi feito automaticamente; o status é só para sua organização interna. ## Fluxo resumido 1. Sua aplicação recebe o alerta via [webhook](https://doc.rapidchargeback.com/canais/webhook/visao-geral/) 2. Você analisa a transação no seu sistema 3. Você chama `PATCH /chargeback-alert/alerts/:id/status` com um dos três status válidos 4. A Rapid processa, armazena e (no caso Ethoca) reencaminha ao provedor Alternativamente, você pode atualizar o status diretamente pelo painel da Rapid (útil para operações manuais). ## Autenticação O callback usa **Basic Auth** com `client_id`/`client_secret`. Ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/). ## Status válidos | Status | Significado | |---|---| | `notfound` | Transação não foi encontrada no seu sistema | | `account_suspended` | Transação encontrada e já resolvida | | `other` | Transação encontrada, mas ainda não resolvida | Para prazos e regras de transição, ver [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/). ## Consultar alertas Se sua integração precisa buscar alertas (ex: confirmar se um alerta com determinado `provider_alert_id` chegou, ou paginar histórico), use o endpoint de listagem: ``` GET /api/v1/chargeback-alert/alerts ``` Aceita filtros por `status`, `provider_alert_id`, intervalo de datas, BIN e final do cartão. Útil quando você só tem o ID do provedor (Ethoca/Verifi) e precisa achar o ID interno da Rapid para atualizar o status. ## Próximos passos - [Consultar alertas](https://doc.rapidchargeback.com/callback/consultar-alertas/): listar alertas com filtros (inclui busca pelo seu `provider_alert_id`). - [Atualizar status](https://doc.rapidchargeback.com/callback/atualizar-status/): spec completa do endpoint de callback. --- # Atualizar status > Atualiza o status de um alerta recebido via webhook. Página: https://doc.rapidchargeback.com/callback/atualizar-status/ Atualiza o status de um alerta recebido via webhook. ## Endpoint ``` PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/:id/status ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) Content-Type: application/json ``` --- ## Parâmetro de URL | Parâmetro | Tipo | Descrição | |---|---|---| | `id` | string (UUID) | `alert_id` recebido no payload do webhook | --- ## Corpo da requisição | Campo | Tipo | Obrigatório | Descrição | |---|---|---|---| | `status` | string | Sim | Um dos três valores: `notfound`, `account_suspended`, `other` | --- ## Validações - `status` deve ser exatamente um dos três valores válidos, qualquer outro retorna `422` - O alerta deve pertencer à sua empresa: caso contrário retorna `404` - Status definitivos (`notfound`, `account_suspended`) não podem ser alterados depois de enviados, retorna erro se você tentar - O status `expired` é gerado automaticamente pelo sistema após 24h sem resposta (Ethoca) e não é enviado pelo cliente - A única transição permitida após resposta inicial é `other → account_suspended`, disponível por até 6 dias (Ethoca) Ver [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/) para o detalhamento completo. --- ## Exemplo de requisição As credenciais vêm de variáveis de ambiente (`RAPID_CLIENT_ID` e `RAPID_CLIENT_SECRET`), nunca escritas no código. **cURL** ```bash curl -X PATCH https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/00000000-0000-0000-0000-000000000099/status \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "status": "account_suspended" }' ``` **Node.js** ```javascript const credenciais = Buffer.from(`${process.env.RAPID_CLIENT_ID}:${process.env.RAPID_CLIENT_SECRET}`).toString('base64') const alertId = '00000000-0000-0000-0000-000000000099' const resposta = await fetch(`https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/${alertId}/status`, { method: 'PATCH', headers: { Authorization: `Basic ${credenciais}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'account_suspended' }), }) const corpo = await resposta.json() if (!resposta.ok) throw new Error(`${resposta.status} ${corpo.error.code}: ${corpo.error.message}`) console.log('Status atualizado:', corpo.data.status) ``` **Python** ```python import os import requests alert_id = "00000000-0000-0000-0000-000000000099" resposta = requests.patch( f"https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts/{alert_id}/status", auth=(os.environ["RAPID_CLIENT_ID"], os.environ["RAPID_CLIENT_SECRET"]), json={"status": "account_suspended"}, timeout=30, ) corpo = resposta.json() if not resposta.ok: raise RuntimeError(f"{resposta.status_code} {corpo['error']['code']}: {corpo['error']['message']}") print("Status atualizado:", corpo["data"]["status"]) ``` **PHP** ```php 'PATCH', CURLOPT_USERPWD => getenv('RAPID_CLIENT_ID') . ':' . getenv('RAPID_CLIENT_SECRET'), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['status' => 'account_suspended']), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $bruto = curl_exec($ch); if ($bruto === false) { throw new RuntimeException('Falha de rede: ' . curl_error($ch)); } $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $corpo = json_decode($bruto, true); if ($status >= 400) { throw new RuntimeException("$status {$corpo['error']['code']}: {$corpo['error']['message']}"); } echo 'Status atualizado: ', $corpo['data']['status'], PHP_EOL; ``` --- ## Exemplos de resposta ### Sucesso ```json { "data": { "id": "00000000-0000-0000-0000-000000000099", "status": "account_suspended", "updated_at": "2026-04-14T14:30:00.000Z" } } ``` ### Alerta não encontrado ```json { "error": { "code": "ALERT_NOT_FOUND", "message": "Alert not found" } } ``` ### Empresa bloqueada ```json { "error": { "code": "COMPANY_BLOCKED", "message": "Company is blocked" } } ``` ### Status fora dos valores válidos Quando o `status` enviado não é um dos três valores aceitos, a validação do corpo falha antes do processamento e retorna `VALIDATION_ERROR` (HTTP 422): ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid enum value. Expected 'notfound' | 'account_suspended' | 'other', received 'foo'" } } ``` ### Transição não permitida Quando o `status` é válido mas a transição não é permitida (prazo, expiração ou status já definitivo), o código é `ALERT_INVALID_STATUS` (HTTP 422). A mensagem indica qual dos três cenários ocorreu: ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Alert has expired" } } ``` ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Response deadline has passed" } } ``` ```json { "error": { "code": "ALERT_INVALID_STATUS", "message": "Alert already has a definitive status" } } ``` Esses três ocorrem apenas em alertas Ethoca, Verifi RDR não tem regras de prazo (ver [Regras e prazos](https://doc.rapidchargeback.com/produtos/alerta/regras-e-prazos/)). --- ## Clientes do sistema anterior Se você integrava com a versão anterior da plataforma, o endpoint antigo continua disponível como alias: ``` POST https://api.rapidchargeback.com/chargeback-alert/update/status ``` Esse alias aceita o body no formato antigo `{ "alert_id": "...", "status": "..." }` e tanto Basic Auth quanto os headers `clientid`/`clientkey`. Como no sistema anterior, **`alert_id` é o ID do alerta no provedor** (o mesmo `alert_id` que você recebe no webhook em formato `legacy` e usa em `POST /chargeback-alert/get`); o UUID da Rapid também é aceito. A resposta mantém o formato antigo `{ "success": true, "message": "...", "status": "..." }` e acrescenta `data` com o objeto do endpoint canônico. Erros seguem o envelope novo (`422 VALIDATION_ERROR` / `ALERT_INVALID_STATUS`, `404 ALERT_NOT_FOUND`). **Recomendação:** migre para `PATCH /chargeback-alert/alerts/:id/status`. O alias será removido no futuro quando não houver mais chamadas. --- # Consultar alertas > Lista os alertas de chargeback da sua empresa, com filtros opcionais e paginação. Página: https://doc.rapidchargeback.com/callback/consultar-alertas/ Lista os alertas de chargeback da sua empresa, com filtros opcionais e paginação. ## Endpoint ``` GET https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts ``` ## Autenticação ``` Authorization: Basic base64(client_id:client_secret) ``` --- ## Query params Todos opcionais. Combine os que precisar. | Param | Tipo | Default | Descrição | |---|---|---|---| | `page` | int (≥ 1) | `1` | Página da paginação | | `per_page` | int (1–100) | `20` | Itens por página | | `status` | enum | - | `pending`, `notfound`, `account_suspended`, `other`, `expired` | | `provider_alert_id` | string | - | ID do alerta no sistema do provedor (Ethoca/Verifi). Único dentro de cada provedor; normalmente devolve 0 ou 1 item | | `date_from` | YYYY-MM-DD | - | Filtra por `received_at >= date_from` (00:00:00) | | `date_to` | YYYY-MM-DD | - | Filtra por `received_at <= date_to` (23:59:59) | | `card_bin` | string (6-8 dígitos) | - | BIN do cartão | | `card_last4` | string (4 dígitos) | - | Final do cartão | --- ## Buscar pelo seu próprio ID (do provedor) Os alertas têm dois IDs: - **`id`**: UUID que a Rapid gera quando recebe o alerta. É o que você precisa para atualizar status (`PATCH /chargeback-alert/alerts/:id/status`). - **`provider_alert_id`**: ID que o Ethoca ou Verifi gerou. É o que você provavelmente já tem armazenado nos seus sistemas, vindo do payload original do provedor. Se você só tem o `provider_alert_id` e precisa achar o nosso `id` (ou os dados do alerta), use este endpoint com o filter: ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "provider_alert_id=ALERT-ETHOCA-12345" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` O `provider_alert_id` é único dentro de cada provedor, então a resposta normalmente terá 1 item em `data`. Para uma chave estável e globalmente única, use o `id` (UUID) que vem na resposta. --- ## Exemplos ### Listar últimos alertas pendentes ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "status=pending" \ --data-urlencode "per_page=50" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Alertas dos últimos 7 dias ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "date_from=2026-04-16" \ --data-urlencode "date_to=2026-04-23" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` ### Buscar por cartão (BIN + final) ```bash curl -G "https://api.rapidchargeback.com/api/v1/chargeback-alert/alerts" \ --data-urlencode "card_bin=424242" \ --data-urlencode "card_last4=4242" \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" ``` --- ## Resposta ### Sucesso ```json { "data": [ { "id": "00000000-0000-0000-0000-000000000099", "company_id": "00000000-0000-0000-0000-0000000000c1", "merchant_id": "00000000-0000-0000-0000-000000000001", "merchant_enrollment_id": "00000000-0000-0000-0000-0000000000aa", "provider": "ethoca_alerts", "provider_alert_id": "ALERT-ETHOCA-12345", "amount": "150.00", "currency": "USD", "card_last4": "4242", "card_bin": "424242", "transaction_date": "2026-04-01T00:00:00.000Z", "descriptor": "LOJA EXEMPLO", "arn": null, "caid": null, "auth_code": "AUTH999", "alert_type": "fraud", "reason_code": "10.4", "issuer": "BANK XYZ", "status": "pending", "received_at": "2026-04-23T10:15:00.000Z", "expires_at": "2026-04-24T10:15:00.000Z", "created_at": "2026-04-23T10:15:00.000Z", "updated_at": "2026-04-23T10:15:00.000Z" } ], "meta": { "page": 1, "per_page": 20, "total": 42, "total_pages": 3 } } ``` ### Sem resultados ```json { "data": [], "meta": { "page": 1, "per_page": 20, "total": 0, "total_pages": 0 } } ``` ### Validação inválida (ex: `card_bin` não-numérico) ```json { "error": { "code": "VALIDATION_ERROR", "message": "card_bin must be 6-8 digits" } } ``` --- ## Clientes do sistema anterior Quem já integrava com o sistema anterior continua podendo consultar um alerta pelo endpoint antigo, mantido como alias: ``` POST https://api.rapidchargeback.com/chargeback-alert/get ``` Note que este alias **não** tem o prefixo `/api/v1`. Ele aceita Basic Auth ou os headers `clientid`/`clientkey`. ### Corpo da requisição Informe **um** dos dois: | Campo | Tipo | Descrição | |---|---|---| | `alert_id` | string | **ID do alerta no provedor**, o mesmo que você recebe no webhook em formato `legacy`. O UUID da Rapid também é aceito | | `authorization_code` | string | Código de autorização da transação | Se os dois vierem, `alert_id` tem prioridade. Quando mais de um alerta casa (por exemplo, dois alertas com o mesmo código de autorização), volta o mais recente. ### Exemplo ```bash curl -X POST https://api.rapidchargeback.com/chargeback-alert/get \ -H "Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=" \ -H "Content-Type: application/json" \ -d '{ "alert_id": "ETH-99887766" }' ``` ### Resposta `200` com `success` e `data`, onde `data` é o **mesmo corpo do webhook em formato `legacy`** (ver [Formato legacy](https://doc.rapidchargeback.com/canais/webhook/payload/#formato-legacy)): ```json { "success": true, "data": { "alert_id": "ETH-99887766", "merchant": "Minha Loja", "provider": "ethoca", "descriptor": "LOJA EXEMPLO", "transaction_date": "2026-04-01T00:00:00.000Z", "currency": "USD", "amount": 150, "card_number": "424242******4242", "created_at": "2026-04-14T12:00:00.000Z" } } ``` A resposta vem com `Cache-Control: no-store`, como no sistema anterior. ### Erros deste alias Para manter a paridade com o sistema anterior, os erros deste endpoint usam o envelope **antigo** (`{"error": "texto"}`), e não o envelope novo com `code`: | Situação | Resposta | |---|---| | Nem `alert_id` nem `authorization_code` | `400` `{"error": "Informe alert_id ou authorization_code."}` | | Nenhum alerta seu corresponde | `404` `{"error": "Alerta não encontrado."}` | Em integrações novas, prefira [`GET /api/v1/chargeback-alert/alerts/:id`](#endpoint), que usa o envelope de erro padrão da API. --- ## Notas - **`provider`** vem como string slug (`"ethoca_alerts"` ou `"verifi_rdr"`), igual ao payload do webhook outbound (formato `v2`). - Os campos da resposta são exatamente os do exemplo acima, mais `installment_number` e `installment_count` (parcelamento, os mesmos do webhook) e `provider_id`, um identificador interno mantido por compatibilidade: use `provider`. - Datas do tipo "só data" (`transaction_date`) chegam como `"2026-04-01T00:00:00.000Z"`. - **Ordenação:** sempre por `received_at` decrescente (mais recente primeiro). Não há parâmetro de ordenação custom. - **Auth, rate limit, códigos de erro:** ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/) e [Códigos de resposta](https://doc.rapidchargeback.com/referencia/codigos-de-resposta/). --- # Autenticação > Esta página é referência técnica para todos os mecanismos de autenticação da Rapid. Página: https://doc.rapidchargeback.com/referencia/autenticacao/ Esta página é referência técnica para todos os mecanismos de autenticação da Rapid. ## Sua aplicação chamando a Rapid Use **Basic Auth** com `client_id` como username e `client_secret` como password. ``` Authorization: Basic base64(client_id:client_secret) ``` Endpoints que usam esse método: - [API de Transações](https://doc.rapidchargeback.com/canais/transactions/visao-geral/): criar, consultar, atualizar, deletar transações - [Merchants](https://doc.rapidchargeback.com/canais/merchants/listar-merchants/): listar os merchants da empresa - [Consulta de alertas](https://doc.rapidchargeback.com/callback/consultar-alertas/) e [callback de status](https://doc.rapidchargeback.com/callback/atualizar-status/) - [API de Evidência](https://doc.rapidchargeback.com/canais/evidence/visao-geral/) e captura server-side (produto Disputa) ### Credenciais | Credencial | Descrição | |---|---| | `client_id` | ID da sua empresa (gerado no painel) | | `client_secret` | Chave secreta (gerada no painel, tratar como senha) | ### Exemplo de header ``` Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ= ``` Onde o valor base64 decodifica para `client_id:client_secret`. ### Segurança - Use sempre HTTPS - Não inclua `client_secret` em código frontend, repositórios públicos ou logs - Rotacione o `client_secret` se suspeitar de exposição, geração de novas credenciais acontece no painel --- ## Rapid chamando sua aplicação (webhook) No formato `v2` a Rapid assina cada webhook com **HMAC-SHA256** e envia a assinatura e o timestamp nos headers: ``` X-Webhook-Signature: sha256= X-Webhook-Timestamp: 1790000000 ``` O conteúdo assinado **não é só o corpo**: é `${X-Webhook-Timestamp}.${corpo_bruto}`, o timestamp, um ponto e o corpo exatamente como chegou. Calcular o HMAC só sobre o corpo dá um valor diferente e toda requisição é recusada. O timestamp entra na conta para impedir que um POST capturado seja reenviado depois (rejeite os que estiverem fora de uma janela de 5 minutos). A chave de assinatura (`secret`) é **gerada pela Rapid** quando você cadastra o webhook e aparece **uma única vez** no painel, em `Configurações > Webhook`. Não é você quem escolhe e não há como consultá-la depois: se perder, peça uma nova ao suporte. O passo a passo de validação, com exemplos em Node.js e Python, está em [Autenticação do webhook](https://doc.rapidchargeback.com/canais/webhook/autenticacao/). ### Formato `legacy` Contas migradas do sistema anterior recebem os webhooks no formato `legacy`, que **não é assinado**. Nele a autenticação são os headers que o sistema antigo já mandava: ``` clientid: clientkey: ``` Esses dois headers existem **só no `legacy`**. No `v2` eles não são enviados: `clientkey` é a sua credencial de acesso à API, e mandá-la em toda entrega a exporia no seu endpoint e nos seus logs sem necessidade, já que no `v2` quem autentica é a assinatura. Para saber em qual formato está a sua conta, veja [Payload](https://doc.rapidchargeback.com/canais/webhook/payload/#formato-legacy). --- # Códigos de resposta > Referência dos códigos HTTP usados por toda a API da Rapid. Página: https://doc.rapidchargeback.com/referencia/codigos-de-resposta/ Referência dos códigos HTTP usados por toda a API da Rapid. ## Códigos de sucesso | Código | Significado | |---|---| | 200 | Sucesso com corpo | | 201 | Recurso criado | | 204 | Sucesso sem corpo (ex: `DELETE`) | ## Códigos de erro do cliente | Código | Significado | |---|---| | 400 | Corpo que não é JSON válido (`INVALID_JSON`) | | 401 | Credenciais ausentes ou inválidas | | 403 | Empresa bloqueada | | 404 | Recurso não encontrado | | 409 | Conflito (duplicata, recurso imutável) | | 413 | Corpo acima do tamanho máximo (`PAYLOAD_TOO_LARGE`) | | 422 | Erro de validação | | 429 | Muitas requisições (rate limit) | ## Códigos de erro do servidor | Código | Significado | |---|---| | 500 | Erro interno (`INTERNAL_ERROR`), retentativa recomendada | --- ## Formato do corpo de erro Toda resposta de erro tem a estrutura: ```json { "error": { "code": "CODIGO_SEMANTICO", "message": "Descrição legível do erro" } } ``` ## Códigos semânticos mais comuns | Código | HTTP | Uso | |---|---|---| | `INVALID_JSON` | 400 | O corpo não é um JSON válido | | `UNAUTHORIZED` | 401 | Credenciais ausentes ou inválidas | | `COMPANY_BLOCKED` | 403 | Empresa bloqueada | | `VALIDATION_ERROR` | 422 | Um ou mais campos inválidos | | `NOT_FOUND` | 404 | O endereço não existe na API (caminho com erro de digitação, barra sobrando no fim) | | `TRANSACTION_NOT_FOUND` | 404 | Transação inexistente | | `TRANSACTION_DUPLICATE` | 409 | `external_source` + `external_id` já cadastrado | | `TRANSACTION_IMMUTABLE` | 409 | Transação já utilizada, não pode ser modificada | | `MERCHANT_NOT_FOUND` | 404 | Merchant inexistente | | `ALERT_NOT_FOUND` | 404 | Alerta inexistente | | `ALERT_INVALID_STATUS` | 422 | Status fora do conjunto permitido | | `PAYLOAD_TOO_LARGE` | 413 | Corpo acima do limite: 1 MB por requisição, 5 MB no [envio em lote](https://doc.rapidchargeback.com/canais/transactions/envio-em-lote/) | | `RATE_LIMIT_EXCEEDED` | 429 | Limite de requisições excedido (ver abaixo) | | `INTERNAL_ERROR` | 500 | Erro inesperado no servidor | ## Rate limit Todas as rotas compartilham um limite de **100 requisições por minuto por IP**, inclusive as que respondem `401` por credencial inválida. A exceção é o [envio de evento pelo navegador](https://doc.rapidchargeback.com/canais/capture/enviar-evento-navegador/), que tem teto próprio de 120 por minuto e não conta nos 100. Ao ultrapassar, a API retorna: ``` HTTP/1.1 429 Too Many Requests Retry-After: 15 X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 15 ``` ```json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded, retry in 15 seconds" } } ``` **Use o `Retry-After`.** Ele diz, em segundos, quanto falta para a janela virar, e a mensagem repete o mesmo número. Esperar exatamente isso é melhor que chutar: espera progressiva cega pode tentar antes da hora (e tomar outro `429`) ou esperar mais que o necessário. Os headers `X-RateLimit-*` vêm em **todas** as respostas, não só no `429`, então você pode se antecipar: quando `X-RateLimit-Remaining` chegar perto de zero, segure o envio em vez de esperar o erro. Em envio de volume, prefira o [envio em lote](https://doc.rapidchargeback.com/canais/transactions/envio-em-lote/), que manda até 1000 transações numa requisição e gasta uma unidade do limite. ## Retry em erros 5xx Erros `5xx` geralmente são transitórios. Retente aumentando o intervalo entre as tentativas. Nunca retente `4xx`: eles indicam erro no seu lado e vão falhar de novo. --- # Exemplos canônicos > Os IDs, valores e credenciais fixos de todos os exemplos da documentação, para que o exemplo de uma página se conecte ao da outra. Página: https://doc.rapidchargeback.com/referencia/exemplos-canonicos/ Valores fixos usados em todos os exemplos da documentação. Use-os como referência ao ler curl samples e payloads, os mesmos IDs aparecem em páginas diferentes intencionalmente, para que um exemplo de transação se conecte a um exemplo de alerta. ## Valores padrão ### IDs gerados pela Rapid Todos seguem o mesmo molde, `00000000-0000-0000-0000-` mais um sufixo, para ficar óbvio que são de exemplo. Um ID real nunca tem esse formato. | O que identifica | Campo | Valor | |---|---|---| | Transação | `id`, `transaction_id` | `00000000-0000-0000-0000-000000000042` | | Merchant | `merchant_id` | `00000000-0000-0000-0000-000000000001` | | Alerta | `alert_id` | `00000000-0000-0000-0000-000000000099` | | Disputa | `dispute_id` | `00000000-0000-0000-0000-0000000000d1` | | Evidência | `id` | `00000000-0000-0000-0000-0000000000e1` | | Sua empresa | `company_id` | `00000000-0000-0000-0000-0000000000c1` | | Credenciamento do merchant | `merchant_enrollment_id` | `00000000-0000-0000-0000-0000000000aa` | A transação `…042` é a mesma em todas as páginas: é a que você cria em [Criar transação](https://doc.rapidchargeback.com/canais/transactions/criar-transacao/), consulta, atualiza e remove nas páginas seguintes, e é para ela que a [evidência](https://doc.rapidchargeback.com/canais/evidence/registrar-evidencia/) aponta. ### Valores da transação | Campo | Valor | |---|---| | `external_id` (seu ID da transação) | `TXN-2026-001` | | `amount` | `150.00` | | `currency` | `USD` | | `transaction_date` | `2026-04-01T15:30:00Z` | | `card_last4` | `4242` | | `card_bin` | `424242` | | `descriptor` | `LOJA EXEMPLO` | | `arn` | `74537119547024600128228` | | URL de webhook do cliente | `https://seu-sistema.com/webhooks/rapid` | | Base URL da API | `https://api.rapidchargeback.com/api/v1` | ## Header de Basic Auth Todos os exemplos usam o mesmo header codificado: ``` Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ= ``` O valor base64 decodifica para `client_id:client_secret`. No seu código, substitua pelas credenciais reais da sua empresa. ## Nomes e endereços de exemplo - Cliente: `João Silva`, email `joao@exemplo.com` - Endereço: `Rua das Flores, 123, São Paulo, SP, 01001000, BRA` Estes valores não têm significado especial, são apenas placeholders consistentes entre páginas. --- # Ferramentas para devs > A documentação no seu assistente de IA (MCP), em Markdown e em llms.txt, e a coleção do Postman com todas as requisições prontas. Página: https://doc.rapidchargeback.com/referencia/ferramentas-para-devs/ Atalhos para integrar mais rápido: a documentação dentro do seu assistente de IA e as requisições prontas para testar. ## MCP O servidor MCP deixa o seu assistente de IA (Claude, Cursor, VS Code, ChatGPT e outros) **buscar e ler esta documentação** enquanto você programa. Em vez de responder de memória, ele consulta a página certa e usa os nomes de campo, os valores aceitos e os códigos de erro reais. ``` https://doc.rapidchargeback.com/mcp/ ``` É só leitura da documentação pública: não pede credencial, não acessa a sua conta na Rapid e não chama a API. ### Claude Code ```bash claude mcp add --transport http rapid-docs https://doc.rapidchargeback.com/mcp/ ``` ### Cursor Em `~/.cursor/mcp.json` (ou `.cursor/mcp.json` no projeto): ```json { "mcpServers": { "rapid-docs": { "url": "https://doc.rapidchargeback.com/mcp/" } } } ``` ### VS Code Em `.vscode/mcp.json` no projeto: ```json { "servers": { "rapid-docs": { "type": "http", "url": "https://doc.rapidchargeback.com/mcp/" } } } ``` ### Claude (app e web) Em **Configurações > Conectores > Adicionar conector personalizado**, informe o nome `Rapid` e a URL acima. ### Outros clientes Qualquer cliente MCP com transporte HTTP funciona com a mesma URL. ### O que o assistente consegue fazer | Ferramenta | O que faz | |---|---| | `search_docs` | Busca por assunto, nome de campo, código de erro, header ou caminho de endpoint. Corrige erro de digitação | | `get_page` | Lê uma página inteira em Markdown | | `list_pages` | Lista todas as páginas, na ordem de leitura | Exemplo de pedido: *"Usando a documentação da Rapid, escreva o handler do webhook de alerta em Node.js, validando a assinatura."* ## Copiar uma página Toda página tem o botão **Copiar página**, ao lado do título. Ele copia a página em Markdown, o formato que se cola num assistente de IA sem perder tabela nem bloco de código. O menu ao lado do botão abre a mesma página direto no ChatGPT ou no Claude. Cada página também existe em Markdown no endereço dela, trocando a barra final por `.md`: ``` https://doc.rapidchargeback.com/canais/webhook/payload.md ``` ## llms.txt Para ferramentas que leem a documentação de uma vez: | Arquivo | Conteúdo | |---|---| | [`/llms.txt`](https://doc.rapidchargeback.com/llms.txt) | Índice de todas as páginas, com descrição e link para o Markdown | | [`/llms-full.txt`](https://doc.rapidchargeback.com/llms-full.txt) | A documentação inteira num arquivo só | ## Coleção do Postman Todas as requisições de exemplo desta documentação, organizadas pelas seções do menu. 1. Baixe a [coleção](https://doc.rapidchargeback.com/rapid.postman_collection.json). 2. No Postman, **Import** e escolha o arquivo. 3. Nas variáveis da coleção, preencha `client_id` e `client_secret` com as credenciais do painel (ver [Autenticação](https://doc.rapidchargeback.com/referencia/autenticacao/)). A autenticação Basic já vem configurada na coleção. Os IDs dos exemplos são fictícios (ver [Exemplos canônicos](https://doc.rapidchargeback.com/referencia/exemplos-canonicos/)): troque pelos da sua conta antes de enviar. A coleção é gerada dos exemplos das páginas, então acompanha a documentação.