Skip to main content

Change Plan API

Full API docs for updating subscriptions.

Plan Change Preview

See charge amounts before changing plans.

Integration Guide

Step-by-step subscription setup.

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
Plan changes can trigger an immediate charge depending on the proration mode you choose.

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
For detailed setup instructions, see our Integration Guide.

Step-by-Step Implementation Guide

Follow this comprehensive guide to implement subscription plan changes in your application:
1

Understand Plan Change Requirements

Before implementing, determine:
  • 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
Test plan changes thoroughly in test mode before implementing in production.
2

Choose Your Proration Strategy

Select the billing approach that aligns with your business needs:
Best for: SaaS applications wanting to charge fairly for unused time
  • 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
3

Implement the Change Plan API

Use the Change Plan API to modify subscription details:
string
obligatorisk
The ID of the active subscription to modify.
string
obligatorisk
The new product ID to change the subscription to.
integer
obligatorisk
Number of units for the new plan (for seat-based products).
string
obligatorisk
How to handle immediate billing: prorated_immediately, full_immediately, difference_immediately, or do_not_bill.
array
Optional addons for the new plan. Leaving this empty removes any existing addons.
string
Controls behavior when the plan change payment fails:
  • prevent_change: Keep subscription on current plan until payment succeeds
  • apply_change (default): Apply plan change immediately regardless of payment outcome
If not specified, uses the business-level default setting.
Samla in beloppet för planändringen med en betalningslänk i stället för att debitera prenumerationens sparade betalningsmetod. Kunden betalar på en hostad checkout-sida.Kräver företagets 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 Samla in betalning via en checkout-länk.Ignoreras av preview-routen.
array
Valfria staplade rabattkoder som ska tillämpas på den nya planen (högst 20, tillämpas i arrayordning). Beteendet beror på vad du skickar:
  • Inte angivet / null — befintliga rabatter med preserve_on_plan_change=true bevaras 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.
string
föråldrad
Föråldrat — använd 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.
string
standard:"immediately"
När planändringen ska tillämpas:
  • immediately (standard): Tillämpa planändringen omedelbart
  • next_billing_date: Schemalägg ändringen till nästa faktureringsdatum. Kunden behåller sin aktuella plan tills faktureringsperioden är slut.
Använd next_billing_date för nedgraderingar så att kunderna behåller förmånerna från sin aktuella plan tills faktureringsperioden är slut.
4

Handle Webhook Events

Konfigurera webhook-hantering för att spåra resultatet av planändringar:
  • subscription.active: Planändringen lyckades, prenumerationen uppdaterades
  • subscription.plan_changed: Prenumerationsplanen ändrades (uppgradering/nedgradering/uppdatering av addon)
  • subscription.on_hold: Debiteringen för planändringen misslyckades, förnyelser stoppades
  • payment.succeeded: Den omedelbara debiteringen för planändringen lyckades
  • payment.failed: Den omedelbara debiteringen misslyckades
Verifiera alltid webhook-signaturer och implementera idempotent händelsehantering.
5

Update Your Application State

Uppdatera din applikation baserat på webhook-händelser:
  • Ge eller återkalla funktioner baserat på den nya planen
  • Uppdatera kundpanelen med information om den nya planen
  • Skicka bekräftelsemejl om planändringar
  • Logga faktureringsändringar för revisionsändamål
6

Test and Monitor

Testa implementeringen noggrant:
  • Testa alla prorationslägen med olika scenarier
  • Verifiera att webhook-hanteringen fungerar korrekt
  • Övervaka andelen lyckade planändringar
  • Konfigurera aviseringar för misslyckade planändringar
Implementeringen av prenumerationsplanändringen är nu redo för produktionsanvändning.

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:
Använd preview-API:t för att skapa bekräftelsedialoger som visar kunderna exakt vilket belopp de kommer att debiteras innan de bekräftar en planändring.

Change Plan API

Använd Change Plan API för att ändra produkt, kvantitet och prorationsbeteende för en aktiv prenumeration.

Snabba exempel

