KasyKasy

RevenueCat (mobile)

Assinaturas iOS e Android com RevenueCat. Do Test Store à produção.

O RevenueCat gerencia assinaturas e compras no app para iOS e Android. Conecta a App Store e a Play Store ao seu backend, sincroniza o status premium e dispara webhooks quando uma compra acontece.

Web usa Stripe. O RevenueCat cobre iOS e Android. Para pagamentos na web, veja Stripe.

Implementação

Pelo MCP do Kasy: peça ao assistente "adiciona revenuecat no meu projeto" pra ligar a feature no código (add_feature). O MCP do RevenueCat (abaixo) é outra coisa: monta o catálogo (produtos, entitlements, offerings) no painel deles. Veja MCP do Kasy.

Fase 1: Test Store (sem conta Apple ou Google)

O RevenueCat tem um ambiente chamado Test Store que simula compras sem precisar de conta na Apple ou Google. Ideal para validar o fluxo completo antes de configurar as lojas reais.

A Test Store valida a sua integração, não valida a loja. Se a compra funciona aqui, está provado que o paywall abre, o entitlement ativa, o webhook dispara e a linha grava no banco. Nada disso diz que a venda real vai funcionar.

O que só a Fase 2 prova: IDs idênticos entre loja e RevenueCat, contrato de aplicativos pagos assinado, conta bancária validada, produto aprovado e conta de pagamento ativa. Falha em qualquer um desses e o Sandbox devolve lista vazia mesmo com a chave certa.

Não pule a Fase 2 achando que a Fase 1 já cobriu.

1. Criar conta e projeto no RevenueCat

Acesse app.revenuecat.com → crie uma conta gratuita → crie um projeto.

2. Pegar a chave do Test Store

Todo projeto RevenueCat já nasce com um app Test Store pronto, você não precisa criar nada. A chave fica em API keys → SDK API keys → Test Store.

Copie a chave test_xxx exibida.

Painel do RevenueCat mostrando a chave test_ do app Test Store em API keys
Painel do RevenueCat: API keys → SDK API keys, com a chave test_ do Test Store revelada

O tipo do app no RC e o prefixo da chave devem bater. Test Store → chave começa com test_. Se criar como App Store e usar test_, dá erro INVALID_CREDENTIALS.

3. Criar Produtos, Entitlements e Offerings

Pelo painel RC (ou via MCP do RevenueCat):

  • Products → + New → crie os planos (ex: premium_monthly, premium_annual)
  • Entitlements → + New → crie premium_access → anexe os produtos
  • Offerings → + New → crie default → adicione os produtos
Painel do RevenueCat com Products, Entitlements e Offerings criados
Como fica o painel com os produtos, o entitlement e o offering criados

4. Configurar no projeto

Se for um projeto novo, a CLI pede a chave durante o kasy new.

Em projeto existente:

kasy add revenuecat

Ou edite o .env diretamente:

RC_TEST_KEY=test_xxxxxxxxxxxxxxx

Pelo MCP: cole a chave no chat e peça "configura a chave do RevenueCat". O assistente grava com configure_project_keys, sem precisar editar o .env na mão. Veja MCP do Kasy.

5. Rodar e testar

kasy run     # simulador iOS ou emulador Android

Um modal de compra simulada aparece com 3 opções: Sucesso / Erro / Cancelado. Escolha Sucesso: o entitlement deve ativar e o app liberar o conteúdo premium.

Webhook key

A chave do webhook (rc_wh_...) precisa ser idêntica no backend e no painel do RevenueCat (campo Authorization header value). A função compara a string inteira do header, incluindo o prefixo Bearer .

No modo Rápido do kasy new, o módulo RevenueCat já vem instalado, mas as credenciais não: o prompt da chave só aparece no fluxo interativo (não Rápido). Configure depois com kasy configure, configure_project_keys no MCP ou kasy deploy.

Backend:

  1. Gravar o secret: kasy configure / configure_project_keys com RC_WEBHOOK_KEY, ou kasy deploy (quando a chave já estiver no fluxo). No Supabase o secret se chama REVENUECAT_WEBHOOK_KEY; a CLI grava com o prefixo Bearer .
  2. RevenueCat → Project → Integrations → Webhooks → campo "Authorization header value": cole Bearer + a mesma chave (ex.: Bearer rc_wh_abc123).
