Change Plan API
Plan Change Preview
Integration Guide
O que é um upgrade ou downgrade de assinatura?
Altere o plano de assinatura de um cliente para movê-lo entre níveis, ajustar a quantidade de produtos baseados em assentos ou migrar para um novo produto. A API calcula automaticamente os valores proporcionais e as cobranças com base no seu modo de cobrança escolhido.Quando usar alterações de plano
- Upgrade when a customer needs more features, usage, or seats
- Downgrade when usage decreases
- Migrate users to a new product or price without cancelling their subscription
Plan Change Flow
Prerequisites
Before implementing subscription plan changes, ensure you have:- A Dodo Payments merchant account with active subscription products
- API credentials (API key and webhook secret key) from the dashboard
- An existing active subscription to modify
- Webhook endpoint configured to handle subscription events
Step-by-Step Implementation Guide
Follow this comprehensive guide to implement subscription plan changes in your application:Understand Plan Change Requirements
- Which subscription products can be changed to which others
- What proration mode fits your business model
- How to handle failed plan changes gracefully
- Which webhook events to track for state management
Choose Your Proration Strategy
- prorated_immediately
- difference_immediately
- full_immediately
- do_not_bill
- Credita a parte não utilizada do ciclo atual, proporcionalmente ao tempo restante
- Em seguida, cobra um ciclo completo no novo plano — o preço do novo plano nunca é calculado proporcionalmente
- Cobrança líquida = ciclo completo do novo plano − (fração restante × ciclo completo do plano antigo)
Implement the Change Plan API
prorated_immediately, full_immediately, difference_immediately, or do_not_bill.null ou enviar um array vazio remove quaisquer add-ons existentes; portanto, inclua os add-ons atuais para mantê-los.prevent_change: Keep subscription on current plan until payment succeedsapply_change(default): Apply plan change immediately regardless of payment outcome
allow_plan_change_via_payment_link (Settings → Subscriptions → Collect Plan Change Payments by Payment Link), effective_at: immediately e on_payment_failure: prevent_change. Consulte Collecting Payment via a Checkout Link. Ignorado pela rota de preview.- Não fornecido /
null— os descontos existentes compreserve_on_plan_change=truesão preservados se forem aplicáveis ao novo produto. [](array vazio) — remove todos os descontos existentes da assinatura.["CODE_A", "CODE_B", ...]— substitui todos os descontos existentes por este conjunto empilhado.
discount_codes para novas integrações. Este campo ainda funciona para compatibilidade retroativa, mas não pode ser combinado com discount_codes na mesma solicitação.immediately(padrão): aplica a alteração de plano imediatamentenext_billing_date: agenda a alteração para a próxima data de cobrança. O cliente mantém o plano atual até o fim do período de cobrança. Use essa opção para downgrades, para que os clientes mantenham os benefícios do plano atual até o fim do período de cobrança.
Handle Webhook Events
subscription.active: alteração de plano bem-sucedida, assinatura atualizadasubscription.plan_changed: plano da assinatura alterado (upgrade/downgrade/atualização de addon)subscription.on_hold: cobrança da alteração de plano falhou, renovações interrompidaspayment.succeeded: cobrança imediata da alteração de plano bem-sucedidapayment.failed: cobrança imediata falhou
Update Your Application State
- Conceda ou revogue recursos de acordo com o novo plano
- Atualize o dashboard do cliente com os detalhes do novo plano
- Envie e-mails de confirmação sobre as alterações de plano
- Registre as alterações de cobrança para fins de auditoria
Test and Monitor
- Teste todos os modos de cálculo proporcional em diferentes cenários
- Verifique se o tratamento de webhooks funciona corretamente
- Monitore as taxas de sucesso das alterações de plano
- Configure alertas para alterações de plano com falha
Visualizar alterações de plano
Antes de confirmar uma alteração de plano, use a Preview API para mostrar aos clientes exatamente quanto será cobrado:- Node.js SDK
- Python SDK
Change Plan API
Use a Change Plan API para modificar o produto, a quantidade e o comportamento do cálculo proporcional de uma assinatura ativa.Exemplos de início rápido
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
200 OK imediatamente — antes que qualquer cobrança seja efetivamente liquidada. O conteúdo do corpo (ChangePlanResponse) depende de como a alteração foi cobrada:
collect_via_payment_link, a assinatura permanece no plano atual até que o cliente conclua o pagamento.Confirme o resultado por webhook (payment.succeeded, payment.failed, subscription.plan_changed) ou lendo novamente a assinatura com GET /subscriptions/{subscription_id} — consulte What Happens While the Link Is Unpaid para o caso de payment link.Coletar pagamento por meio de um link de checkout
Por padrão, uma alteração imediata de plano cobra diretamente o método de pagamento salvo da assinatura. Definacollect_via_payment_link: true para enviar o cliente a uma página de checkout hospedada — útil quando não há um método de pagamento salvo ou quando você deseja que o cliente confirme ativamente o novo preço.
Requisitos
collect_via_payment_link: true só funciona quando todas as condições a seguir são atendidas — caso contrário, a solicitação falha com 422:
- A empresa tem o recurso
allow_plan_change_via_payment_linkhabilitado (Settings → Subscriptions → Collect Plan Change Payments by Payment Link). effective_atéimmediately(o padrão). Uma alteração agendada (next_billing_date) nunca precisa de uma página de checkout.- O
on_payment_failureefetivo resolve paraprevent_change. Não é necessário enviá-lo explicitamente — se o padrão no nível da empresa já forprevent_change, omitir o campo atende a essa condição. Umapply_changeexplícito falha com422.
collect_via_payment_link se aplica a qualquer alteração imediata que resulte em uma cobrança, inclusive downgrades, desde que os requisitos acima sejam atendidos.payment_link e os outros campos de checkout retornam null, e a alteração é aplicada imediatamente. Isso não é um 422. Chame Preview Plan Change primeiro para verificar o valor antes de solicitar um link.
- Node.js SDK
- Python SDK
- HTTP
O que acontece enquanto o link não é pago
- A assinatura permanece no plano atual —
product_id,recurring_pre_tax_amountenext_billing_datepermanecem inalterados até que o link seja pago. - Uma nova solicitação
change-plané rejeitada com409 PendingPlanChangeExistsenquanto o link está pendente. Cancele uma alteração agendada comDELETE /subscriptions/{subscription_id}/change-plan/scheduled, se necessário, mas esse endpoint não cancela uma alteração pendente por payment link — somente um pagamento bem-sucedido ou a expiração faz isso. - O cliente pode tentar novamente um cartão na mesma sessão de checkout após uma recusa; uma nova chamada
change-plannão é o caminho para tentar novamente. - Se o link nunca for pago, ele deixará de funcionar após
expires_on— a assinatura ficará automaticamente disponível para aceitar uma nova solicitação de alteração de plano pouco depois. - Se já existia uma alteração agendada e você a substituir por
cancel_scheduled_change_plan: true, a programação original permanecerá enquanto o link não for pago e só será cancelada quando o link for pago — na mesma transação que aplica o novo plano.
Gerenciar addons
Ao alterar planos de assinatura, você também pode modificar addons:Aplicar códigos de desconto
Aplique um ou mais códigos de desconto empilhados ao alterar planos de assinatura (máximo de 20, aplicados na ordem do array):- Node.js SDK
- Python SDK
- HTTP
Comportamento dos descontos na alteração de plano
discount_code neste endpoint está obsoleto, mas ainda funciona para compatibilidade retroativa — as integrações existentes não precisam ser alteradas imediatamente. Ele não pode ser combinado com discount_codes na mesma solicitação. Migre para o formato de array quando for conveniente.Modos de cálculo proporcional
Escolha como cobrar o cliente ao alterar planos:prorated_immediately
- Credita a parte não utilizada do ciclo atual — plano base, quantidade e addons — proporcionalmente ao tempo restante
- Em seguida, cobra um ciclo completo do novo plano, quantidade e addons. A cobrança em si nunca é proporcional
- Cobrança imediata líquida = (ciclo completo novo) − (fração restante × ciclo completo antigo)
- Se o crédito exceder a cobrança do novo ciclo (comum em downgrades), a diferença será mantida como crédito vinculado à assinatura para renovações futuras
- Se estiver em trial, cobra imediatamente e muda para o novo plano agora
full_immediately
- Cobra imediatamente o valor integral do novo plano
- Ignora o tempo restante do plano antigo — não há crédito para o ciclo atual
prorated_immediately e por downgrades que usam difference_immediately são vinculados à assinatura e distintos dos benefícios de Credit-Based Billing. Eles são aplicados automaticamente a renovações futuras da mesma assinatura e não podem ser transferidos entre assinaturas.difference_immediately
- Upgrade: cobra imediatamente a diferença de preço entre os planos antigo e novo
- Downgrade: adiciona o valor restante como crédito interno à assinatura e aplica automaticamente nas renovações
do_not_bill
- Nenhuma cobrança ou crédito é calculado
- O cliente muda imediatamente para o novo plano sem qualquer ajuste de cobrança
- O ciclo de cobrança permanece inalterado
- Ideal para migrações como cortesia, mudanças para planos gratuitos ou absorção de diferenças de custo
Cenários de exemplo
Use estes números canônicos de forma consistente:- Plano atual: Basic a $30/mês
- Destino do upgrade: Pro a $80/mês
- Destino do downgrade (a partir do Pro): Starter a $20/mês
- Ciclo de cobrança: 30 dias, iniciado em 1º de janeiro
- A alteração de plano ocorre em 16 de janeiro (15 dias restantes, 15 dias utilizados)
Upgrade: Basic ($30) → Pro ($80) with prorated_immediately
Upgrade: Basic ($30) → Pro ($80) with prorated_immediately
Downgrade: Pro ($80) → Starter ($20) with prorated_immediately
Downgrade: Pro ($80) → Starter ($20) with prorated_immediately
Upgrade: Basic ($30) → Pro ($80) with difference_immediately
Upgrade: Basic ($30) → Pro ($80) with difference_immediately
Downgrade: Pro ($80) → Starter ($20) with difference_immediately
Downgrade: Pro ($80) → Starter ($20) with difference_immediately
Upgrade: Basic ($30) → Pro ($80) with full_immediately
Upgrade: Basic ($30) → Pro ($80) with full_immediately
Mid-cycle upgrade with add-ons using prorated_immediately
Mid-cycle upgrade with add-ons using prorated_immediately
Como cada modo processa a cobrança
Tratar falhas de pagamento
Controle o que acontece quando o pagamento de uma alteração de plano falha usando o parâmetroon_payment_failure.
Modos de falha de pagamento
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- A alteração de plano é marcada como “pending”
- O cliente mantém acesso ao plano atual
- A assinatura só passa para o estado
activeapós o pagamento bem-sucedido - Útil quando você deseja garantir o pagamento antes de conceder recursos atualizados
on_payment_failure usará a configuração padrão da empresa definida no dashboard.Quando usar cada modo
Padrões de empresa e cobrança
Defina o comportamento padrão de upgrades e downgrades no nível da empresa em Settings → Subscriptions. Esses padrões se aplicam a todas as alterações de plano pelo customer portal e podem ser substituídos por coleção de produtos. Existem padrões separados para upgrades e downgrades:Ordem de resolução
Para qualquer alteração de plano, cada configuração é resolvida nesta ordem:Tratar webhooks
Acompanhe o estado da assinatura por meio de webhooks para confirmar alterações de plano e pagamentos.Tipos de evento a tratar
subscription.active: assinatura ativadasubscription.plan_changed: plano da assinatura alterado (upgrade/downgrade/alterações de addon)subscription.on_hold: cobrança falhou, renovações interrompidassubscription.renewed: renovação bem-sucedidapayment.succeeded: pagamento da alteração de plano ou renovação bem-sucedidopayment.failed: pagamento falhou
Verificar assinaturas e tratar intenções
- Next.js Route Handler
- Express.js
Práticas recomendadas
Estratégia de alteração de plano
- Teste detalhadamente: sempre teste alterações de plano no modo de teste antes da produção
- Escolha o cálculo proporcional com cuidado: selecione o modo que esteja alinhado ao seu modelo de negócio
- Trate falhas adequadamente: implemente tratamento de erros e lógica de novas tentativas
- Monitore as taxas de sucesso: acompanhe as taxas de sucesso/falha das alterações de plano e investigue os problemas
Implementação de webhook
- Verifique as assinaturas: sempre valide as assinaturas dos webhooks para garantir a autenticidade
- Implemente idempotência: trate eventos de webhook duplicados adequadamente
- Processe de forma assíncrona: não bloqueie as respostas dos webhooks com operações pesadas
- Registre tudo: mantenha logs detalhados para depuração e auditoria
Experiência do usuário
- Comunique-se claramente: informe os clientes sobre as alterações de cobrança e o momento em que ocorrerão
- Forneça confirmações: envie confirmações por e-mail para alterações de plano bem-sucedidas
- Trate casos extremos: considere períodos de trial, cálculos proporcionais e pagamentos recusados
- Atualize a interface imediatamente: reflita as alterações de plano na interface da aplicação
Problemas comuns e soluções
Resolva problemas típicos encontrados durante alterações de planos de assinatura:Charge created but subscription not updated
Charge created but subscription not updated
- O processamento do webhook falhou ou foi atrasado
- O estado da aplicação não foi atualizado após o recebimento dos webhooks
- Problemas na transação do banco de dados durante a atualização do estado
- Implemente o tratamento de webhooks com lógica de novas tentativas
- Use operações idempotentes para atualizações de estado
- Adicione monitoramento para detectar e alertar sobre eventos de webhook perdidos
- Verifique se o endpoint do webhook está acessível e respondendo corretamente
Credits not applied after downgrade
Credits not applied after downgrade
- Expectativas sobre o modo de cálculo proporcional: downgrades creditam a diferença integral de preço do plano com
difference_immediately, enquantoprorated_immediatelycredita o tempo não utilizado do ciclo antigo e depois cobra um ciclo completo do novo plano — portanto, um saldo de crédito só permanece quando esse crédito excede o preço do novo plano - Os créditos são específicos da assinatura e não são transferidos entre assinaturas
- O saldo de crédito não está visível no dashboard do cliente
- Use
difference_immediatelypara downgrades quando quiser créditos automáticos - Explique aos clientes que os créditos se aplicam a renovações futuras da mesma assinatura
- Implemente o customer portal para exibir saldos de crédito
- Verifique o preview da próxima fatura para visualizar os créditos aplicados
Webhook signature verification fails
Webhook signature verification fails
- Chave secreta do webhook incorreta
- Corpo bruto da solicitação modificado antes da verificação da assinatura
- Algoritmo incorreto de verificação da assinatura
- Verifique se está usando o
DODO_PAYMENTS_WEBHOOK_KEYcorreto do dashboard - Leia o corpo bruto da solicitação antes de qualquer middleware de parsing de JSON
- Use a biblioteca padrão de verificação de webhooks da sua plataforma
- Teste a verificação da assinatura do webhook no ambiente de desenvolvimento
Plan change fails with 422 error
Plan change fails with 422 error
- ID de assinatura ou ID de produto inválido
- Assinatura não está no estado ativo
- Parâmetros obrigatórios ausentes
- Produto indisponível para alterações de plano
- Verifique se a assinatura existe e está ativa
- Confirme se o ID do produto é válido e está disponível
- Garanta que todos os parâmetros obrigatórios sejam fornecidos
- Consulte a documentação da API para conhecer os requisitos dos parâmetros
Immediate charge fails during plan change
Immediate charge fails during plan change
- Saldo insuficiente no método de pagamento do cliente
- Método de pagamento expirado ou inválido
- O banco recusou a transação
- A detecção de fraude bloqueou a cobrança
- Trate os eventos de webhook
payment.failedadequadamente - Notifique o cliente para atualizar o método de pagamento
- Implemente lógica de novas tentativas para falhas temporárias
- Considere permitir alterações de plano com cobranças imediatas recusadas
Subscription on hold after plan change
Subscription on hold after plan change
on_holdO que acontece:
Quando a cobrança de uma alteração de plano falha, a assinatura é automaticamente colocada no estado on_hold. A assinatura não será renovada automaticamente até que o método de pagamento seja atualizado.Solução: atualize o método de pagamento para reativar a assinaturaPara reativar uma assinatura no estado on_hold após uma alteração de plano malsucedida:- Atualize o método de pagamento usando a Update Payment Method API
- Criação automática da cobrança: a API cria automaticamente uma cobrança para os valores restantes
- Geração da fatura: uma fatura é gerada para a cobrança
- Processamento do pagamento: o pagamento é processado usando o novo método de pagamento
- Reativação: após o pagamento bem-sucedido, a assinatura é reativada para o estado
active
subscription.on_hold: assinatura colocada em espera (recebido quando a cobrança da alteração de plano falha)payment.succeeded: pagamento dos valores restantes bem-sucedido (após atualizar o método de pagamento)subscription.active: assinatura reativada após pagamento bem-sucedido
- Notifique os clientes imediatamente quando uma cobrança de alteração de plano falhar
- Forneça instruções claras sobre como atualizar o método de pagamento
- Monitore os eventos de webhook para acompanhar o status da reativação
- Considere implementar lógica automática de novas tentativas para falhas temporárias de pagamento
Update Payment Method API Reference
Testar sua implementação
Teste detalhadamente sua implementação de alteração de plano de assinatura:Set up test environment
- Use API keys de teste e produtos de teste
- Crie assinaturas de teste com diferentes tipos de plano
- Configure um endpoint de webhook de teste
- Configure monitoramento e logging
Test different proration modes
- Teste
prorated_immediatelycom diferentes posições no ciclo de cobrança - Teste
difference_immediatelypara upgrades e downgrades - Teste
full_immediatelypara redefinir ciclos de cobrança - Teste
do_not_billpara mudanças de plano sem cobrança/crédito - Verifique se os cálculos de crédito estão corretos
Test webhook handling
- Verifique se todos os eventos de webhook relevantes são recebidos
- Teste a verificação das assinaturas dos webhooks
- Trate eventos de webhook duplicados adequadamente
- Teste cenários de falha no processamento de webhooks
Test error scenarios
- Teste com IDs de assinatura inválidos
- Teste com métodos de pagamento expirados
- Teste falhas de rede e timeouts
- Teste com saldo insuficiente
Monitor in production
- Configure alertas para alterações de plano malsucedidas
- Monitore os tempos de processamento dos webhooks
- Acompanhe as taxas de sucesso das alterações de plano
- Analise os chamados do suporte ao cliente relacionados a problemas de alteração de plano
Tratamento de erros
Trate os erros comuns da API adequadamente na sua implementação:HTTP Status Codes
200 OK
200 OK
ChangePlanResponse com payment_id, payment_link, client_secret e expires_on. Os quatro valores podem ser nulos, portanto o corpo é serializado como {} para uma alteração off-session comum; eles são preenchidos para uma solicitação collect_via_payment_link bem-sucedida, que retorna identificadores de checkout — consulte Collecting Payment via a Checkout Link. Se on_payment_failure=prevent_change, a alteração de plano permanece pendente até que o pagamento seja concluído.400 Bad Request
400 Bad Request
409 Conflict
409 Conflict
PendingPlanChangeExists). Para uma alteração agendada, cancele-a com DELETE /subscriptions/{subscription_id}/change-plan/scheduled antes de enviar uma nova. Para uma alteração por payment link pendente, não há endpoint de cancelamento — a assinatura aceitará uma nova solicitação de alteração de plano quando o cliente pagar ou o link expirar.422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_link — a empresa não tem o recurso habilitado, effective_at não é immediately ou on_payment_failure não é prevent_change. Consulte Requirements. Um ID de assinatura inexistente ou que não pertença à sua conta retorna 404 com o código NOT_FOUND.500 Internal Server Error
500 Internal Server Error
Formato da resposta de erro
Os erros retornam um corpo JSON com umcode e um message legível por humanos:
Próximas etapas
- Consulte a Change Plan API
- Explore Credit-Based Billing
- Implemente alertas para
subscription.on_hold - Consulte o Webhook Integration Guide