En lyckad planändring returnerar 200 OK omedelbart — innan någon debitering faktiskt har slutförts. Vad body (ChangePlanResponse) innehåller beror på hur ändringen samlades in:
I alla fall är detta svar inte ett betalningsresultat — endast en bekräftelse på att själva begäran accepterades. Det säger inget om huruvida en omedelbar debitering faktiskt lyckades.För en vanlig omedelbar debitering fastställs resultatet utanför sessionen, direkt efter anropet.För en collect_via_payment_link-begäran fastställs resultatet senare och asynkront — svaret ger dig endast en checkout-länk, prenumerationen ligger kvar på sin aktuella plan och inget är känt om resultatet förrän kunden faktiskt slutför betalningen via länken.Oavsett vilket ska du inte dra slutsatser om resultatet från detta svar. Bekräfta det via webhook (payment.succeeded, payment.failed, subscription.plan_changed) eller genom att läsa prenumerationen igen med GET /subscriptions/{subscription_id} — se Vad händer medan länken är obetald specifikt för fallet med betalningslänk.
Om den omedelbara debiteringen misslyckas kan prenumerationen övergå till tillståndet subscription.on_hold tills betalningen lyckas.

Samla in betalning via en checkout-länk

Som standard debiterar en omedelbar planändring prenumerationens sparade betalningsmetod direkt. Ange collect_via_payment_link: true för att i stället skicka kunden till en hostad checkout-sida — användbart när det inte finns någon sparad betalningsmetod som du får debitera utanför sessionen, eller när du vill att kunden aktivt ska bekräfta det nya priset.
Detta är också det som driver växlingsalternativet Collect Plan Change Payments by Payment Link i Settings → Subscriptions, som dirigerar den inbyggda Customer Portal:s flöde för planändringar genom checkout i stället för det sparade kortet.

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 allow_plan_change_via_payment_link-funktionen aktiverad (Settings → Subscriptions → Collect Plan Change Payments by Payment Link).
  • effective_at är immediately (standardvärdet). En schemalagd ändring (next_billing_date) behöver aldrig en checkout-sida, eftersom inget debiteras förrän ändringen tillämpas.
  • Den effektiva on_payment_failure löses till prevent_change. Du behöver inte skicka den uttryckligen — om företagets standardvärde (se Företags- och insamlingsstandarder nedan) redan är prevent_change uppfyller det också detta villkor när fältet utelämnas. Ett uttryckligt apply_change, eller ett löst standardvärde på apply_change, misslyckas med 422.
collect_via_payment_link är inte begränsad till uppgraderingar — den gäller alla omedelbara ändringar som leder till en debitering, inklusive nedgraderingar, så länge kraven ovan är uppfyllda.
Om ändringen blir noll eller en krediteringproration_billing_mode: do_not_bill eller ett annat läge som råkar ge noll netto den här cykeln — finns det inget att lägga på en checkout-sida. Ingen betalningslänk utfärdas, payment_link och liknande returneras som null, och ändringen tillämpas omedelbart, precis som den skulle ha gjort utan collect_via_payment_link. Detta är inte ett 422; flaggan träder endast i kraft när det finns ett positivt belopp att samla in. Om du anger collect_via_payment_link generellt för planändringar i stället för enbart för tydliga uppgraderingar bör du först anropa Preview Plan Change och endast begära en länk när det förhandsgranskade beloppet är värt att samla in.
En lyckad begäran returnerar checkout-handtagen:

Vad händer medan länken är obetald

  • Prenumerationen ligger kvar på sin aktuella plan — product_id, recurring_pre_tax_amount och next_billing_date påverkas inte förrän länken har betalats.
  • En ytterligare change-plan-begäran för samma prenumeration avvisas med 409 PendingPlanChangeExists medan länken väntar. Avbryt en schemalagd ändring med DELETE /subscriptions/{subscription_id}/change-plan/scheduled vid behov, men den endpointen avbryter inte en väntande ändring via betalningslänk — endast en lyckad betalning eller länkens utgång gör det.
  • Kunden kan försöka betala med ett kort igen i samma checkout-session efter ett avslag; ett nytt change-plan-anrop är inte rätt sätt att försöka igen.
  • 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 (next_billing_date) redan fanns och du ersätter den med cancel_scheduled_change_plan: true ligger det ursprungliga schemat kvar medan länken är obetald och avbryts först när länken har betalats — i samma transaktion som tillämpar den nya planen.