Formulário de webhook do RevenueCat preenchido
Integrations → Webhooks: URL da função + Authorization header value preenchidos

Salve essa chave imediatamente. O Supabase não exibe o valor depois, só um hash.

Para ver ou alterar depois:

# Firebase: ver valor atual
firebase functions:secrets:access REVENUECAT_WEBHOOK_KEY

# Supabase: alterar valor (inclua Bearer, a função compara a string inteira)
supabase secrets set REVENUECAT_WEBHOOK_KEY="Bearer rc_wh_..."

Se os dois lados não tiverem o mesmo valor, o webhook retorna 401 e a tabela subscriptions para de atualizar.

Para testar: no painel RC, depois de salvar o webhook, clique em Send test event. Se a resposta for 200 OK, está funcionando. Depois faça uma compra pelo Test Store e confira se a linha aparece na tabela subscriptions.

Fase 2: Sandbox real (iOS)

Necessário quando o fluxo via Test Store já funciona e você quer testar com produto real na App Store.

Custo: USD $99/ano (conta Apple Developer)

1. Criar conta Apple Developer

Acesse developer.apple.com e pague o USD $99/ano.

2. Configurar a parte comercial no App Store Connect

Sem isso o Sandbox não funciona. App Store Connect → menu superior → Agreements, Tax, and Banking:

  • Assine o Paid Applications Agreement
  • Cadastre e valide a conta bancária
  • Preencha os formulários fiscais

Aguarde aprovação (pode levar até 1 dia).

Página Agreements, Tax, and Banking do App Store Connect
App Store Connect: Paid Applications Agreement assinado e conta bancária validada

3. Criar o app no App Store Connect

App Store Connect → My Apps → + → New App → use o mesmo Bundle ID do projeto Flutter.

4. Criar as assinaturas

App Store Connect → seu app → Monetização → Assinaturas:

  • Crie um grupo de assinaturas (ex: "Premium")
  • Adicione os produtos (ex: premium_monthly, premium_annual)
  • O identificador deve ser idêntico ao que você vai criar no RevenueCat
Grupo de assinaturas no App Store Connect
App Store Connect: grupo de assinaturas com os produtos criados

Existem duas seções de Idioma, e as duas são obrigatórias. Sem elas, tudo fica travado em "Preparar para envio":

  1. No grupo (nesta tela, "Standard Subscription Plans") → seção Idioma → adicione um idioma com o nome de exibição do grupo.
  2. Em cada assinatura (Monthly Subscription, Annual Subscription...) → seção Idioma dela → adicione o mesmo idioma com nome de exibição e descrição.

Faltar qualquer um dos dois trava o envio para revisão.

5. Configurar o RevenueCat com a chave Apple

No painel RC → Project → Apps → + Add app → App Store → copie a chave appl_xxx.

App iOS conectado na RevenueCat com as chaves da App Store Connect válidas
RevenueCat: app App Store criado, com o Bundle ID e as chaves P8 validadas

Cole no .env:

RC_IOS_PROD_KEY=appl_xxxxxxxxxxxxxxx

6. Criar Produtos, Entitlements e Offerings no RC

Com a chave appl_xxx ativa:

  • Products → crie com os mesmos IDs das assinaturas do App Store Connect
  • Entitlements → premium_access → anexe os produtos
  • Offerings → default → adicione os pacotes

7. Criar conta Sandbox Tester

App Store Connect → Users and Access → aba Sandbox → Testers → + → crie com um e-mail fictício.

Criação de Sandbox Tester no App Store Connect
Users and Access → Sandbox → Testers: conta de teste criada

8. Conectar Sandbox Tester no iPhone

No iPhone físico: Ajustes → App Store → Sandbox Account → Sign In com o e-mail/senha do Tester criado. Em versões recentes do iOS o campo fica em Ajustes → Desenvolvedor → Sandbox Apple Account (só aparece com o Modo de Desenvolvedor ligado).

