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 dell’azienda (Settings → Subscriptions → Collect Plan Change Payments by Payment Link), effective_at: immediately e on_payment_failure: prevent_change. Consulta Collecting Payment via a Checkout Link.Ignorato dalla route di anteprima.- Non fornito /
null— gli sconti esistenti conpreserve_on_plan_change=truevengono mantenuti, se applicabili al nuovo prodotto. [](array vuoto) — rimuove tutti gli sconti esistenti dall’abbonamento.["CODE_A", "CODE_B", ...]— sostituisce gli eventuali sconti esistenti con questo insieme stacked.
discount_codes. Questo campo continua a funzionare per la compatibilità con le versioni precedenti, ma non può essere combinato con discount_codes nella stessa richiesta.immediately(predefinito): applica subito la modifica del pianonext_billing_date: pianifica la modifica per la prossima data di fatturazione. Il cliente mantiene il piano attuale fino alla fine del periodo di fatturazione.
next_billing_date per i downgrade, così i clienti mantengono i vantaggi del piano attuale fino alla fine del periodo di fatturazione.Handle Webhook Events
subscription.active: modifica del piano completata, abbonamento aggiornatosubscription.plan_changed: piano dell’abbonamento modificato (upgrade/downgrade/aggiornamento dell’addon)subscription.on_hold: addebito della modifica del piano non riuscito, rinnovi interrottipayment.succeeded: addebito immediato della modifica del piano completatopayment.failed: addebito immediato non riuscito
Update Your Application State
- Concedi/revoca le funzionalità in base al nuovo piano
- Aggiorna il dashboard del cliente con i dettagli del nuovo piano
- Invia email di conferma sulle modifiche del piano
- Registra le modifiche di fatturazione per scopi di audit
Test and Monitor
- Testa tutte le modalità di prorazione con scenari diversi
- Verifica che la gestione dei webhook funzioni correttamente
- Monitora i tassi di successo delle modifiche del piano
- Configura avvisi per le modifiche del piano non riuscite
Anteprima delle modifiche del piano
Prima di confermare una modifica del piano, usa l’API Preview per mostrare ai clienti esattamente quanto verrà loro addebitato:- Node.js SDK
- Python SDK
API Change Plan
Usa l’API Change Plan per modificare prodotto, quantità e comportamento della prorazione per un abbonamento attivo.Esempi per iniziare rapidamente
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
200 OK, prima che qualsiasi addebito sia stato effettivamente saldato. Il contenuto del body (ChangePlanResponse) dipende da come è stata riscossa la modifica:
collect_via_payment_link, l’esito viene determinato più tardi e in modo asincrono: la risposta ti fornisce solo un link di checkout, l’abbonamento rimane sul piano attuale e l’esito non è noto finché il cliente non completa effettivamente il pagamento tramite quel link.In entrambi i casi, non dedurre l’esito da questa risposta. Confermalo tramite webhook (payment.succeeded, payment.failed, subscription.plan_changed) oppure rileggendo l’abbonamento con GET /subscriptions/{subscription_id} — per il caso del payment link nello specifico, consulta What Happens While the Link Is Unpaid.Raccolta del pagamento tramite un link di checkout
Per impostazione predefinita, una modifica immediata del piano addebita direttamente il metodo di pagamento salvato dell’abbonamento. Impostacollect_via_payment_link: true per inviare il cliente a una pagina di checkout ospitata: è utile quando non esiste un metodo di pagamento salvato che puoi addebitare fuori sessione o quando vuoi che il cliente confermi attivamente il nuovo prezzo.
Requisiti
collect_via_payment_link: true ha esito positivo solo quando sono soddisfatte tutte le condizioni seguenti; in caso contrario, la richiesta non va a buon fine con 422:
- L’azienda ha abilitato la capability
allow_plan_change_via_payment_link(Settings → Subscriptions → Collect Plan Change Payments by Payment Link). effective_atèimmediately(il valore predefinito). Una modifica pianificata (next_billing_date) non richiede mai una pagina di checkout, poiché non viene addebitato nulla fino alla sua applicazione.on_payment_failureeffettivo restituisceprevent_change. Non è necessario inviarlo esplicitamente: se il valore predefinito a livello aziendale (vedi Business & Collection Defaults di seguito) è giàprevent_change, anche omettere il campo soddisfa questo requisito. Unapply_changeesplicito, o un valore predefinito risolto inapply_change, non va a buon fine con422.
collect_via_payment_link non è limitato agli upgrade: si applica a qualsiasi modifica immediata che comporti un addebito, inclusi i downgrade, purché siano soddisfatti i requisiti precedenti.proration_billing_mode: do_not_bill, oppure un’altra modalità che in questo ciclo risulti pari a zero — non c’è nulla da inserire in una pagina di checkout. Non viene emesso alcun payment link, payment_link e gli altri campi simili restituiscono null, e la modifica viene applicata immediatamente, proprio come avverrebbe senza collect_via_payment_link. Questo non è un 422: il flag ha effetto solo quando c’è un importo positivo da riscuotere. Se imposti collect_via_payment_link sulle modifiche del piano in generale, anziché solo sugli upgrade evidenti, chiama prima Preview Plan Change e richiedi un link solo quando l’importo visualizzato in anteprima vale la pena di essere riscosso.
- Node.js SDK
- Python SDK
- HTTP
Cosa succede quando il link non è stato pagato
- L’abbonamento rimane sul piano attuale:
product_id,recurring_pre_tax_amountenext_billing_daterimangono invariati finché il link non viene pagato. - Un’ulteriore richiesta
change-plansullo stesso abbonamento viene rifiutata con409 PendingPlanChangeExistsmentre il link è in attesa. Se necessario, annulla una modifica pianificata conDELETE /subscriptions/{subscription_id}/change-plan/scheduled, ma quell’endpoint non annulla una modifica tramite payment link in attesa: solo un pagamento completato o la scadenza possono farlo. - Il cliente può ritentare il pagamento con la carta nella stessa sessione di checkout dopo un rifiuto; una nuova chiamata
change-plannon è il percorso per ritentare il pagamento. - Se il link non viene mai pagato, smette di funzionare dopo
expires_on; poco dopo, l’abbonamento diventa automaticamente disponibile per accettare una nuova richiesta di modifica del piano. - Se esisteva già una modifica pianificata (
next_billing_date) e la sostituisci concancel_scheduled_change_plan: true, la pianificazione originale rimane attiva mentre il link non è pagato e viene annullata solo dopo il pagamento del link, nella stessa transazione che applica il nuovo piano.
Gestione degli addon
Quando modifichi i piani degli abbonamenti, puoi modificare anche gli addon:Applicazione dei codici sconto
Puoi applicare uno o più codici sconto stacked quando modifichi i piani degli abbonamenti (massimo 20, applicati nell’ordine dell’array). È utile per offrire prezzi promozionali su upgrade o migrazioni.- Node.js SDK
- Python SDK
- HTTP
Comportamento degli sconti durante la modifica del piano
discount_code su questo endpoint è deprecato, ma continua a funzionare per la compatibilità con le versioni precedenti: le integrazioni esistenti non devono essere modificate immediatamente. Non può essere combinato con discount_codes nella stessa richiesta. Esegui la migrazione al formato array quando preferisci.Modalità di prorazione
Scegli come addebitare il cliente quando modifichi i piani:prorated_immediately
- Addebita la differenza parziale per il ciclo attuale
- Se il cliente è in prova, addebita immediatamente e passa subito al nuovo piano
- Downgrade: può generare un credito prorato applicato ai rinnovi futuri
full_immediately
- Addebita immediatamente l’intero importo del nuovo piano
- Ignora il tempo rimanente del vecchio piano
difference_immediately sono associati all’abbonamento e distinti dalle entitlements di Credit-Based Billing. Vengono applicati automaticamente ai rinnovi futuri dello stesso abbonamento e non sono trasferibili tra abbonamenti.difference_immediately
- Upgrade: addebita immediatamente la differenza di prezzo tra il vecchio e il nuovo piano
- Downgrade: aggiunge il valore rimanente come credito interno all’abbonamento e lo applica automaticamente ai rinnovi
do_not_bill
- Non vengono calcolati addebiti o crediti
- Il cliente passa immediatamente al nuovo piano senza alcun adeguamento di fatturazione
- Il ciclo di fatturazione rimane invariato
- Ideale per migrazioni di cortesia, passaggi a piani gratuiti o assorbimento delle differenze di costo
Scenari di esempio
Usa questi valori canonici in modo coerente:- Piano attuale: Basic a $30/mese
- Obiettivo dell’upgrade: Pro a $80/mese
- Obiettivo del downgrade (da Pro): Starter a $20/mese
- Ciclo di fatturazione: 30 giorni, iniziato il January 1
- La modifica del piano avviene il January 16 (15 giorni rimanenti, 15 giorni utilizzati)
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
Come ogni modalità gestisce la fatturazione
Gestione dei pagamenti non riusciti
Controlla cosa succede quando il pagamento di una modifica del piano non riesce usando il parametroon_payment_failure.
Modalità di pagamento non riuscito
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- La modifica del piano viene contrassegnata come “pending”
- Il cliente mantiene l’accesso al piano attuale
- L’abbonamento passa allo stato
activesolo dopo il pagamento completato - Utile quando vuoi assicurarti del pagamento prima di concedere le funzionalità dell’upgrade
on_payment_failure usa l’impostazione predefinita a livello aziendale configurata nel dashboard.Quando usare ciascuna modalità
Impostazioni predefinite aziendali e di raccolta
Invece di passare i parametri di prorazione a ogni modifica del piano, puoi impostare una volta il comportamento predefinito per upgrade e downgrade a livello aziendale. Queste impostazioni predefinite si applicano a tutte le modifiche del piano dal portale clienti e possono essere sostituite per ogni raccolta di prodotti. Esistono impostazioni predefinite separate per upgrade e downgrade:Ordine di risoluzione
Per qualsiasi modifica del piano, ogni impostazione viene risolta nel seguente ordine:Gestione dei webhook
Monitora lo stato dell’abbonamento tramite webhook per confermare le modifiche del piano e i pagamenti.Tipi di eventi da gestire
subscription.active: abbonamento attivatosubscription.plan_changed: piano dell’abbonamento modificato (modifiche di upgrade/downgrade/addon)subscription.on_hold: addebito non riuscito, rinnovi interrottisubscription.renewed: rinnovo completatopayment.succeeded: pagamento della modifica del piano o del rinnovo completatopayment.failed: pagamento non riuscito
Verifica delle firme e gestione degli intent
- Next.js Route Handler
- Express.js
Procedure consigliate
Segui queste raccomandazioni per modifiche affidabili dei piani degli abbonamenti:Strategia di modifica del piano
- Testa accuratamente: testa sempre le modifiche del piano in modalità test prima della produzione
- Scegli attentamente la prorazione: seleziona la modalità di prorazione in linea con il tuo modello aziendale
- Gestisci correttamente gli errori: implementa una gestione degli errori e una logica di retry adeguate
- Monitora i tassi di successo: monitora i tassi di successo/errore delle modifiche del piano e analizza i problemi
Implementazione dei webhook
- Verifica le firme: convalida sempre le firme dei webhook per garantirne l’autenticità
- Implementa l’idempotenza: gestisci correttamente gli eventi webhook duplicati
- Elabora in modo asincrono: non bloccare le risposte dei webhook con operazioni pesanti
- Registra tutto: mantieni log dettagliati per il debug e gli audit
Esperienza utente
- Comunica chiaramente: informa i clienti sulle modifiche di fatturazione e sulle tempistiche
- Fornisci conferme: invia email di conferma per le modifiche del piano completate
- Gestisci i casi limite: considera periodi di prova, prorazioni e pagamenti non riusciti
- Aggiorna subito l’interfaccia: rifletti le modifiche del piano nell’interfaccia della tua applicazione
Problemi comuni e soluzioni
Risolvi i problemi tipici riscontrati durante le modifiche dei piani degli abbonamenti:Charge created but subscription not updated
Charge created but subscription not updated
- L’elaborazione del webhook non è riuscita o è stata ritardata
- Lo stato dell’applicazione non è stato aggiornato dopo la ricezione dei webhook
- Problemi nelle transazioni del database durante l’aggiornamento dello stato
- Implementa una gestione robusta dei webhook con logica di retry
- Usa operazioni idempotenti per gli aggiornamenti dello stato
- Aggiungi il monitoraggio per rilevare e segnalare gli eventi webhook mancanti
- Verifica che l’endpoint webhook sia accessibile e risponda correttamente
Credits not applied after downgrade
Credits not applied after downgrade
- Aspettative sulla modalità di prorazione: i downgrade accreditano l’intera differenza di prezzo del piano con
difference_immediately, mentreprorated_immediatelycrea un credito prorato basato sul tempo rimanente del ciclo - I crediti sono specifici dell’abbonamento e non vengono trasferiti tra abbonamenti
- Il saldo dei crediti non è visibile nel dashboard del cliente
- Usa
difference_immediatelyper i downgrade quando vuoi crediti automatici - Spiega ai clienti che i crediti si applicano ai rinnovi futuri dello stesso abbonamento
- Implementa il portale clienti per mostrare i saldi dei crediti
- Controlla l’anteprima della prossima fattura per visualizzare i crediti applicati
Webhook signature verification fails
Webhook signature verification fails
- Chiave segreta del webhook errata
- Body della richiesta raw modificato prima della verifica della firma
- Algoritmo di verifica della firma errato
- Verifica di usare il corretto
DODO_WEBHOOK_SECRETdal dashboard - Leggi il body raw della richiesta prima di qualsiasi middleware di parsing JSON
- Usa la libreria standard di verifica dei webhook per la tua piattaforma
- Testa la verifica della firma dei webhook nell’ambiente di sviluppo
Plan change fails with 422 error
Plan change fails with 422 error
- ID dell’abbonamento o ID del prodotto non validi
- Abbonamento non nello stato attivo
- Parametri obbligatori mancanti
- Prodotto non disponibile per le modifiche del piano
- Verifica che l’abbonamento esista e sia attivo
- Controlla che l’ID del prodotto sia valido e disponibile
- Assicurati che siano forniti tutti i parametri obbligatori
- Consulta la documentazione API per i requisiti dei parametri
Immediate charge fails during plan change
Immediate charge fails during plan change
- Fondi insufficienti sul metodo di pagamento del cliente
- Metodo di pagamento scaduto o non valido
- La banca ha rifiutato la transazione
- Il rilevamento delle frodi ha bloccato l’addebito
- Gestisci opportunamente gli eventi webhook
payment.failed - Informa il cliente di aggiornare il metodo di pagamento
- Implementa una logica di retry per gli errori temporanei
- Valuta di consentire modifiche del piano con addebiti immediati non riusciti
Subscription on hold after plan change
Subscription on hold after plan change
on_holdCosa succede:
Quando l’addebito di una modifica del piano non riesce, l’abbonamento viene automaticamente impostato sullo stato on_hold. L’abbonamento non verrà rinnovato automaticamente finché il metodo di pagamento non viene aggiornato.Soluzione: aggiorna il metodo di pagamento per riattivare l’abbonamentoPer riattivare un abbonamento nello stato on_hold dopo una modifica del piano non riuscita:- Aggiorna il metodo di pagamento usando l’API Update Payment Method
- Creazione automatica dell’addebito: l’API crea automaticamente un addebito per gli importi ancora dovuti
- Generazione della fattura: viene generata una fattura per l’addebito
- Elaborazione del pagamento: il pagamento viene elaborato usando il nuovo metodo di pagamento
- Riattivazione: dopo il pagamento completato, l’abbonamento viene riattivato allo stato
active
subscription.on_hold: abbonamento sospeso (ricevuto quando l’addebito della modifica del piano non riesce)payment.succeeded: pagamento degli importi ancora dovuti completato (dopo l’aggiornamento del metodo di pagamento)subscription.active: abbonamento riattivato dopo il pagamento completato
- Informa immediatamente i clienti quando l’addebito di una modifica del piano non riesce
- Fornisci istruzioni chiare su come aggiornare il metodo di pagamento
- Monitora gli eventi webhook per tenere traccia dello stato di riattivazione
- Valuta di implementare una logica di retry automatica per i pagamenti temporaneamente non riusciti
Update Payment Method API Reference
Test della tua implementazione
Segui questi passaggi per testare accuratamente l’implementazione delle modifiche del piano degli abbonamenti:Set up test environment
- Usa chiavi API di test e prodotti di test
- Crea abbonamenti di test con diversi tipi di piano
- Configura l’endpoint webhook di test
- Configura il monitoraggio e il logging
Test different proration modes
- Testa
prorated_immediatelycon diverse posizioni nel ciclo di fatturazione - Testa
difference_immediatelyper upgrade e downgrade - Testa
full_immediatelyper reimpostare i cicli di fatturazione - Testa
do_not_billper passaggi di piano senza addebiti o crediti - Verifica che i calcoli dei crediti siano corretti
Test webhook handling
- Verifica che vengano ricevuti tutti gli eventi webhook pertinenti
- Testa la verifica delle firme dei webhook
- Gestisci correttamente gli eventi webhook duplicati
- Testa gli scenari di errore nell’elaborazione dei webhook
Test error scenarios
- Testa con ID di abbonamento non validi
- Testa con metodi di pagamento scaduti
- Testa errori di rete e timeout
- Testa con fondi insufficienti
Monitor in production
- Configura avvisi per le modifiche del piano non riuscite
- Monitora i tempi di elaborazione dei webhook
- Monitora i tassi di successo delle modifiche del piano
- Esamina i ticket dell’assistenza clienti relativi ai problemi delle modifiche del piano
Gestione degli errori
Gestisci correttamente gli errori API comuni nella tua implementazione:Codici di stato HTTP
200 OK
200 OK
collect_via_payment_link completata, che restituisce i riferimenti al checkout: consulta Collecting Payment via a Checkout Link. Se on_payment_failure=prevent_change, la modifica del piano rimane in attesa finché il pagamento non va a buon fine.400 Bad Request
400 Bad Request
404 Not Found
404 Not Found
409 Conflict
409 Conflict
PendingPlanChangeExists). Per una modifica pianificata, annullala con DELETE /subscriptions/{subscription_id}/change-plan/scheduled prima di inviarne una nuova. Per una modifica payment link in attesa, non esiste alcun endpoint di annullamento: l’abbonamento accetta una nuova richiesta di modifica del piano quando il cliente paga o il link scade.422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_link: l’azienda non ha abilitato la capability, effective_at non è immediately oppure on_payment_failure non è prevent_change. Consulta Requirements.500 Internal Server Error
500 Internal Server Error
Formato della risposta di errore
Passaggi successivi
- Consulta la Change Plan API
- Esplora Credit-Based Billing
- Implementa avvisi per
subscription.on_hold - Consulta la nostra Webhook Integration Guide