När en omedelbar ändring via betalningslänk har utfärdats blockeras varje ytterligare begäran om planändring för prenumerationen — inklusive den bieffektfria förhandsgranskningen — tills länken har lösts. Utfärda inte en länk som du inte avser att kunden ska betala omedelbart.

Hantera addons

När du ändrar prenumerationsplaner kan du även ändra addons:
Addons inkluderas i prorationsberäkningen och debiteras enligt det valda prorationsläget.

Tillämpa rabattkoder

Du kan tillämpa en eller flera staplade rabattkoder när du ändrar prenumerationsplaner (högst 20, tillämpas i arrayordning). Detta är användbart när du erbjuder kampanjpriser vid uppgraderingar eller migreringar.

Rabattbeteende vid planändring

Det enskilda fältet discount_code för 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.
Använd Preview Plan Change API med discount_codes för att visa kunderna exakt hur mycket de sparar innan de bekräftar planändringen.

Prorationslägen

Välj hur kunden ska faktureras när planer ändras:

prorated_immediately

  • Debiterar den proportionella skillnaden för den del av den aktuella cykeln som återstår
  • Om kunden är i en provperiod debiteras kunden omedelbart och byter till den nya planen nu
  • Nedgradering: kan skapa en proportionell kreditering som tillämpas på framtida förnyelser

full_immediately

  • Debiterar hela beloppet för den nya planen omedelbart
  • Tar inte hänsyn till återstående tid i den gamla planen
Krediter som skapas av nedgraderingar med difference_immediately är knutna till prenumerationen och skiljer sig från förmåner inom 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 faktureringsjustering
  • Faktureringscykeln förblir oförändrad
  • Passar bäst för kostnadsfria migreringar, byten till gratisplaner eller när kostnadsskillnader tas bort

Exempelscenarier

Använd dessa kanoniska siffror konsekvent:
  • Aktuell plan: Basic$30/månad
  • Målplan för uppgradering: Pro$80/månad
  • Målplan för nedgradering (från Pro): Starter$20/månad
  • Faktureringscykel: 30 dagar, startade January 1
  • Planändringen sker January 16 (15 dagar kvar, 15 dagar använda)

Så behandlar varje läge faktureringen

Välj prorated_immediately för rättvis tidsbaserad redovisning; välj full_immediately för att starta om faktureringen; använd difference_immediately för enkla uppgraderingar och automatisk kreditering vid nedgraderingar; eller använd do_not_bill för att byta plan utan någon faktureringsjustering.

Hantera betalningsmisslyckanden

Styr vad som händer när en betalning för en planändring misslyckas med parametern on_payment_failure.

Lägen för betalningsmisslyckanden

Om den inte anges använder parametern on_payment_failure företagets standardinställning som konfigurerats i dashboarden.

När ska varje läge användas?

Företags- och insamlingsstandarder

I stället för att skicka prorationsparametrar vid varje planändring kan du ange standardbeteende för uppgraderingar och nedgraderingar en gång på företagsnivå. Dessa standardvärden gäller för alla planändringar i kundportalen och kan åsidosättas per produktkollektion. Det finns separata standardvärden för uppgraderingar och nedgraderingar: Konfigurera företagsstandarder under Settings → Subscriptions och åsidosättningar för kollektioner på varje produktkollektion. Varje kollektionsfält är fristående — lämna det ej angivet för att ärva från företagsstandarden, eller ange ett värde för att endast åsidosätta det för den kollektionen.

Prioritetsordning

För en viss planändring löses varje inställning i denna ordning:
Ett värde som uttryckligen skickas till Change Plan API har alltid företräde. Företags- och kollektionsstandarderna börjar endast gälla när inget uttryckligt värde har angetts — vilket gäller för alla planändringar som initieras från kundportalen.
En vanlig konfiguration är att behålla uppgraderingar på immediately + difference_immediately så att kunderna betalar skillnaden och får åtkomst direkt, och att behålla nedgraderingar på next_billing_date så att kunderna behåller sin aktuella plan tills cykeln är slut.

Hantera webhooks