E se o app vier do TestFlight? App instalado por TestFlight já roda em sandbox automaticamente e a compra nunca é cobrada. Mesmo assim, a Apple recomenda entrar com a Sandbox Apple Account para conseguir testar os cenários de assinatura: saia da sua conta de produção em Media & Purchases e entre com a de sandbox nas configurações de Desenvolvedor.

No TestFlight a renovação é acelerada: cada assinatura renova diariamente, até 6 vezes numa janela de 1 semana, independente da duração real do plano.

9. Testar

kasy run      # detecta iPhone físico e usa RC_IOS_PROD_KEY automaticamente

Faça uma compra: o modal real da Apple aparece. Confirme e o entitlement deve ativar.

Fase 2: Sandbox real (Android)

Custo: USD $25 (pagamento único)

1. Criar conta Google Play Developer

Acesse play.google.com/console e pague o USD $25.

2. Configurar Merchant Account

Google Play Console → Configurações → Conta do desenvolvedor → Perfil de pagamentos → preencha o nome legal e o endereço da empresa. Dados bancários e fiscais não são pedidos nessa etapa, só entram depois, quando a primeira venda acontecer.

Se você já tem um perfil de pagamentos compartilhado com o Google Workspace (ou outro produto Google) e a criação da assinatura travar com um erro de conta retida, crie um perfil para pagamentos dedicado só para o Play Console. Não precisa reaproveitar o perfil da organização nem preencher dados bancários de novo, só nome e endereço.

3. Criar e publicar no track interno

Gere um APK/AAB assinado e suba em: Testes → Testes internos → criar release → publicar.

O app não precisa estar completo. Uma versão de desenvolvimento assinada já serve. Isso é obrigatório para criar assinaturas.

Track de testes internos no Google Play Console
Play Console: Testes → Testes internos com a release publicada (mesmo passo detalhado em Publicar → Android)

4. Criar as assinaturas

Google Play Console → seu app → Monetizar → Assinaturas → + Criar assinatura:

  • Crie premium_monthly, premium_annual
  • O identificador deve ser idêntico ao que você vai criar no RevenueCat
Assinaturas criadas no Google Play Console
Play Console: Monetizar → Assinaturas com os produtos ativos

5. Criar Service Account e configurar RC

O Android usa uma Service Account:

a) Google Cloud Console → seu projeto → APIs e serviços → Biblioteca: ative Google Play Android Developer API e Google Play Developer Reporting API

API do Google Play ativada no Google Cloud Console
Google Cloud Console: confirmação de 'API Enabled', repita para as duas APIs

Se for a primeira vez que você usa o Google Cloud Console nessa conta Google, ele vai pedir pra aceitar os Termos de Serviço do Google Cloud Platform antes de mostrar qualquer projeto. É só uma vez.

b) IAM e administração → Contas de serviço → + Criar → dê um nome (ex: revenuecat-play) → Criar e fechar (não precisa conceder papéis aqui). Depois abra a conta criada → aba Chaves → Adicionar chave → Criar nova chave → JSON: o download começa automaticamente. Guarde esse arquivo, você vai precisar dele no passo (d).

Criação de chave privada JSON para a Service Account no Google Cloud Console
Google Cloud Console: Contas de serviço → Chaves → Criar nova chave (JSON)

c) Google Play Console → Usuários e permissões → Convidar usuário → cole o e-mail da service account (nome@seu-projeto.iam.gserviceaccount.com) → permissão de Administrador → Aplicar ao app

Convite da Service Account no Google Play Console
Play Console: Service Account convidada com as permissões necessárias

d) No painel RC → Apps → + Add app → Google Play → suba o JSON da service account → copie a chave goog_xxx

App Android conectado na RevenueCat com as credenciais da service account válidas
RevenueCat: app Google Play criado, com o package name e o JSON da service account validados

Cole no .env:

RC_ANDROID_PROD_KEY=goog_xxxxxxxxxxxxxxx

Fase 3: Produção

Use as mesmas chaves da Fase 2. O RevenueCat detecta sozinho se a compra é Sandbox ou Produção. O que muda:

  • A chave P8 é obrigatória no RC para iOS (App Settings → In-App Purchase Key)
  • Os produtos precisam estar aprovados nas lojas
  • Teste via TestFlight antes de submeter (iOS)

