Mapa de Endpoints da API
Catálogo dos endpoints do BFF consumidos pelo template front-web-base
(direto ou via packages do core @cactus-agents/*). Para ver qual rota
SSR (/api/*) chama cada um, consulte SSR Routes → BFF.
Todos os paths abaixo são relativos ao API_BASE_URL, que é var de Worker
por environment (o CI resolve das bindings do Cloudflare e mascara o valor).
A base já termina em /v2 — daí os paths começarem em /auth, /bff, etc. O
valor de referência do workspace fica em envs/front-web-base.env; o exemplo do
template, em .env.example.
:::warning Esta página descreve a trunk main-7k
Trunks de marca diferentes consomem conjuntos diferentes de endpoints — features
são portadas, não mergeadas. Ver
Trunks de marca.
:::
Auth
| Metodo | Endpoint | Observacao |
|---|---|---|
| POST | /auth/login | Login por email/senha (+ 2FA, captcha, icg_token) |
| POST | /auth/logout | Invalida sessao |
| GET | /auth/user-profile[?check_spa_again=1&icg_token=…] | Perfil do usuario logado |
| POST | /users/refresh-token | Refresh JWT |
| POST | /auth/register | Registro completo (quando documento/telefone sao obrigatorios) |
| POST | /auth/register/simplified | Registro simplificado legado |
| POST | /bff/register-simplified | Registro single-step por email |
| POST | /bff/social/{provider} | Login social (troca token do provider por JWT Cactus) |
| POST | /bff/social/{provider}/registerSimplified | Registro social (provider dinamico) |
| POST | /auth/passwords/reset/options | Esqueci a senha — envia opcoes de recuperacao |
| POST | /auth/passwords/reset/by-email | Envia codigo por email |
| POST | /auth/passwords/reset/by-sms | Envia codigo por SMS |
| POST | /auth/passwords/reset/validate-code | Valida codigo de recuperacao |
| POST | /auth/passwords/reset/confirm | Confirma nova senha |
| POST | /documents/validate | Valida CPF (BR) / CURP (MX); tambem usado no fluxo Didit (CHL) |
| POST | /documents/confirm-birthdate | Confirma data de nascimento (fluxo Didit, CHL) |
| POST | /bff/otp/register/send | Envia OTP de telefone no cadastro |
| POST | /bff/otp/register/resend | Reenvia o OTP de telefone |
O endpoint final de registro e resolvido por
resolveRegisterEndpoint()no template em runtime conformeregisterTypeVersionda brand + flagsrequestDocument/requestPhone/socialService.
:::warning Contrato do OTP de cadastro: duas fontes discordam
A rota app/routes/api/auth/register.validate-phone.ts chama de fato
/bff/otp/register/send e /bff/otp/register/resend — é isso que está na tabela
acima. Mas app/modules/register/flow.ts e @cactus-agents/types descrevem o
contrato como /bff/register/validate-phone, path pra qual não existe
nenhum call site.
Antes de escrever código novo contra esse fluxo, confirme com o time de back-end qual é o contrato real — uma das duas fontes está errada, e de qual lado fica a correção depende dessa resposta. :::
:::note /auth/logout-auto não aparece nesta página
O endpoint existe no BFF, mas o caminho de logout forçado está incompleto em três
camadas — e o efeito prático não é um 404, é a ausência do sinal:
- Core, raiz:
AuthService.logoutAuto()existe de verdade e tem teste (packages/accounts/src/auth-service.test.ts), acessível só via oAuthServiceraiz. - Core,
/react:packages/accounts/src/react/auth-http.tsdefinedefaultLogoutAuto()apontando pra/api/auth/logout-auto, mas ela não é exportada pelo barrel/reacte não tem nenhum call site — é código morto. - Core, config:
AccountsConfig(react/config.ts) expõe sólogout?; não existe seamlogoutAuto?, então nem um consumidor que quisesse ligar o caminho forçado conseguiria fazê-lo viainitAccounts().
No template, app/routes/api/auth/ não tem logout-auto.ts, e deleteJwtCookie() chama
POST /api/auth/logout fixo, sem ramificação. Ou seja: nada dispara a rota removida, e
nada 404 hoje.
Consequência real: o log de auditoria do BFF não distingue logout forçado de voluntário.
Ligar isso exige uma rota proxy no template e um seam novo no core — não é só recriar a
rota. Detalhe completo em ../sdk/accounts.md.
:::
:::caution Não confie no comentário do código aqui
app/components/user/panel/UserPanelLogout.tsx documenta um opt-in via
authFeaturesConfig.useAutoLogoutEndpoint. Essa flag não existe em lugar nenhum de
app/ ou overrides/ — a única ocorrência é dentro do próprio comentário que a descreve.
:::
Brand
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /appearance | Configuracao visual da marca (logo, cores, banners) |
| GET | /bff/features | Feature flags ativas |
| POST | /bookmaker-settings | Configuracoes do bookmaker (operador) |
| GET | /getlegalterm | Termos legais / contratos da marca |
User
| Metodo | Endpoint | Observacao |
|---|---|---|
| POST | /users/update/{id} | Atualiza dados do usuario |
| POST | /users/change-password/{id} | Troca senha |
| GET | /bff/users/address-by-user | Endereco cadastrado |
| PATCH | /bff/users/self-email | Atualiza email |
| PATCH | /bff/users/add-phone | Adiciona telefone |
| PATCH | /bff/users/update-address | Atualiza endereco |
| PATCH | /bff/users/self-contracts | Aceita contratos/termos |
| PATCH | /bff/users/self-mkt | Opt-in/out marketing |
| PATCH | /bff/users/update-user-info-metadata | Preferencias genericas — campo livre, whitelist no core (ver aviso abaixo) |
| PATCH | /bff/users/update-pending-data | Atualiza dados pendentes pos-login |
| POST | /bff/users/check-password | Verifica senha atual |
| PATCH | /bff/users/self-two-factor | Habilita/desabilita 2FA |
| GET | /bff/users/account-social | Lista contas sociais vinculadas |
| POST | /bff/users/account-social/connect/{type} | Vincula conta social (google, apple) |
| DELETE | /bff/users/account-social/{id} | Remove conta social |
| GET | /bff/users/login-history?page={page} | Historico de logins paginado |
| GET | /bff/games/user-last-casino-games-dl | Ultimos jogos jogados pelo usuario (DL) |
| GET | /bff/users/zendesk/create-or-update-user | Token SSO do Zendesk |
| POST | /users/list-referrals | Lista convidados (refer-a-friend) |
| POST | /apicep | Lookup de CEP/codigo postal |
| PATCH | /bff/users/update-limits | Atualiza limites de deposito/aposta |
| PATCH | /bff/users/timeout-limits | Define timeout temporario |
| PATCH | /bff/users/self-exclusion | Autoexclusao |
| POST | /income-report/generate | Gera relatorio IRPF |
| GET | /income-report/{id} | Polling do relatorio (intervalo de 3s) |
| GET | /income-report/available-years | Anos disponiveis para relatorio |
| POST | /documents/verify-identity | Dispara verificacao de identidade (CHL) |
:::danger Endpoints de campo livre: o whitelist mora no CORE
Alguns endpoints do BFF aceitam qualquer JSON. O caso canônico é
PATCH /bff/users/update-user-info-metadata, que grava o que vier sob a chave
preferencies (typo do backend — não corrigir). Como o BFF não valida a forma,
o contrato do que pode ser gravado tem que morar em outro lugar — e mora no
core:
| Onde | O quê |
|---|---|
ALLOWED_PREFERENCES em @cactus-agents/accounts | Mapa chave → valores permitidos. Única fonte de verdade. |
updateUserPreferences() (mesmo package) | Aplica o guard e lança antes da chamada de rede pra chave desconhecida ou valor fora da lista. |
app/routes/api/user/update-preferences.ts no base | Só chama createUserFromClient(client).updateUserPreferences(body). |
Três consequências práticas:
- O base nunca conhece o path do BFF nem a lista de chaves. Nada em
app/mencionaupdate-user-info-metadata. Não substitua a chamada do service por umclient.patch()direto — isso contorna o único guard existente e devolve ao BFF a capacidade de gravar qualquer coisa. - Adicionar uma preferência exige bump do core — nova entry em
ALLOWED_PREFERENCES+ campo emUserPreferences. Não existe caminho pelo base, e não existe feature flag que destrave isso. - Ao adicionar um endpoint de campo livre novo, repita esse padrão: guard tipado no core, base chamando o service. Um endpoint de campo livre sem whitelist no core é bug de arquitetura, não conveniência. :::
Wallet
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /users/wallet | Saldo atual |
| POST | /bff/transactions | Historico de transacoes (filtros no body) |
| GET | /transactions/cashback?page=...&per_page=10 | Historico de cashback paginado |
| GET | /bonus/rollover | Rollover ativo |
| GET | /bonus/rollover-accomplished | Rollover concluido |
| POST | /bonus/transfer | Transfere saldo de bonus |
| POST | /cashback/transfer | Resgata cashback |
| GET | /withdraw/{id}/generate | Gera comprovante de saque |
/withdraw/{id}/generateé operação de saque — listado aqui por proximidade funcional.
Payments
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /payment-providers | Lista de providers de pagamento disponiveis |
| POST | /wallet/add-credit | Deposito |
| GET | /wallet/charge/{transactionId} | Status do deposito (polling) |
| POST | /new-withdraws | Solicita saque |
| GET | /bff/users/bank-list | Lista de bancos |
| POST | /pix-keys/user-key | Le chave PIX cadastrada (BR) |
| POST | /pix-keys/update-user-key-v2 | Atualiza chave PIX (BR) |
| GET | /mex-bank-accounts/user-account | Conta bancaria do usuario (MX) |
| POST | /mex-bank-accounts/store | Cadastra conta bancaria (MX) |
| GET | /generic-bank-accounts/user-account | Conta bancaria generica do usuario (CHL/NGA) |
| POST | /generic-bank-accounts/store | Cadastra conta bancaria generica (CHL/NGA) |
| GET | /coupons/{code} | Valida cupom promocional |
Games
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /casino-games/home | Layout da homepage — rows com jogos por categoria |
| GET | /casino-games/page/{page} | Layout de pagina curada pelo BFF (alt. de /home) |
| GET | /casino-games/list/base | Categorias (custom_categories) + providers |
| GET | /casino-games/list/?… | Lista paginada: categories[]=slug&providers[]=slug&term=texto&page=1&per_page=24 |
| GET | /casino-games?slug={slug} | Detalhe de um jogo |
| GET | /casino-games/filter | Legacy — mas ainda ativo: e o endpoint que o legacy-service usa em CASSINO_MODE=legacy |
| GET | /start-game-v2?… | ?slug=&platform=MOBILE|WEB&use_demo=0|1 — autenticado, abre jogo |
| GET | /bff/games/top-wins-dl | Maiores ganhos (data-lake) |
| GET | /bff/games/game-top-wins-dl?slug={slug} | Maiores ganhos por jogo (data-lake) |
| GET | /bff/games/last-wins | Ultimos ganhos |
| GET | /bff/games/game-high-payers-dl | High-payers (data-lake) — alimenta top-games na home |
| GET | /bff/games/statistics?slug={slug} | Estatisticas por periodo (5min, 1h, 24h, 7d, 15d, 30d) |
| GET | /bff/games/statistics-dl?slug={slug} | Estatisticas data-lake (usadas por /api/games/statistics-dl) |
| GET | /casino-game-votes?casinoGameId={id} | Voto do usuario (autenticado) |
| GET | /casino-game-votes/count/{gameId} | Contagem de likes/dislikes |
| POST | /casino-game-votes/store/ | Body: { casinoGameId, is_like } — autenticado |
| DELETE | /casino-game-votes/destroy/{gameId} | Remove voto — autenticado |
| GET | /bff/favorite-games | Lista jogos favoritos do usuario |
| PUT | /bff/favorite-games/toggle | Toggle de favorito (body { slug_url }) |
Sports
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /cactus-sportbook/search | Busca no sportsbook |
| GET | /cactus-sportbook/launch | Launch autenticado |
| GET | /cactus-sportbook/anonymous-launch | Launch anonimo |
| GET | /cactus-sportbook/auth/anonymous | Token anonimo da Rogue (exige header x-api-key) |
| GET | /cactus-sportbook/auth/login | Token logado da Rogue (exige header x-api-key) |
| GET | /cactus-sportbook/* | Proxy transparente para qualquer subpath (/api/cactus-sportbook/*) |
| POST | /betby/get-jwt | JWT para provider Betby |
| GET | /alternar/token | Token para provider Altenar |
Providers suportados:
["first", "altenar", "betby", "rogue"]. As duas rotas/cactus-sportbook/auth/*devolvem{ access_token, api_url }e são o único ponto de contato com o BFF no fluxo Rogue — todo o resto do tráfego vai direto pra Rogue API (fssb.io) através do proxy same-origin/api/sports/rogue-proxy/*. Ver SSR Routes.
KYC
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /bff/users/kyc?source={source} | Inicia KYC |
| GET | /bff/users/kyc/recovery | Recovery do KYC |
| GET | /bff/users/kyc/status?kyc_id={id} | Status do KYC |
| GET | /bff/users/kyc/status/recovery | Status recovery do KYC |
Validation
:::warning Typo no backend
Os endpoints /bff/users/validade-email-code e /bff/users/validade-sms-code possuem typo no backend — "validade" ao inves de "validate". Nao corrigir no front; usar exatamente como esta.
:::
| Metodo | Endpoint | Observacao |
|---|---|---|
| POST | /bff/users/send-email | Envia codigo de verificacao por email |
| POST | /bff/users/validade-email-code | Valida codigo de email (typo: "validade") |
| POST | /bff/users/send-sms | Envia codigo de verificacao por SMS |
| POST | /bff/users/validade-sms-code | Valida codigo de SMS (typo: "validade") |
| PATCH | /bff/users/self-phone | Atualiza telefone apos validacao |
| PATCH | /bff/users/add-address | Adiciona endereco |
| PATCH | /bff/users/add-initial-data | Dados iniciais pos-registro |
| POST | /bff/validate-confirmation | Confirma link de validacao por email |
Os endpoints do fluxo Didit (CHL) —
/documents/validate,/documents/confirm-birthdatee/documents/verify-identity— estão listados em Auth e User.
Gamification (REST + Smartico SDK)
A gamificacao do Cactus expoe 2 endpoints REST pelo BFF (rewards / redeem). Alem disso, ha integracao client-side com Smartico (3rd party) via JS SDK, sem rotas BFF envolvidas.
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /bff/gamification/rewards?page=…&per_page=…&type=… | Lista paginada de rewards do usuario |
| POST | /bff/gamification/redeem | Resgata reward — body { reward_id } |
Smartico: ver
SmarticoInitializerno layout e o hookuseSmartico().
Sweepstakes (Gold Coins / Sweeps Coins)
:::info Não é dependência do front-web-base em main-7k
@cactus-agents/sweepstakes não está no package.json do base nesta trunk, e
nenhum arquivo de app/ o importa — logo não há rota /api/* de sweepstakes
aqui. A tabela abaixo documenta o contrato que o package publicado (0.6.0)
implementa, pra quem for ligar o modelo sweepstakes numa brand ou trunk. Ao
adotar, as rotas de proxy /api/* precisam ser criadas e listadas em
SSR Routes.
:::
| Metodo | Endpoint | Observacao |
|---|---|---|
| GET | /sweepstakes/balances | Saldos por moeda (GC / SC) |
| GET | /sweepstakes/wallet-preference | Moeda ativa da carteira |
| POST | /sweepstakes/wallet-preference | Define a moeda ativa — body { coin_type } |
| POST | /sweepstakes/currency-switch | Troca a moeda em uso — body { coin_type } |
| GET | /sweepstakes/eligibility | Elegibilidade pra resgate |
| GET | /sweepstakes/redemptions[?page={n}] | Lista de resgates (paginador Laravel) |
| GET | /sweepstakes/redemptions/{id} | Detalhe de um resgate (envelope { data }) |
| POST | /sweepstakes/redemptions | Solicita resgate |
| GET | /store/packages | Pacotes de Gold Coins à venda |
| POST | /store/purchase | Compra de pacote — body { package_id } |
:::warning Dois níveis de incerteza nesses paths
O próprio service.ts do package registra o que foi e o que não foi
confirmado — reproduzido aqui porque muda o risco de cada linha:
/store/packagesé confirmado por probe ao vivo:API_BASE_URLtermina em/v2, então resolve pra/v2/store/packages. É a única variante que o BFF reconhece —/api/store/...,/sweepstakes/store/...e/sweepstakes/packagesdevolvem 404 duro. Com a flagsweepstakes_store_enableddesligada no tenant, responde 403 "Store not available"./store/purchaseNÃO foi testado (criaria uma cobrança real). Foi inferido como irmão do path confirmado. Confirme com o back-end antes de subir pra produção.- O prefixo
/sweepstakes/*das demais linhas assume montagem na raiz do host e também está marcado como "confirmar com o backend" no código. :::
Headers
Fonte de verdade: buildHeaders() em packages/api-client/src/client.ts
(comuns) e getExtraHeaders() / getCfGeoHeaders() em
packages/api-client/src/server.ts (server-side).
Sempre presentes
| Header | Descricao |
|---|---|
tenant | ID do tenant (marca) |
lang | Idioma normalizado pro BFF (normalizeBackendLanguage colapsa es-cl → es) |
language | Mesmo valor de lang |
version | Build version id (cache-busting) |
origin-domain | Mesmo valor de tenant |
X-LOG-INFO | Payload de log estruturado |
Condicionais (client e server)
| Header | Quando |
|---|---|
Authorization | Bearer <jwt> — quando ha sessao |
X-ORIGIN-ACCESS | Quando o origin access e conhecido (desktop/mobile/app) |
X-ORIGIN-REFERRER, X-ORIGIN-HOSTNAME, X-ORIGIN-CINFO-ID, X-ORIGIN-CINFO-ID-REF | Tracking de origem, quando disponivel |
cactus-service: DEBUG | Client em modo debug |
Content-Type: application/json | Requests com body |
Só server-side (rotas /api/*)
Nenhum destes existe em request feito do browser — só saem do Worker.
| Header | Descricao |
|---|---|
cf-worker-key | Segredo (CF_WORKER_KEY). E a credencial que identifica o proxy oficial do front pro BFF. Sem ela, um caller de outra origem toma 404. |
is_new_front: "true" | Marca o front novo (temporario, ate a migracao terminar) |
country, country_alpha3, currency, jurisdiction | Derivados da brand/geo |
city | Cidade (sanitizada — São Paulo → Sao Paulo) |
Cookie | Repassa os cookies do request original |
User-Agent | Repassa o UA do usuario |
Geo do Cloudflare (server-side)
Emitidos por getCfGeoHeaders(). O IP real do usuario vai em quatro formatos
porque o backend le nomes diferentes por integracao — sem isso o BFF veria o IP
do Worker:
| Header | Descricao |
|---|---|
S-Client-Addr | IP real — nome que o backend PHP le pra PGSoft e outros providers |
x-cac-real-ip, X-Forwarded-For, X-Real-IP | Mesmo IP, nomes alternativos |
x-country | Pais (lowercase) |
x-user-info-timezone, x-user-info-lat, x-user-info-long, x-user-info-region, x-user-info-city | Geo do request.cf |
CF-Connecting-IPé deliberadamente não enviado — é header reservado do Cloudflare e setá-lo em request de saída faz o backend/WAF responder 403.
Só em dev
dev-user, dev-user-token-checksum, CF-Access-Client-Id,
CF-Access-Client-Secret — presentes apenas quando as vars correspondentes estão
setadas.
Headers extras por caller
Um caller server-side pode injetar headers próprios via extraHeaders no
createClient(). Escopo é aquele client só — não vaza pras outras chamadas nem
pro browser. Uso real hoje: x-api-key (de SPORTS_ROGUE_API_KEY) nas rotas de
token da Rogue.
Comportamentos por status HTTP
| Status | Comportamento |
|---|---|
| 401 | Logout automatico (tenta refresh-token antes) |
| 440 | Logout automatico — sessao encerrada server-side, refresh nao recupera (ver EM0030 em Codigos de erro) |
| 429 | Abre challenge/captcha |
| 202 | Timeout limit (resolve, nao throw) |
Rotas de proxy do template (/api/*)
O template front-web-base expõe 101 rotas internas que atuam como proxies server-side: leem o JWT do cookie HttpOnly e delegam ao BFF. O front-end só chama essas rotas — nunca o BFF diretamente.
Consulte SSR Routes → BFF para o mapa completo /api/* → BFF, agrupado por domínio (Auth, Validation, User, Wallet, Payments, Games, Search, Sports, KYC, Rewards, Income Report, FTD Cashback, Tracking, Infra).