Spåra prenumerationens status via webhooks för att bekräfta planändringar och betalningar.

Händelsetyper att hantera

  • subscription.active: prenumerationen aktiverades
  • subscription.plan_changed: prenumerationsplanen ändrades (uppgradering/nedgradering/ändringar av addon)
  • subscription.on_hold: debiteringen misslyckades, förnyelser stoppades
  • subscription.renewed: förnyelsen lyckades
  • payment.succeeded: betalningen för planändringen eller förnyelsen lyckades
  • payment.failed: betalningen misslyckades
Vi rekommenderar att du baserar affärslogiken på prenumerationshändelser och använder betalningshändelser för bekräftelse och avstämning.

Verifiera signaturer och hantera intents

Bästa praxis

Följ dessa rekommendationer för tillförlitliga planändringar av prenumerationer:

Strategi för planändringar

  • Testa noggrant: Testa alltid planändringar i testläge före produktion
  • Välj proration med omsorg: Välj det prorationsläge som passar din affärsmodell
  • Hantera fel på ett bra sätt: Implementera korrekt felhantering och logik för nya försök
  • Övervaka lyckade ändringar: Spåra andelen lyckade och misslyckade planändringar och undersök problem

Webhook-implementering

  • Verifiera signaturer: Validera alltid webhook-signaturer för att säkerställa äkthet
  • Implementera idempotens: Hantera dubbla webhook-händelser på ett bra sätt
  • Bearbeta asynkront: Blockera inte webhook-svar med tunga operationer
  • Logga allt: Spara detaljerade loggar för felsökning och revisionsändamål

Användarupplevelse

  • Kommunicera tydligt: Informera kunderna om faktureringsändringar och tidpunkter
  • Ge bekräftelser: Skicka bekräftelsemejl för lyckade planändringar
  • Hantera specialfall: Ta hänsyn till provperioder, prorering och misslyckade betalningar
  • Uppdatera gränssnittet omedelbart: Återspegla planändringar i applikationens gränssnitt

Vanliga problem och lösningar

Lös typiska problem som uppstår vid ändringar av prenumerationsplaner:
Symptom: API-anropet lyckas men prenumerationen ligger kvar på den gamla planenVanliga orsaker:
  • Webhook-bearbetningen misslyckades eller fördröjdes
  • Applikationens tillstånd uppdaterades inte efter mottagna webhooks
  • Problem med databastransaktioner under tillståndsuppdateringen
Lösningar:
  • Implementera robust webhook-hantering med logik för nya försök
  • Använd idempotenta åtgärder för tillståndsuppdateringar
  • Lägg till övervakning för att upptäcka och avisera om missade webhook-händelser
  • Verifiera att webhook-endpointen är tillgänglig och svarar korrekt
Symptom: Kunden nedgraderar men ser inget kreditsaldoVanliga orsaker:
  • Förväntningar på prorationsläget: nedgraderingar krediterar hela prisskillnaden med difference_immediately, medan prorated_immediately skapar en proportionell kreditering baserat på återstående tid i cykeln
  • Krediter är prenumerationsspecifika och överförs inte mellan prenumerationer
  • Kreditsaldot visas inte i kundpanelen
Lösningar:
  • Använd difference_immediately fö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 nästa fakturaförhandsgranskning för att se tillämpade krediter
Symptom: Webhook-händelser avvisas på grund av ogiltig signaturVanliga orsaker:
  • Felaktig webhook-hemlighet
  • Rå request body ändrades före signaturverifieringen
  • Fel algoritm för signaturverifiering
Lösningar:
  • Verifiera att du använder rätt DODO_WEBHOOK_SECRET från dashboarden
  • Läs den råa request body innan någon middleware för JSON-parsning körs
  • Använd standardbiblioteket för webhook-verifiering för din plattform
  • Testa verifieringen av webhook-signaturer i utvecklingsmiljön
Symptom: API returnerar felet 422 Unprocessable EntityVanliga orsaker:
  • 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
Lösningar:
  • Verifiera 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 information om parameterkrav
