Documentação
Um script no navegador, uma chamada de API do seu servidor. Tudo o que você precisa para entrar no ar, em uma única página.
Início rápido
Você precisa da sua chave pública (pk_...) para o navegador e da sua chave secreta (sk_...) para o servidor. As duas ficam no painel, em Sites e chaves.
1. Adicione o script
Coloque esta tag nas páginas onde os usuários se cadastram, entram, clicam em ofertas ou pedem um saque. Ele se inicializa sozinho a partir de data-key
<script src="https://cashoutguard.com/v1/agent.js" data-key="pk_live_YOUR_PUBLIC_KEY" async></script>
2. Colete e envie o request_id ao seu servidor
Chame collect() no momento que importa, com o nome do evento. Ele resolve para { request_id, visitor_id }
const { request_id } = await CashoutGuard.collect({ event: 'cashout' });
collect() nunca rejeita. Em caso de falha (bloqueio, offline, timeout) ele resolve com request_id: null e uma string de erro. Envie o formulário mesmo assim e deixe o seu servidor decidir.
3. Peça uma decisão a partir do seu servidor
Faça POST do evento para /v1/evaluate com a sua chave secreta no header Authorization: Bearer sk_live_...
Nunca coloque a chave secreta em código de navegador ou em um app mobile. Só o seu servidor deve chamar /v1/evaluate.
Requisição evaluate
POST https://cashoutguard.com/v1/evaluate pontua um evento de uma conta, vincula esse evento ao dispositivo, à rede e ao endereço de pagamento, e retorna uma decisão. Envie JSON.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
event | string | Obrigatório | signup, login, offer_click, conversion, cashout ou custom. |
account_id | string | Obrigatório | O ID do seu usuário, até 191 caracteres. Use um ID opaco, não um e-mail. |
request_id | string | Opcional | Vem do collect() no navegador. Válido por 1 hora. Sem ele, só temos os dados de rede. |
ip | string | Opcional | O IP do usuário. Só é necessário quando você não tem um request_id, por exemplo em postbacks. |
email | string | Opcional | Armazenado como hash. Detecta domínios descartáveis e e-mails compartilhados entre contas. |
payout_address | string | Opcional | E-mail do PayPal, carteira ou conta que recebe o dinheiro. Armazenado como hash. |
payout_method | string | Opcional | Texto livre, como paypal, usdt ou giftcard. |
amount | number | Opcional | Valor do saque ou da conversão. |
currency | string | Opcional | Código da moeda, por exemplo USD. Padrão USD para saques. |
offer_id | string | Opcional | ID da oferta, para offer_click e conversion. Usado na velocidade de ofertas. |
offer_country | string | Opcional | País pelo qual a oferta paga (código ISO, ex. US), em conversões. Um usuário em outro país é marcado. |
geo_country | string | Opcional | Sua própria geolocalização do IP do usuário (código ISO). Se divergir da nossa, o IP provavelmente é uma saída de proxy. |
transaction_id | string | Opcional | ID de transação da rede para uma conversão. Usado para pegar duplicatas. |
offer_name | string | Opcional | Título da oferta como seus usuários o veem. Aparece em todo o painel no lugar do id. |
click_id | string | Opcional | Seu id de clique. Envie o mesmo valor no offer_click e na conversão para vinculá-los. |
source | string | Opcional | De onde veio o evento, por exemplo o nome da offerwall ou da rede. |
meta | object | Opcional | Até 20 campos de texto extras salvos com o evento (por exemplo sub ids). |
Resposta
A resposta tem sempre o mesmo formato. Campos que não se aplicam vêm como null.
scorevai de 0 a 100. Os motivos são combinados para que vários sinais médios somem sem passar de 100.reasonslista cada sinal disparado, do mais forte para o mais fraco, com seu peso, detalhes e um rótulo em inglês simples que você pode mostrar como está.device.confidenceindica o quão único o dispositivo parece. Fingerprints podem ser falsificados, então nunca afirmamos certeza.linked_accountslista outras contas que compartilham dispositivo, endereço de pagamento ou e-mail com esta.cashoutsó vem preenchido em eventos de cashout e informa o status na sua fila de revisão.
Decisões e ações
Aja com base no campo action, não em decision. Os limites abaixo são os padrões e podem ser alterados por site no painel.
| Decisão | Pontuação (padrão) | action no modo sombra | action no modo ativo | O que fazer |
|---|---|---|---|---|
allow | 0-49 | allow | allow | Siga normalmente. |
review | 50-79 | allow | review | Retenha o saque ou peça uma verificação extra. Ele aparece na sua fila de revisão. |
block | 80-100 | allow | block | Interrompa a ação. Congele o saldo ou recuse o cadastro. |
No modo sombra o action é sempre allow, então o mesmo código pode ir para produção com segurança antes de você começar a bloquear. Quando mudar para o modo ativo, nada no seu código muda.
Tipos de evento
Envie os eventos que você tiver. Cadastro e saque são os mais importantes; as conversões alimentam as checagens de velocidade de ofertas.
| Evento | Quando enviar | O que detecta |
|---|---|---|
signup | Conta criada | Multicontas, bots, cadastros com VPN, e-mails descartáveis |
login | Login bem-sucedido | Compartilhamento de conta, mudanças de país, dispositivos novos |
offer_click | Usuário abre uma oferta | Inicia o cronômetro da velocidade de ofertas |
conversion | Postback do offerwall ou da rede | Ofertas concluídas rápido demais, transações duplicadas, picos de conversão |
cashout | Usuário pede um saque | Endereços de pagamento compartilhados, velocidade de saques, saques de contas novas |
custom | Qualquer outra coisa que você queira pontuar | Sinais de dispositivo e de rede |
Offerwalls e postbacks
As conversões de offerwall chegam por postback, de servidor para servidor, sem navegador. O CashoutGuard vincula cada conversão ao clique que a iniciou, então ela é avaliada com o dispositivo e a rede desse clique.
1. Quando o usuário abre uma oferta
Colete no navegador e envie um offer_click com a oferta e seu id de clique.
2. Quando o postback chega
Envie uma conversion do seu handler de postback com o mesmo account_id e click_id. Não precisa de request_id. Envie o IP do usuário se a offerwall fornecer.
As conversões são verificadas para: concluída rápido demais para a oferta, conversão sem clique, clique e conversão de países diferentes, ganhos muito acima do dia normal da conta e ids de transação duplicados.
Redes de offerwall
Se você opera uma rede com muitos publishers, envie ids de conta que incluam o publisher e ative o "Modo rede de offerwall" em Sites. Assim as contas só são vinculadas dentro do mesmo publisher, porque é normal uma pessoa usar vários sites dos seus publishers. Formato: publisher_id:user_id
Catálogo de ofertas
POST /v1/offers envia os nomes das suas ofertas (até 1.000 por chamada). Eventos passados e futuros mostram o nome real mesmo quando trazem só o id.
Códigos de motivo
Estes códigos aparecem em reasons[].code. Mostre o texto aos seus moderadores; use o código na sua lógica.
| Código | Significado | Grupo | Peso |
|---|---|---|---|
ip_tor | Nó de saída Tor | Rede | 60 |
ip_vpn | Conexão VPN | Rede | 45 |
ip_datacenter | IP de datacenter / hospedagem | Rede | 40 |
timezone_mismatch | Fuso horário do navegador não bate com a localização do IP | Rede | 20 |
webrtc_ip_leak | IP real vazou em outro país | Rede | 30 |
ip_multi_timezone | Mesmo IP com muitos fusos horários diferentes (saída de proxy) | Rede | 50 |
proxy_farm_ip | Várias contas num IP, todas com o mesmo relógio estrangeiro (proxy partilhado) | Rede | 60 |
provider_rotation | Muitos fornecedores de internet em poucos dias, com relógio estrangeiro (proxy residencial rotativo) | Rede | 45 |
privacy_relay | iCloud Private Relay (recurso de privacidade) | Rede | 5 |
proxy_headers | A requisição veio por um proxy | Rede | 20 |
geo_sources_disagree | As fontes de geolocalização divergem | Rede | 45 |
ip_shared_with_accounts | Mesmo IP usado por outras contas hoje | Rede | 25 |
country_changed | País mudou | Rede | 15 |
impossible_travel | Viagem impossível: IPs de dois países distantes em poucas horas | Rede | 50 |
locale_country_mismatch | Idioma do navegador de outro país | Rede | 30 |
phone_country_mismatch | Telefone de outro país que o IP | Rede | 20 |
ip_flagged_on_network | IP bloqueado em outros sites | Rede | 25 |
device_shared_with_accounts | Dispositivo compartilhado com outras contas | Dispositivo | 55 |
automation_detected | Bot ou ferramenta de automação | Dispositivo | 70 |
auto_clicker | Auto-clicker no celular | Dispositivo | 55 |
scripted_behavior | Uso da página por script | Dispositivo | 45 |
emulator_or_vm | Emulador ou máquina virtual | Dispositivo | 45 |
browser_tampering | Navegador adulterado / falsificado | Dispositivo | 35 |
device_rooted | Celular com root | Dispositivo | 25 |
incognito | Navegação anônima | Dispositivo | 10 |
device_spoofed | Modelo de celular falso | Dispositivo | 55 |
emulator_profile | Perfil padrão de emulador | Dispositivo | 60 |
cloud_phone | Celular na nuvem | Dispositivo | 60 |
phone_farm_display | Tela de fazenda de celulares | Dispositivo | 45 |
device_market_mismatch | Celular só da China no exterior | Dispositivo | 25 |
storage_cleared_reappeared | Limpou os cookies e voltou | Dispositivo | 15 |
no_device_data | Nenhum dado do dispositivo enviado | Dispositivo | 15 |
request_reused | Token do dispositivo reutilizado por outra conta | Dispositivo | 40 |
device_farm_proxy | Fazenda de celulares com proxies residenciais | Dispositivo | 85 |
device_clones | Clones de dispositivo: um telefone que reinicia sua identidade para se passar por muitas contas novas numa rede | Dispositivo | 55 |
payout_address_shared | Endereço de pagamento usado por outras contas | Conta | 70 |
email_disposable | E-mail descartável | Conta | 25 |
email_invalid | E-mail que não pode receber mensagens (domínio de e-mail inexistente) | Conta | 35 |
email_shared | Mesmo e-mail de outra conta | Conta | 50 |
phone_shared | Telefone compartilhado com outras contas | Conta | 50 |
phone_voip | Telefone VoIP ou virtual | Conta | 40 |
phone_invalid | Telefone inválido | Conta | 30 |
many_devices_per_account | Dispositivos demais em uma só conta | Conta | 20 |
flagged_on_network | Marcado em outros sites protegidos pelo CashoutGuard | Conta | 45 |
face_same_person | Mesmo rosto que outras contas | Conta | 0 |
offer_completed_too_fast | Oferta concluída rápido demais para ser real | Comportamento | 40 |
slow_after_click | Converteu muito depois do clique | Comportamento | 0 |
conversion_velocity | Conversões demais por hora | Comportamento | 30 |
conversion_without_click | Conversão sem clique na sua offerwall | Comportamento | 35 |
click_conversion_country_mismatch | Clique em um país, conversão em outro | Comportamento | 30 |
offer_country_mismatch | O país da oferta difere do usuário | Comportamento | 45 |
click_velocity | Cliques demais em ofertas em poucos minutos | Comportamento | 35 |
earnings_spike | Ganhos muito acima de um usuário normal | Comportamento | 30 |
source_high_reversals | Fonte com muitos estornos | Comportamento | 45 |
offer_high_reversals | Oferta com muitos estornos | Comportamento | 35 |
duplicate_transaction | ID de transação duplicado | Comportamento | 60 |
offer_repeated_other_publisher | Mesma oferta já feita por outro publisher | Comportamento | 85 |
offer_repeated_other_account | Mesma oferta já feita por outra conta neste aparelho | Comportamento | 85 |
offer_farm_burst | Vaga de quinta: muitas contas novas com dispositivos de quinta nesta oferta em poucas horas | Comportamento | 30 |
signup_burst | Rajada de cadastros: várias contas cadastradas com segundos de diferença a partir de IPs diferentes | Comportamento | 25 |
face_check_required | Falta a verificação facial | Comportamento | 0 |
face_check_failed | Verificação facial reprovada | Comportamento | 0 |
publisher_farm_wave | Vaga de quinta do seu publisher: a maioria das contas novas que enviou para esta oferta vinha de telemóveis na nuvem ou emuladores | Comportamento | 55 |
cashout_velocity | Saques demais por dia | Comportamento | 30 |
new_account_cashout | Saque de uma conta recém-criada | Comportamento | 20 |
blocklisted | Na sua lista de bloqueio | Suas listas | 100 |
Os pesos são combinados com um noisy-OR: score = 100 x (1 - produto de (1 - weight/100)). Dois sinais de 40 dão 64, não 80. Uma ocorrência na lista de bloqueio sempre dá 100.
Webhooks
Defina um URL de webhook no painel. Enviamos um POST por cada evento classificado como block (event.blocked), quando uma conta passa a block (account.blocked) e quando a sua equipa decide um levantamento (cashout.decided). Ignore os tipos que não usa.
Cada requisição é assinada com o seu segredo de webhook. O HMAC-SHA256 em hex do corpo bruto vem no header X-CashoutGuard-Signature
Responda com qualquer status 2xx. Entregas com falha são tentadas de novo até 5 vezes: após 10 segundos, 1 minuto, 5 minutos e 15 minutos.
Status da conta
GET /v1/accounts/{account_id} retorna a visão de risco atual de uma conta sem criar um evento.
POST /v1/accounts/{account_id}/status permite que as suas próprias ferramentas de moderação mudem o status de uma conta.
active: Pontuação normal.allowlisted: As pontuações ficam limitadas abaixo do limite de revisão. Para usuários de confiança e para a equipe.blocked: Todo evento retorna block com pontuação 100.
Estornos e precisão
POST /v1/outcomes informa o que aconteceu com as conversões depois de pontuadas: estornadas pelo offerwall ou anunciante (chargeback) ou confirmadas como válidas. Cruzamos seus ids com as conversões e medimos o motor no seu próprio tráfego na página Precisão.
Sem código: envie na página Precisão o export mensal de estornos dos seus offerwalls (CSV ou Excel). Encontramos a coluna de ids automaticamente.
PHP, Node.js, Python, Android
Não precisa de SDK. Uma chamada HTTP simples com timeout curto basta. Exemplo completo de saque:
- cashoutguard.php: PHP 7.4+, um arquivo, sem Composer. É só dar require.
- composer require cashoutguard/cashoutguard-php: o mesmo cliente PHP com README, para sua pasta vendor.
- npm install @cashoutguard/node: Node 18+, com tipos TypeScript.
- cashoutguard-wordpress.zip: plugin de WordPress: o script do navegador em todas as páginas, cadastros e logins pontuados, e hooks para saques, conversões de offerwall e reversões.
Erros e limites
| HTTP | Corpo | Significado |
|---|---|---|
| 401 | missing_or_invalid_secret_key | Chave secreta ausente, errada ou revogada. A resposta diz o motivo em "reason" (missing, public_key, unknown_secret, placeholder, malformed) e como corrigir em "hint". |
| 404 | not_found | Conta não encontrada (endpoints de conta). |
| 422 | { "message", "errors" } | Corpo inválido. errors lista cada campo. |
| 429 | Too Many Requests | Limite de requisições atingido. A API do servidor permite 3.000 requisições por minuto por site. |
| 401 · agent.js | unknown_public_key | O data-key não é a chave pública de nenhum site. Copie de novo o pk_live_... em Instalação. |
| 403 · agent.js | origin_not_allowed | O domínio da página não está nas origens permitidas do site. Adicione em Sites ou deixe a lista vazia. localhost sempre funciona. O agent.js também explica isso no console do navegador. WebViews de apps enviam a origem "null": adicione null à lista para aceitá-los. O SDK nativo de Android não precisa de nada. |
| 403 | account_suspended | A conta está suspensa, normalmente por fatura não paga. Veja Faturamento. |
| 503 | temporarily_unavailable | Falha breve do nosso lado. Deixe a ação passar e tente de novo depois. |
Fail open: se a chamada der timeout ou erro, permita a ação e registre. Nunca deixe uma queda nossa travar os seus usuários.