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 ou 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: mantém a assinatura no plano atual até que o pagamento seja bem-sucedidoapply_change(padrão): aplica a alteração do plano imediatamente, independentemente do resultado do pagamento
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.subscription_id, payment_id e status. Requer collect_via_payment_link: true; caso contrário, a solicitação falha com 422. Consulte Redirecionando o Cliente Após o Pagamento.409. Consulte Substituindo um Link de Pagamento Pendente. 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 por 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. Use esta 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 do 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 do plano falhou, renovações interrompidaspayment.succeeded: cobrança imediata da alteração do plano bem-sucedidapayment.failed: cobrança imediata falhou
Update Your Application State
- Conceda/revoque recursos com base no novo plano
- Atualize o dashboard do cliente com os detalhes do novo plano
- Envie e-mails de confirmação sobre alterações de plano
- Registre as alterações de cobrança para fins de auditoria
Test and Monitor
- Teste todos os modos de proration com 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
immediate_charge.summary, customer_credits é a alteração líquida no saldo de crédito do cliente, na moeda indicada por customer_credits_currency. Essa é a moeda da carteira de créditos do cliente, que corresponde à moeda da assinatura. Ela pode ser diferente de currency do resumo, que se aplica a total_amount e tax. Por exemplo, um cliente que paga em INR em uma assinatura em USD vê os créditos em USD.Change Plan API
Use a Change Plan API para modificar o produto, a quantidade e o comportamento de proration de uma assinatura ativa.Exemplos rápidos
- 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, 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 O que Acontece Enquanto o Link Não é Pago 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 ou quando você quer 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.- A solicitação define
on_payment_failure: prevent_change. Umapply_changeexplícito falha com422.
collect_via_payment_link aplica-se a qualquer alteração imediata que resulte em uma cobrança, incluindo 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 estiver pendente. Para substituir a alteração pendente, envie a nova solicitação comcancel_older_payment_link: true. Consulte Substituindo um Link de Pagamento Pendente. - Para tentar novamente após um pagamento recusado, chame
change-plannovamente para obter um novo link. - Se o link nunca for pago, ele deixará de funcionar após
expires_on— a assinatura ficará automaticamente livre 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, o agendamento original permanece enquanto o link não for pago e só será cancelado quando o link for pago — na mesma transação que aplica o novo plano.
Redirecionando o cliente após o pagamento
Definareturn_url para enviar o cliente de volta ao seu site depois que ele pagar o link:
return_url com estes parâmetros de consulta:
return_url requer collect_via_payment_link: true. Sem ele, a solicitação falha com 422.
Substituindo um link de pagamento pendente
Se o cliente sair do checkout sem pagar, definacancel_older_payment_link: true na próxima solicitação change-plan. Dodo Payments cancela o link não pago, e a nova alteração de plano substitui a pendente. O link cancelado não aceita mais pagamentos, mesmo em uma página de checkout já aberta.
change-plan emite sua própria fatura. A alteração de plano substituída e sua fatura são canceladas. Se não houver uma alteração de plano pendente, cancel_older_payment_link não terá efeito.
Gerenciando addons
Ao alterar planos de assinatura, você também pode modificar addons:Aplicando 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 por 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
- Credita a parte não utilizada do ciclo atual — plano base, quantidade e addons — proporcionalmente ao tempo restante
- Em seguida, cobra um ciclo completo no novo plano, quantidade e addons. A cobrança em si nunca é proporcional
- Cobrança imediata líquida = (novo ciclo completo) − (fração restante × ciclo antigo completo)
- Se o crédito exceder a cobrança do novo ciclo (comum em downgrades), a diferença será mantida como crédito no escopo da assinatura para renovações futuras
- Se estiver em período de teste, cobra imediatamente e muda para o novo plano agora
full_immediately
- Cobra imediatamente o valor total do novo plano
- Ignora o tempo restante do plano antigo — não há crédito referente ao ciclo atual
prorated_immediately e por downgrades usando difference_immediately pertencem ao escopo da assinatura e são 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 nenhum 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 valores 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 do 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
Lidando com 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 bem-sucedido - Ú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
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 do 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:Lidando com 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
Verifique assinaturas e trate intenções
- Next.js Route Handler
- Express.js
Práticas recomendadas
Estratégia de alteração de plano
- Teste completamente: sempre teste as alterações de plano no modo de teste antes da produção
- Escolha o proration com cuidado: selecione o modo de proration alinhado ao seu modelo de negócio
- Lide com 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 os prazos
- Forneça confirmações: envie confirmações por e-mail para alterações de plano bem-sucedidas
- Lide com casos extremos: considere períodos de teste, prorations e pagamentos malsucedidos
- Atualize a interface 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 atrasou
- O estado da aplicação não foi atualizado após o recebimento dos webhooks
- Problemas de 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 proration: downgrades creditam a diferença total de preço do plano com
difference_immediately, enquantoprorated_immediatelycredita o tempo não utilizado do ciclo antigo e cobra um ciclo completo no 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 portal do cliente para exibir saldos de crédito
- Verifique o preview da próxima fatura para ver 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 análise JSON
- Use a biblioteca padrão de verificação de webhooks para 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
- Confira 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
- Banco recusou a transação
- 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 do 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 pendentes
- 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 do plano falha)payment.succeeded: pagamento dos valores pendentes bem-sucedido (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 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 de novas tentativas automáticas para falhas temporárias de pagamento
Update Payment Method API Reference
Testando sua implementação
Teste completamente sua implementação de alteração de plano da assinatura:Set up test environment
- Use chaves de API 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 várias posições no ciclo de cobrança - Teste
difference_immediatelypara upgrades e downgrades - Teste
full_immediatelypara reiniciar ciclos de cobrança - Teste
do_not_billpara alterações 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 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
ChangePlanResponse com payment_id, payment_link, client_secret e expires_on. Todos os quatro aceitam nulo, portanto o corpo é serializado como {} para uma alteração comum fora da sessão; eles são preenchidos para uma solicitação 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 bem-sucedido.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 de link de pagamento pendente, envie a nova solicitação com cancel_older_payment_link: true para substituí-la. Consulte Substituindo um Link de Pagamento Pendente.Com cancel_older_payment_link: true, um 409 significa que o cliente está pagando o link anterior agora (PLAN_CHANGE_PAYMENT_IN_PROGRESS) ou que já o pagou (PLAN_CHANGE_PAYMENT_ALREADY_COMPLETED).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 Requisitos. Um ID de assinatura que não existe ou não pertence à 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 - Confira o Guia de integração de webhooks