Symptom: Planändringen initierades men den omedelbara debiteringen misslyckadesVanliga orsaker:
  • Otillräckliga medel på kundens betalningsmetod
  • Betalningsmetoden har upphört att gälla eller är ogiltig
  • Banken avvisade transaktionen
  • Bedrägeridetektering blockerade debiteringen
Lösningar:
  • Hantera webhook-händelser av typen payment.failed korrekt
  • Informera kunden om att uppdatera betalningsmetoden
  • Implementera logik för nya försök vid tillfälliga fel
  • Överväg att tillåta planändringar trots misslyckade omedelbara debiteringar
Symptom: Debiteringen för planändringen misslyckas och prenumerationen övergår till tillståndet 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:
  1. Uppdatera betalningsmetoden med Update Payment Method API
  2. Automatisk skapelse av debitering: API:t skapar automatiskt en debitering för återstående belopp
  3. Generering av faktura: En faktura genereras för debiteringen
  4. Betalningshantering: Betalningen behandlas med den nya betalningsmetoden
  5. Återaktivering: Efter en lyckad betalning återaktiveras prenumerationen till tillståndet active
Webhook-händelser att övervaka:
  • subscription.on_hold: Prenumerationen sattes på hold (mottas när debiteringen för planändringen misslyckas)
  • payment.succeeded: Betalningen för återstående belopp lyckades (efter uppdatering av betalningsmetoden)
  • subscription.active: Prenumerationen återaktiverades efter en lyckad betalning
Bästa praxis:
  • Informera 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 spåra återaktiveringsstatus
  • Överväg att implementera automatisk logik för nya försök vid tillfälliga betalningsfel

Update Payment Method API Reference

Visa den fullständiga API-dokumentationen för uppdatering av betalningsmetoder och återaktivering av prenumerationer.

Testa din implementering

Följ dessa steg för att testa implementeringen av planändringar för prenumerationer noggrant:
1

Set up test environment

  • Använd test-API-nycklar och testprodukter
  • Skapa testprenumerationer med olika plantyper
  • Konfigurera test-endpointen för webhooks
  • Konfigurera övervakning och loggning
2

Test different proration modes

  • Testa prorated_immediately med olika positioner i faktureringscykeln
  • Testa difference_immediately för uppgraderingar och nedgraderingar
  • Testa full_immediately för att återställa faktureringscykler
  • Testa do_not_bill för planbyten utan debitering eller kreditering
  • Verifiera att krediterna beräknas korrekt
3

Test webhook handling

  • Verifiera att alla relevanta webhook-händelser tas emot
  • Testa verifiering av webhook-signaturer
  • Hantera dubbla webhook-händelser på ett bra sätt
  • Testa scenarier där webhook-bearbetningen misslyckas
4

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
5

Monitor in production

  • Konfigurera aviseringar för misslyckade planändringar
  • Övervaka webhook-bearbetningstider
  • Spåra andelen lyckade planändringar
  • Granska kundsupportärenden om problem med planändringar

Felhantering

Hantera vanliga API-fel på ett bra sätt i din implementering:

HTTP-statuskoder

Begäran om planändring behandlades korrekt. Svarskroppen är tom, förutom vid en lyckad collect_via_payment_link-begäran, som returnerar checkout-handtag — se Samla in betalning via en checkout-länk. Om on_payment_failure=prevent_change förblir planändringen väntande tills betalningen lyckas.
Ogiltiga begärandeparametrar. Kontrollera att alla obligatoriska fält har angetts och formaterats korrekt.
Ogiltig eller saknad API-nyckel. Kontrollera att din DODO_PAYMENTS_API_KEY är korrekt och har rätt behörigheter.
Prenumerations-ID:t hittades inte eller tillhör inte ditt konto.
Det finns redan en väntande planändring för denna prenumeration (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 att avbryta den — prenumerationen accepterar en ny begäran om planändring när kunden betalar eller länken löper ut.
Prenumerationen är inaktiv eller on-demand, eller så är begäran inte kvalificerad för collect_via_payment_link — företaget har inte funktionen aktiverad, effective_at är inte immediately, eller on_payment_failure är inte prevent_change. Se Krav.
Ett serverfel inträffade. Försök skicka begäran igen efter en kort stund.

Format för felsvar

Nästa steg

Senast ändrad 26 augusti 2026