Nunca deixe test_ num build de loja. O SDK do RevenueCat crasha o app de propósito em release com chave de teste. O kasy run e o kasy ios release usam as chaves de produção do .env automaticamente.

Informações

O que a CLI configura automaticamente

Ao selecionar RevenueCat no kasy new ou kasy add revenuecat:

O que a CLI fazVocê faz
Instala purchases_flutterCriar conta no RevenueCat
Pede até 3 chaves e salva no .envColar pelo menos a chave de teste quando a CLI perguntar
Gera o código da feature (paywall, repositório etc.)Criar Produtos, Entitlements e Offerings no painel RC
Firebase: deploya a Cloud Function do webhookRegistrar a URL do webhook no painel RC
Supabase: deploya a Edge Function do webhookNenhuma ação extra
API REST: você implementa o webhookRegistrar a URL no painel RC

API REST: o app é igual nos 3 backends, mas no API REST você implementa o handler do webhook do RevenueCat no seu servidor. Quando o RC dispara o evento, seu servidor valida o Authorization header com a REVENUECAT_WEBHOOK_KEY configurada e grava em subscriptions(user_id, store=REVENUECAT, ...). O contrato completo do payload está no README.md gerado dentro do seu projeto Kasy.

3 conceitos essenciais

TermoO que éExemplo
ProdutoO item vendável na loja (Apple/Google)Assinatura mensal R$19,90
EntitlementA permissão que o produto libera no apppremium_access
OfferingO conjunto de produtos que aparece no paywallPlano mensal + anual

Fluxo: Produto comprado → Entitlement ativo → app desbloqueia o conteúdo premium

Chaves por tipo de device

O RevenueCat usa três tipos de chave, cada uma para um ambiente:

ChaveFunciona em
test_xxxSimulador iOS e emulador Android
appl_xxxiPhone físico (Sandbox e Produção)
goog_xxxAndroid físico

O kasy run detecta o device e injeta a chave certa. No .env:

RC_TEST_KEY=test_xxx
RC_IOS_PROD_KEY=appl_xxx
RC_ANDROID_PROD_KEY=goog_xxx

Se só RC_TEST_KEY estiver preenchida, o kasy run usa ela em qualquer device e avisa. O fluxo de desenvolvimento não quebra.

Período de teste gratuito (trial)

O trial é detectado automaticamente pelo kit. Quando o produto tem um introductoryPrice com price = 0.0, a duração aparece no paywall automaticamente. Você não muda nada no código, só configura nas lojas.

iOS: App Store Connect

  1. App Store Connect → seu app → In-App Purchases
  2. Selecione o produto
  3. Em "Subscription Prices" → + → Add Introductory Offer
  4. Tipo: Free Trial → defina a duração (7 dias, 1 mês etc.)
  5. Salve

Android: Google Play Console

  1. Google Play Console → Monetizar → Assinaturas
  2. Selecione o produto → seção "Free trial"
  3. Defina a duração em dias → Salve (pode levar algumas horas para ativar)

Tempo de assinatura no Sandbox

Em Sandbox, as assinaturas duram minutos. É normal:

PlanoiOS SandboxAndroid Sandbox
Mensal5 min5 min
Anual1 hora30 min

Cada assinatura renova automaticamente até 6 vezes antes de expirar. Se a assinatura "desapareceu" durante o teste, não é bug.

Escolher e trocar o paywall

O kit traz 4 paywalls prontos. No modo Rápido do kasy new, o padrão é o unlock; no Passo a passo, a CLI pergunta qual usar. Os 4 arquivos vão para o projeto de qualquer forma, trocar depois é editar uma linha.

PaywallFactory.XIdeal para
soloUm único plano. Benefícios + botão de assinar, sem distrações
comparePlanos lado a lado + tabela comparando free vs premium
trialPlano anual com toggle de teste grátis e vídeo de fundo
unlockConversão no onboarding ou paywall "duro" (padrão do modo Rápido)

Para trocar, edite o router.dart do seu projeto:

// antes:
child: const PremiumPage(paywall: PaywallFactory.unlock),
// depois:
child: const PremiumPage(paywall: PaywallFactory.solo),

Como o trial funciona

