Change Plan API
Plan Change Preview
Integration Guide
Vad är en uppgradering eller nedgradering av en prenumeration?
Ändra kundens prenumerationsplan för att flytta dem mellan nivåer, justera kvantiteten för sätesbaserade produkter eller migrera till en ny produkt. API:t beräknar automatiskt proportionella belopp och debiteringar baserat på det valda debiteringsläget.När ska planändringar användas?
- 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
- Krediterar den oanvända delen av den aktuella cykeln, proportionellt efter återstående tid
- Debiterar sedan en hel cykel för den nya planen – priset för den nya planen proportioneras aldrig
- Nettodebitering = hel ny cykel − (återstående andel × hel gammal cykel)
Implement the Change Plan API
prorated_immediately, full_immediately, difference_immediately, or do_not_bill.null eller skickar en tom array tas alla befintliga tillägg bort, så inkludera befintliga tillägg för att behålla dem.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-funktion (Settings → Subscriptions → Collect Plan Change Payments by Payment Link), effective_at: immediately och on_payment_failure: prevent_change. Se Collecting Payment via a Checkout Link. Ignoreras av förhandsgranskningsrutten.- Inte angivet /
null– befintliga rabatter medpreserve_on_plan_change=truebevaras om de gäller för den nya produkten. [](tom array) – tar bort alla befintliga rabatter från prenumerationen.["CODE_A", "CODE_B", ...]– ersätter alla befintliga rabatter med denna staplade uppsättning.
discount_codes för nya integrationer. Fältet fungerar fortfarande för bakåtkompatibilitet, men kan inte kombineras med discount_codes i samma begäran.immediately(standard): Tillämpa planändringen direktnext_billing_date: Schemalägg ändringen till nästa debiteringsdatum. Kunden behåller sin aktuella plan tills debiteringsperioden slutar. Använd detta för nedgraderingar så att kunderna behåller förmånerna från sin aktuella plan fram till debiteringsperiodens slut.
Handle Webhook Events
subscription.active: Planändringen lyckades, prenumerationen uppdateradessubscription.plan_changed: Prenumerationsplanen ändrades (uppgradering/nedgradering/tilläggsuppdatering)subscription.on_hold: Debiteringen för planändringen misslyckades, förnyelser stoppadespayment.succeeded: Den omedelbara debiteringen för planändringen lyckadespayment.failed: Den omedelbara debiteringen misslyckades
Update Your Application State
- Bevilja/återkalla funktioner baserat på den nya planen
- Uppdatera kundens dashboard med information om den nya planen
- Skicka bekräftelsemeddelanden om planändringar
- Logga debiteringsändringar för granskningsändamål
Test and Monitor
- Testa alla proportioneringslägen med olika scenarier
- Kontrollera att webhook-hanteringen fungerar korrekt
- Övervaka hur ofta planändringar lyckas
- Konfigurera aviseringar för misslyckade planändringar
Förhandsgranska planändringar
Innan du genomför en planändring kan du använda Preview API för att visa kunderna exakt vad de kommer att debiteras:- Node.js SDK
- Python SDK
Change Plan API
Använd Change Plan API för att ändra produkt, kvantitet och proportioneringsbeteende för en aktiv prenumeration.Snabbstartsexempel
- Node.js SDK
- Python SDK
- Go SDK
- HTTP
200 OK omedelbart – innan någon debitering faktiskt har slutförts. Vad body (ChangePlanResponse) innehåller beror på hur ändringen samlades in:
collect_via_payment_link ligger prenumerationen kvar på sin aktuella plan tills kunden slutför betalningen.Bekräfta resultatet via webhook (payment.succeeded, payment.failed, subscription.plan_changed) eller genom att läsa prenumerationen igen med GET /subscriptions/{subscription_id} – se What Happens While the Link Is Unpaid för fallet med betalningslänk.Samla in betalning via en checkout-länk
Som standard debiterar en omedelbar planändring prenumerationens sparade betalningsmetod direkt. Angecollect_via_payment_link: true för att i stället skicka kunden till en hostad checkout-sida – användbart när det saknas en sparad betalningsmetod eller när du vill att kunden aktivt ska bekräfta det nya priset.
Krav
collect_via_payment_link: true lyckas endast när alla följande villkor är uppfyllda – annars misslyckas begäran med 422:
- Företaget har funktionen
allow_plan_change_via_payment_linkaktiverad (Settings → Subscriptions → Collect Plan Change Payments by Payment Link). effective_atärimmediately(standardvärdet). En schemalagd ändring (next_billing_date) behöver aldrig en checkout-sida.- Det effektiva värdet för
on_payment_failureblirprevent_change. Du behöver inte skicka det uttryckligen – om standardvärdet på företagsnivå redan ärprevent_changeräcker det att utelämna fältet. Ett uttryckligtapply_changemisslyckas med422.
collect_via_payment_link gäller för alla omedelbara ändringar som leder till en debitering, inklusive nedgraderingar, så länge kraven ovan är uppfyllda.payment_link och de andra checkout-fälten returneras som null, och ändringen tillämpas omedelbart. Detta är inte ett 422. Anropa Preview Plan Change först för att kontrollera beloppet innan du begär en länk.
- Node.js SDK
- Python SDK
- HTTP
Vad händer medan länken är obetald?
- Prenumerationen ligger kvar på sin aktuella plan –
product_id,recurring_pre_tax_amountochnext_billing_datepåverkas inte förrän länken är betald. - En ytterligare begäran med
change-planavvisas med409 PendingPlanChangeExistsmedan länken väntar. Avbryt en schemalagd ändring medDELETE /subscriptions/{subscription_id}/change-plan/scheduledvid behov, men den endpointen avbryter inte en väntande ändring via betalningslänk – endast en lyckad betalning eller att länken löper ut gör det. - Kunden kan försöka igen med ett kort i samma checkout-session efter ett avslag; ett nytt anrop med
change-planär inte rätt väg för ett nytt försök. - Om länken aldrig betalas slutar den att fungera efter
expires_on– prenumerationen blir automatiskt tillgänglig för en ny begäran om planändring kort därefter. - Om en schemalagd ändring redan fanns och du ersätter den med
cancel_scheduled_change_plan: trueligger det ursprungliga schemat kvar medan länken är obetald och avbryts först när länken betalas – i samma transaktion som tillämpar den nya planen.
Hantera tillägg
När du ändrar prenumerationsplaner kan du även ändra tillägg:Tillämpa rabattkoder
Tillämpa en eller flera staplade rabattkoder när du ändrar prenumerationsplaner (högst 20, tillämpas i arrayordning):- Node.js SDK
- Python SDK
- HTTP
Rabattbeteende vid planändring
discount_code på denna endpoint är föråldrat men fungerar fortfarande för bakåtkompatibilitet – befintliga integrationer behöver inte ändras omedelbart. Det kan inte kombineras med discount_codes i samma begäran. Migrera till arrayformatet när det passar.Proportioneringslägen
Välj hur kunden ska debiteras när du ändrar planer:prorated_immediately
- Krediterar den oanvända delen av den aktuella cykeln – basplan, kvantitet och tillägg – proportionellt efter återstående tid
- Debiterar sedan en hel cykel för den nya planen, kvantiteten och tilläggen. Själva debiteringen proportioneras aldrig
- Omedelbar nettodebitering = (hel ny cykel) − (återstående andel × hel gammal cykel)
- Om krediten överstiger debiteringen för den nya cykeln (vanligt vid nedgraderingar) sparas skillnaden som prenumerationsspecifik kredit för framtida förnyelser
- Under en provperiod debiteras kunden omedelbart och byter till den nya planen nu
full_immediately
- Debiterar det fulla beloppet för den nya planen omedelbart
- Bortser från återstående tid på den gamla planen – ingen kredit för den aktuella cykeln
prorated_immediately och av nedgraderingar med difference_immediately är prenumerationsspecifika och skiljer sig från förmåner i Credit-Based Billing. De tillämpas automatiskt på framtida förnyelser av samma prenumeration och kan inte överföras mellan prenumerationer.difference_immediately
- Uppgradering: Debiterar omedelbart prisskillnaden mellan den gamla och den nya planen
- Nedgradering: Lägger till återstående värde som intern kredit på prenumerationen och tillämpar den automatiskt vid förnyelser
do_not_bill
- Inga debiteringar eller krediter beräknas
- Kunden byter omedelbart till den nya planen utan någon debiteringsjustering
- Debiteringscykeln förblir oförändrad
- Bäst för servicebyten, kostnadsfria planbyten eller när du absorberar kostnadsskillnader
Exempelscenarier
Använd konsekvent dessa standardtal:- Aktuell plan: Basic på $30/månad
- Uppgraderingsmål: Pro på $80/månad
- Nedgraderingsmål (från Pro): Starter på $20/månad
- Debiteringscykel: 30 dagar, startade 1 januari
- Planändringen sker 16 januari (15 dagar återstår, 15 dagar har använts)
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
Så bearbetar varje läge debiteringen
Hantera betalningsfel
Styr vad som händer när en betalning för en planändring misslyckas med parameternon_payment_failure.
Lägen för betalningsfel
- prevent_change (Recommended for critical upgrades)
- apply_change (Default)
- Planändringen markeras som “väntande”
- Kunden behåller åtkomsten till sin aktuella plan
- Prenumerationen flyttas till tillståndet
activeförst efter en lyckad betalning - Användbart när du vill säkerställa betalning innan uppgraderade funktioner beviljas
on_payment_failure standardinställningen på företagsnivå som konfigurerats i dashboarden.När ska varje läge användas?
Standardinställningar för företag och insamling
Ange standardbeteende för uppgraderingar och nedgraderingar på företagsnivå under Settings → Subscriptions. Dessa standardvärden gäller för alla planändringar i kundportalen och kan åsidosättas per produktsamling. Det finns separata standardvärden för uppgraderingar och nedgraderingar:Prioritetsordning
För en viss planändring fastställs varje inställning i följande ordning:Hantera webhooks
Spåra prenumerationens tillstånd via webhooks för att bekräfta planändringar och betalningar.Händelsetyper som ska hanteras
subscription.active: prenumerationen aktiveradessubscription.plan_changed: prenumerationsplanen ändrades (uppgradering/nedgradering/tilläggsändringar)subscription.on_hold: debiteringen misslyckades, förnyelser stoppadessubscription.renewed: förnyelsen lyckadespayment.succeeded: betalningen för planändringen eller förnyelsen lyckadespayment.failed: betalningen misslyckades
Verifiera signaturer och hantera avsikter
- Next.js Route Handler
- Express.js
Bästa praxis
Strategi för planändringar
- Testa noggrant: Testa alltid planändringar i testläge före produktion
- Välj proportionering med omsorg: Välj det proportioneringsläge som passar din affärsmodell
- Hantera fel smidigt: Implementera korrekt felhantering och logik för nya försök
- Övervaka lyckade ändringar: Följ upp hur ofta planändringar lyckas/misslyckas och undersök problem
Webhook-implementation
- Verifiera signaturer: Validera alltid webhook-signaturer för att säkerställa äkthet
- Implementera idempotens: Hantera duplicerade webhook-händelser på ett smidigt sätt
- Bearbeta asynkront: Blockera inte webhook-svar med tunga operationer
- Logga allt: Upprätthåll detaljerade loggar för felsökning och granskning
Användarupplevelse
- Kommunicera tydligt: Informera kunderna om debiteringsändringar och tidpunkter
- Ge bekräftelser: Skicka e-postbekräftelser för lyckade planändringar
- Hantera specialfall: Ta hänsyn till provperioder, proportionering och misslyckade betalningar
- Uppdatera gränssnittet direkt: Visa planändringar omedelbart i applikationens gränssnitt
Vanliga problem och lösningar
Lös typiska problem som uppstår under planändringar för prenumerationer:Charge created but subscription not updated
Charge created but subscription not updated
- Webhook-bearbetningen misslyckades eller fördröjdes
- Applikationens tillstånd uppdaterades inte efter mottagna webhooks
- Problem med databastransaktioner under tillståndsuppdateringen
- Implementera webhook-hantering med logik för nya försök
- Använd idempotenta operationer för tillståndsuppdateringar
- Lägg till övervakning för att upptäcka och varna om missade webhook-händelser
- Kontrollera att webhook-endpointen är åtkomlig och svarar korrekt
Credits not applied after downgrade
Credits not applied after downgrade
- Förväntningar på proportioneringsläget: nedgraderingar krediterar hela prisskillnaden mellan planerna med
difference_immediately, medanprorated_immediatelykrediterar oanvänd tid i den gamla cykeln och sedan debiterar en hel cykel för den nya planen – ett kreditsaldo finns därför endast kvar när krediten överstiger priset för den nya planen - Krediter är prenumerationsspecifika och överförs inte mellan prenumerationer
- Kreditsaldot visas inte i kundens dashboard
- Använd
difference_immediatelyför nedgraderingar när du vill ha automatiska krediter - Förklara för kunderna att krediter tillämpas på framtida förnyelser av samma prenumeration
- Implementera kundportalen så att kreditsaldon visas
- Kontrollera förhandsgranskningen av nästa faktura för att se tillämpade krediter
Webhook signature verification fails
Webhook signature verification fails
- Felaktig hemlig webhook-nyckel
- Den råa request body ändrades före signaturverifieringen
- Fel algoritm för signaturverifiering
- Kontrollera att du använder rätt
DODO_PAYMENTS_WEBHOOK_KEYfrån dashboarden - Läs den råa request body innan någon JSON-parsningsmiddleware körs
- Använd standardbiblioteket för webhook-verifiering för din plattform
- Testa webhook-signaturverifieringen i utvecklingsmiljön
Plan change fails with 422 error
Plan change fails with 422 error
- Ogiltigt prenumerations-ID eller produkt-ID
- Prenumerationen är inte i aktivt tillstånd
- Obligatoriska parametrar saknas
- Produkten är inte tillgänglig för planändringar
- Kontrollera att prenumerationen finns och är aktiv
- Kontrollera att produkt-ID:t är giltigt och tillgängligt
- Säkerställ att alla obligatoriska parametrar har angetts
- Läs API-dokumentationen för krav på parametrar
Immediate charge fails during plan change
Immediate charge fails during plan change
- Otillräckliga medel på kundens betalningsmetod
- Betalningsmetoden har löpt ut eller är ogiltig
- Banken avvisade transaktionen
- Bedrägeridetektering blockerade debiteringen
- Hantera webhook-händelser med
payment.failedpå lämpligt sätt - Meddela kunden att betalningsmetoden måste uppdateras
- Implementera logik för nya försök vid tillfälliga fel
- Överväg att tillåta planändringar även när omedelbara debiteringar misslyckas
Subscription on hold after plan change
Subscription on hold after plan change
on_holdVad händer:
När en debitering för en planändring misslyckas placeras prenumerationen automatiskt i tillståndet on_hold. Prenumerationen förnyas inte automatiskt förrän betalningsmetoden har uppdaterats.Lösning: Uppdatera betalningsmetoden för att återaktivera prenumerationenSå här återaktiverar du en prenumeration från tillståndet on_hold efter en misslyckad planändring:- Uppdatera betalningsmetoden med Update Payment Method API
- Skapa debitering automatiskt: API:t skapar automatiskt en debitering för återstående skulder
- Skapa faktura: En faktura skapas för debiteringen
- Bearbeta betalningen: Betalningen behandlas med den nya betalningsmetoden
- Återaktivering: När betalningen lyckas återaktiveras prenumerationen till tillståndet
active
subscription.on_hold: Prenumerationen pausades (mottas när debiteringen för planändringen misslyckas)payment.succeeded: Betalningen för återstående skulder lyckades (efter uppdatering av betalningsmetoden)subscription.active: Prenumerationen återaktiverades efter lyckad betalning
- Meddela kunderna omedelbart när en debitering för en planändring misslyckas
- Ge tydliga instruktioner om hur betalningsmetoden uppdateras
- Övervaka webhook-händelser för att följa återaktiveringsstatus
- Överväg att implementera automatisk logik för nya försök vid tillfälliga betalningsfel
Update Payment Method API Reference
Testa din implementation
Testa din implementation av planändringar för prenumerationer noggrant:Set up test environment
- Använd test-API-nycklar och testprodukter
- Skapa testprenumerationer med olika plantyper
- Konfigurera en testendpoint för webhooks
- Konfigurera övervakning och loggning
Test different proration modes
- Testa
prorated_immediatelymed olika positioner i debiteringscykeln - Testa
difference_immediatelyför uppgraderingar och nedgraderingar - Testa
full_immediatelyför att återställa debiteringscykler - Testa
do_not_billför planbyten utan debitering eller kredit - Kontrollera att kreditberäkningarna är korrekta
Test webhook handling
- Kontrollera att alla relevanta webhook-händelser tas emot
- Testa verifiering av webhook-signaturer
- Hantera duplicerade webhook-händelser på ett smidigt sätt
- Testa scenarier där webhook-bearbetningen misslyckas
Test error scenarios
- Testa med ogiltiga prenumerations-ID:n
- Testa med utgångna betalningsmetoder
- Testa nätverksfel och tidsgränser
- Testa med otillräckliga medel
Monitor in production
- Konfigurera aviseringar för misslyckade planändringar
- Övervaka webhook-bearbetningstider
- Följ upp hur ofta planändringar lyckas
- Granska kundsupportärenden om problem med planändringar
Felhantering
Hantera vanliga API-fel på ett smidigt sätt i din implementation:HTTP-statuskoder
200 OK
200 OK
ChangePlanResponse med payment_id, payment_link, client_secret och expires_on. Alla fyra kan vara null, så kroppen serialiseras som {} vid en vanlig off-session-ändring; de fylls i vid en lyckad begäran med collect_via_payment_link, som returnerar checkout-handtag – se Collecting Payment via a Checkout Link. Om on_payment_failure=prevent_change förblir planändringen väntande tills betalningen lyckas.400 Bad Request
400 Bad Request
409 Conflict
409 Conflict
PendingPlanChangeExists). För en schemalagd ändring ska du avbryta den med DELETE /subscriptions/{subscription_id}/change-plan/scheduled innan du skickar en ny. För en väntande ändring via betalningslänk finns ingen endpoint för avbrytning – prenumerationen accepterar en ny begäran om planändring när kunden betalar eller länken löper ut.422 Unprocessable Entity
422 Unprocessable Entity
collect_via_payment_link – företaget har inte funktionen aktiverad, effective_at är inte immediately eller on_payment_failure är inte prevent_change. Se Requirements. Ett prenumerations-ID som inte finns eller inte tillhör ditt konto returnerar 404 med koden NOT_FOUND.500 Internal Server Error
500 Internal Server Error
Format för felsvar
Fel returnerar en JSON-body med encode och ett människoläsbart message:
Nästa steg
- Läs Change Plan API
- Utforska Credit-Based Billing
- Implementera aviseringar för
subscription.on_hold - Läs Webhook Integration Guide