Change Plan API
Plan Change Preview
Integration Guide
What is a subscription upgrade or downgrade?
Changing plans lets you move a customer between subscription tiers or quantities. Use it to:- Align pricing with usage or features
- Move from monthly to annual (or vice versa)
- Adjust quantity for seat-based products
When to use plan changes
- 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
- Calculates exact prorated amount based on remaining cycle time
- Charges a prorated amount based on unused time remaining in the cycle
- Provides transparent billing to customers
Implement the Change Plan API
prorated_immediately, full_immediately, difference_immediately, or do_not_bill.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 da empresa (Settings → Subscriptions → Collect Plan Change Payments by Payment Link), effective_at: immediately e on_payment_failure: prevent_change. Consulte Coletando pagamento por meio de um link de checkout.Ignorado pela rota de preview.- Não informado /
null— os descontos existentes compreserve_on_plan_change=truesão preservados quando 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 do 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.
next_billing_date 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 do plano concluída, assinatura atualizadasubscription.plan_changed: plano da assinatura alterado (upgrade/downgrade/atualização de addon)subscription.on_hold: cobrança da alteração do plano falhou, renovações interrompidaspayment.succeeded: cobrança imediata da alteração do plano concluídapayment.failed: cobrança imediata falhou
Update Your Application State
- Conceda ou revogue recursos com base no novo plano
- Atualize o dashboard do cliente com os detalhes do novo plano
- Envie emails de confirmação sobre as alterações do plano
- Registre as alterações de cobrança para fins de auditoria
Test and Monitor
- Teste todos os modos de proration 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 malsucedidas
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 de proration 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 coletada:
collect_via_payment_link, o resultado é resolvido posteriormente e de forma assíncrona — a resposta fornece apenas um link de checkout, a assinatura permanece no plano atual e nada se sabe sobre o resultado até que o cliente conclua o pagamento nesse link.De qualquer forma, não deduza o resultado a partir desta resposta. Confirme-o por meio de um webhook (payment.succeeded, payment.failed, subscription.plan_changed) ou lendo novamente a assinatura com GET /subscriptions/{subscription_id} — consulte O que acontece enquanto o link não é pago especificamente para o caso de link de pagamento.Coletando 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 que você possa cobrar fora da sessão ou quando você quer que o cliente confirme ativamente o novo preço.
Requisitos
collect_via_payment_link: true só funciona quando todos os requisitos a seguir são atendidos — caso contrário, a solicitação falha com 422:
- A empresa tem a capacidade
allow_plan_change_via_payment_linkhabilitada (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, pois nada é cobrado até que seja aplicada.- O
on_payment_failureefetivo é resolvido comoprevent_change. Você não precisa enviá-lo explicitamente — se o padrão no nível da empresa (consulte Padrões da empresa e de cobrança abaixo) já forprevent_change, omitir o campo também atende a esse requisito. Umapply_changeexplícito ou um padrão resolvido comoapply_changefalha com422.
collect_via_payment_link não se limita a upgrades — ele se aplica a qualquer alteração imediata que resulte em uma cobrança, incluindo downgrades, desde que os requisitos acima sejam atendidos.proration_billing_mode: do_not_bill ou outro modo que ocasionalmente resulte em zero neste ciclo — não há nada a colocar em uma página de checkout. Nenhum link de pagamento é emitido, payment_link e similares retornam null, e a alteração é aplicada imediatamente, da mesma forma que seria sem collect_via_payment_link. Isso não é um 422; o sinalizador só tem efeito quando há um valor positivo a cobrar. Se você definir collect_via_payment_link genericamente nas alterações de plano, em vez de usá-lo apenas em upgrades claros, chame Preview Plan Change primeiro e solicite um link somente quando o valor exibido na preview justificar a cobrança.
- 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-planpara a mesma assinatura é rejeitada com409 PendingPlanChangeExistsenquanto o link estiver pendente. Cancele uma alteração agendada comDELETE /subscriptions/{subscription_id}/change-plan/scheduledse necessário, mas esse endpoint não cancela uma alteração pendente por link de pagamento — apenas um pagamento bem-sucedido ou a expiração faz isso. - O cliente pode tentar novamente com 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 será automaticamente liberada para aceitar uma nova solicitação de alteração de plano pouco depois. - Se já existia uma alteração agendada (
next_billing_date) e você a substituir porcancel_scheduled_change_plan: true, o agendamento original permanece enquanto o link não for pago e só é cancelado quando o link é pago — na mesma transação que aplica o novo plano.
Gerenciando addons
Ao alterar os planos de assinatura, você também pode modificar addons:Aplicando códigos de desconto
Você pode aplicar um ou mais códigos de desconto empilhados ao alterar os planos de assinatura (máx. 20, aplicados na ordem do array). Isso é útil para oferecer preços promocionais em upgrades ou migrações.- 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 proration
Escolha como cobrar o cliente ao alterar os planos:prorated_immediately
- Cobra a diferença proporcional referente ao ciclo atual
- Se estiver em trial, cobra imediatamente e muda para o novo plano agora
- Downgrade: pode gerar um crédito proporcional aplicado a renovações futuras
full_immediately
- Cobra imediatamente o valor total do novo plano
- Ignora o tempo restante do plano antigo
difference_immediately são específicos da 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 de 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 (do Pro): Starter a $20/mês
- Ciclo de cobrança: 30 dias, iniciado em 1º de janeiro
- A alteração do plano ocorre em 16 de janeiro (15 dias restantes, 15 dias usados)
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
Tratando 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 do plano é marcada como “pendente”
- O cliente mantém acesso ao plano atual
- A assinatura só passa para o estado
activeapós o pagamento ser concluído - Útil quando você quer garantir o pagamento antes de conceder recursos atualizados
on_payment_failure usará a configuração padrão no nível da empresa definida no dashboard.Quando usar cada modo
Padrões da empresa e de cobrança
Em vez de enviar parâmetros de proration em cada alteração de plano, você pode definir o comportamento padrão de upgrade e downgrade uma vez no nível da empresa. Esses padrões se aplicam a todas as alterações de plano no portal do cliente e podem ser substituídos por coleção de produtos. Há padrões separados para upgrades e downgrades:Ordem de resolução
Para qualquer alteração de plano, cada configuração é resolvida nesta ordem:Tratando 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 concluídapayment.succeeded: pagamento da alteração do plano ou renovação concluídopayment.failed: pagamento falhou
Verifique assinaturas e trate intents
- Next.js Route Handler
- Express.js
Práticas recomendadas
Siga estas recomendações para alterações confiáveis de planos de assinatura:Estratégia de alteração de plano
- Teste detalhadamente: sempre teste as alterações de plano em modo de teste antes da produção
- Escolha o proration com cuidado: selecione o modo de proration alinhado ao seu modelo de negócios
- Trate as falhas de forma adequada: 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 seus prazos
- Forneça confirmações: envie emails de confirmação para alterações de plano bem-sucedidas
- Trate casos extremos: considere períodos de trial, proration e pagamentos malsucedidos
- Atualize a UI imediatamente: reflita as alterações de plano na interface da sua 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 um tratamento robusto 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 não recebidos
- Verifique se o endpoint de webhook está acessível e respondendo corretamente
Credits not applied after downgrade
Credits not applied after downgrade
- Expectativas em relação ao modo de proration: downgrades creditam a diferença total de preço do plano com
difference_immediately, enquantoprorated_immediatelycria um crédito proporcional com base no tempo restante do ciclo - 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 portal do cliente para exibir os saldos de crédito
- Verifique a preview da próxima invoice para ver os créditos aplicados
Webhook signature verification fails
Webhook signature verification fails
- Chave secreta de webhook incorreta
- Corpo bruto da solicitação modificado antes da verificação da assinatura
- Algoritmo incorreto de verificação da assinatura
- Verifique se você está usando o
DODO_WEBHOOK_SECRETcorreto do dashboard - Leia o corpo bruto da solicitação antes de qualquer middleware de parsing JSON
- Use a biblioteca padrão de verificação de webhook 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 não disponível para alterações de plano
- Verifique se a assinatura existe e está ativa
- Verifique 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 malsucedidas
Subscription on hold after plan change
Subscription on hold after plan change
on_holdO que acontece:
Quando uma cobrança de 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 invoice: uma invoice é 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 do plano falha)payment.succeeded: pagamento dos valores restantes concluído (após a atualização do método de pagamento)subscription.active: assinatura reativada após pagamento bem-sucedido
- Notifique os clientes imediatamente quando uma cobrança de alteração do 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 de novas tentativas automáticas para falhas temporárias de pagamento
Update Payment Method API Reference
Testando sua implementação
Siga estas etapas para testar 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 o endpoint de webhook de teste
- Configure monitoramento e logging
Test different proration modes
- Teste
prorated_immediatelyem várias posições do ciclo de cobrança - Teste
difference_immediatelypara upgrades e downgrades - Teste
full_immediatelypara reiniciar os 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 da assinatura do webhook
- 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 e timeouts de rede
- 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 tickets de suporte ao cliente relacionados a problemas de alteração de plano
Tratamento de erros
Trate os erros comuns da API adequadamente em sua implementação:Códigos de status HTTP
200 OK
200 OK
collect_via_payment_link bem-sucedida, que retorna identificadores de checkout — consulte Coletando pagamento por meio de um link de checkout. Se on_payment_failure=prevent_change, a alteração do plano permanece pendente até que o pagamento seja concluído.400 Bad Request
400 Bad Request
404 Not Found
404 Not Found
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 link de pagamento pendente, não há endpoint de cancelamento — a assinatura aceita uma nova solicitação de alteração de plano quando o cliente paga ou o link expira.422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_link — a empresa não tem a capacidade habilitada, effective_at não é immediately ou on_payment_failure não é prevent_change. Consulte Requisitos.500 Internal Server Error
500 Internal Server Error
Formato da resposta de erro
Próximas etapas
- Consulte a Change Plan API
- Explore o Credit-Based Billing
- Implemente alertas para
subscription.on_hold - Confira nosso Guia de integração de Webhooks