O toggle liga e desliga o teste grátis do plano anual: ON mostra "X dias grátis, depois o preço"; OFF assina o anual cobrando na hora. É o padrão de Duolingo, Calm e Headspace: o trial remove a barreira do plano mais caro. Se o trial ainda não estiver configurado nas lojas, aparece "0 dias grátis" (esperado em desenvolvimento). Se nenhum produto tiver trial, prefira solo ou compare.

Ver os 4 antes de escolher

Console Admin → Ferramentas → Paywalls mostra os 4 layouts em modo preview, sem compra real. Abra em claro e escuro antes de decidir.

A/B de preços e ofertas (RevenueCat Experiments, todos os backends)

O painel RC → Experiments serve Offerings diferentes para grupos de usuários (ex.: trial de 7 vs 14 dias, preço cheio vs desconto). O código do kit já usa getOfferings().current, então o experimento funciona sem mudar nada no app.

Mudar nome, preço ou produto precisa de nova versão?

Não. O paywall busca tudo das lojas e do painel RC em tempo de execução:

O que você mudaOnde mudaNova versão?
Nome do produtoApp Store Connect / Play ConsoleNão
PreçoApp Store Connect / Play ConsoleNão
Quais produtos aparecem (Offering)Painel RevenueCatNão
Trial (dias grátis)App Store Connect / Play ConsoleNão

O usuário vê a mudança na próxima abertura do app (cache do SDK). Em desenvolvimento, use hot restart (R): o hot reload (r) não rebusca os dados do RC.

Erros comuns

INVALID_CREDENTIALS

CausaSolução
Chave test_ com app tipo App Store no RCMude o tipo para Test Store
Chave digitada erradaCopie de novo do painel, sem espaços
Chave appl_ com app tipo Test StoreCrie um app do tipo App Store no RC

Produtos não aparecem no paywall

  • IDs idênticos no App Store Connect/Play Console e no RC, caractere por caractere
  • (iOS) Paid Applications Agreement assinado e conta bancária validada; sem isso nada aparece, nem no Sandbox
  • (iOS) Produto em Ready to Submit ou Approved
  • (Android) App publicado no track interno e conta de pagamento ativa
  • Teste em device físico: simulador só funciona com Test Store

Sandbox retorna lista vazia mesmo com a chave certa

Quase sempre é a parte comercial incompleta: (iOS) Agreements, Tax, and Banking pendente; (Android) conta de pagamento não verificada. Esses passos bloqueiam o Sandbox independentemente do RevenueCat.

Custos

ServiçoCusto
RevenueCatGrátis até USD $2.500/mês de receita
Apple Developer ProgramUSD $99/ano
Google Play Developer ProgramUSD $25 (pagamento único)

MCP do RevenueCat

O RevenueCat tem um servidor MCP que permite criar Produtos, Entitlements, Offerings e paywalls direto pelo Claude, sem abrir o painel.

Configurar

Painel RevenueCat → menu superior direito (seu nome) → API Keys → Secret API keys → + New secret API key (começa com sk_).

Cole na sua IA (troque pela sua chave):

Configure o MCP do RevenueCat nesta máquina, no Claude Code.
É um servidor MCP remoto do tipo HTTP na URL https://mcp.revenuecat.ai/mcp
com o header:  Authorization: Bearer MINHA_CHAVE
Minha chave secreta é: sk_XXXXXXXX
Adicione como um servidor MCP chamado "revenuecat".
No fim, me avise pra eu reiniciar o Claude Code.

Reinicie o Claude Code. O MCP só carrega em sessão nova.

Se preferir configurar na mão, adicione no arquivo de configuração MCP do Claude (~/.claude.json ou equivalente):

{
  "mcpServers": {
    "revenuecat": {
      "type": "http",
      "url": "https://mcp.revenuecat.ai/mcp",
      "headers": {
        "Authorization": "Bearer SUA_SK_AQUI"
      }
    }
  }
}

O que dá pra fazer

  • "Crie um produto premium_monthly no projeto X"
  • "Crie um Offering default e anexe os produtos A e B"
  • "Liste todos os Entitlements do meu projeto"
  • "Mostre as métricas de receita do último mês"

Atualizado em 03/11/2026