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
requerido
The ID of the active subscription to modify.
string
requerido
The new product ID to change the subscription to.
integer
requerido
Number of units for the new plan (for seat-based products).
string
requerido
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.
Recopila el importe del cambio de plan mediante un enlace de pago en lugar de cargar el método de pago guardado de la suscripción. El cliente paga en una página de checkout alojada.Requiere que la empresa tenga habilitada la capacidad allow_plan_change_via_payment_link (Settings → Subscriptions → Collect Plan Change Payments by Payment Link), effective_at: immediately y on_payment_failure: prevent_change. Consulta Recopilar pagos mediante un enlace de checkout.La ruta de vista previa lo ignora.
array
Códigos de descuento apilados opcionales que se aplicarán al nuevo plan (máximo 20, aplicados en el orden de la matriz). El comportamiento depende de lo que envíes:
  • No proporcionado / null: los descuentos existentes con preserve_on_plan_change=true se conservan si son aplicables al nuevo producto.
  • [] (matriz vacía): elimina todos los descuentos existentes de la suscripción.
  • ["CODE_A", "CODE_B", ...]: reemplaza cualquier descuento existente por este conjunto apilado.
string
obsoleto
Obsoleto: para nuevas integraciones, prefiere discount_codes. Este campo sigue funcionando por compatibilidad con versiones anteriores, pero no se puede combinar con discount_codes en la misma solicitud.
string
predeterminado:"immediately"
Cuándo aplicar el cambio de plan:
  • immediately (predeterminado): aplica el cambio de plan de inmediato
  • next_billing_date: programa el cambio para la próxima fecha de facturación. El cliente conserva su plan actual hasta que finaliza el periodo de facturación.
Usa next_billing_date para las reducciones de plan, de modo que los clientes conserven los beneficios de su plan actual hasta el final del periodo de facturación.
4

Handle Webhook Events

Configura el manejo de webhooks para realizar un seguimiento de los resultados de los cambios de plan:
  • subscription.active: cambio de plan exitoso, suscripción actualizada
  • subscription.plan_changed: plan de suscripción cambiado (actualización/reducción del plan o actualización del addon)
  • subscription.on_hold: el cargo del cambio de plan falló, renovaciones detenidas
  • payment.succeeded: el cargo inmediato del cambio de plan se realizó correctamente
  • payment.failed: el cargo inmediato falló
Verifica siempre las firmas de los webhooks e implementa un procesamiento de eventos idempotente.
5

Update Your Application State

Según los eventos de webhook, actualiza tu aplicación:
  • Concede o revoca funciones según el nuevo plan
  • Actualiza el panel del cliente con los detalles del nuevo plan
  • Envía correos de confirmación sobre los cambios de plan
  • Registra los cambios de facturación para fines de auditoría
6

Test and Monitor

Prueba exhaustivamente tu implementación:
  • Prueba todos los modos de prorrateo con distintos escenarios
  • Verifica que el manejo de webhooks funcione correctamente
  • Supervisa las tasas de éxito de los cambios de plan
  • Configura alertas para los cambios de plan fallidos
Tu implementación de cambios de plan de suscripción ya está lista para usarse en producción.

Vista previa de los cambios de plan

Antes de confirmar un cambio de plan, usa la Preview API para mostrar a los clientes exactamente cuánto se les cobrará:
Usa la Preview API para crear diálogos de confirmación que muestren a los clientes el importe exacto que se les cobrará antes de confirmar un cambio de plan.

Change Plan API

Usa la Change Plan API para modificar el producto, la cantidad y el comportamiento del prorrateo de una suscripción activa.

Ejemplos de inicio rápido

Un cambio de plan exitoso devuelve 200 OK de inmediato, antes de que se liquide cualquier cargo. Lo que contiene el cuerpo (ChangePlanResponse) depende de cómo se haya cobrado el cambio:
En todos los casos, esta respuesta no es un resultado de pago; solo indica que la solicitud fue aceptada. No dice nada sobre si un cargo inmediato se realizó correctamente.En el caso de un cargo inmediato ordinario, el resultado se resuelve fuera de sesión justo después de la llamada.En el caso de una solicitud collect_via_payment_link, se resuelve más tarde y de forma asíncrona: la respuesta solo te entrega un enlace de checkout, la suscripción permanece en su plan actual y no se conoce el resultado hasta que el cliente completa el pago mediante ese enlace.En cualquier caso, no deduzcas el resultado a partir de esta respuesta. Confírmalo mediante un webhook (payment.succeeded, payment.failed, subscription.plan_changed) o volviendo a leer la suscripción con GET /subscriptions/{subscription_id}. Consulta Qué sucede mientras el enlace no está pagado específicamente para el caso del enlace de pago.
Si el cargo inmediato falla, la suscripción puede pasar al estado subscription.on_hold hasta que el pago se realice correctamente.

Recopilar pagos mediante un enlace de checkout

De forma predeterminada, un cambio de plan inmediato carga directamente el método de pago guardado de la suscripción. Establece collect_via_payment_link: true para enviar al cliente a una página de checkout alojada. Esto resulta útil cuando no existe un método de pago guardado que puedas cargar fuera de sesión o cuando quieres que el cliente confirme activamente el nuevo precio.
Esto también es lo que activa el selector Collect Plan Change Payments by Payment Link en Settings → Subscriptions, que dirige el flujo de cambio de plan del Customer Portal integrado mediante checkout en lugar de usar la tarjeta guardada.

Requisitos

collect_via_payment_link: true solo funciona correctamente cuando se cumplen todas las condiciones siguientes; de lo contrario, la solicitud falla con 422:
  • La empresa tiene habilitada la capacidad allow_plan_change_via_payment_link (Settings → Subscriptions → Collect Plan Change Payments by Payment Link).
  • effective_at es immediately (el valor predeterminado). Un cambio programado (next_billing_date) nunca necesita una página de checkout, ya que no se cobra nada hasta que se aplica.
  • El on_payment_failure efectivo se resuelve como prevent_change. No tienes que enviarlo explícitamente: si el valor predeterminado a nivel de empresa (consulta Business & Collection Defaults más abajo) ya es prevent_change, omitir el campo también cumple este requisito. Un apply_change explícito o un valor predeterminado resuelto como apply_change falla con 422.
collect_via_payment_link no se limita a las actualizaciones: se aplica a cualquier cambio inmediato que genere un cargo, incluidas las reducciones, siempre que se cumplan los requisitos anteriores.
Si el cambio resulta en cero o en un crédito (proration_billing_mode: do_not_bill u otro modo cuyo resultado neto sea cero en este ciclo), no hay nada que colocar en una página de checkout. No se emite ningún enlace de pago, payment_link y otros campos similares devuelven null, y el cambio se aplica de inmediato, igual que sin collect_via_payment_link. Esto no es un 422; el indicador solo tiene efecto cuando existe un importe positivo que cobrar. Si estableces collect_via_payment_link para cambios de plan de forma general, en lugar de hacerlo únicamente para actualizaciones claras, llama primero a Preview Plan Change y solicita un enlace solo cuando el importe de la vista previa merezca la pena cobrarlo.
Una solicitud exitosa devuelve los identificadores de checkout:

Qué sucede mientras el enlace no está pagado

  • La suscripción permanece en su plan actual; product_id, recurring_pre_tax_amount e next_billing_date no cambian hasta que se pague el enlace.
  • Una nueva solicitud change-plan para la misma suscripción se rechaza con 409 PendingPlanChangeExists mientras el enlace está pendiente. Si es necesario, cancela un cambio programado con DELETE /subscriptions/{subscription_id}/change-plan/scheduled, pero ese endpoint no cancela un cambio de enlace de pago pendiente; solo lo hacen un pago exitoso o la caducidad.
  • El cliente puede volver a intentar pagar con tarjeta en la misma sesión de checkout después de un rechazo; una nueva llamada a change-plan no es el mecanismo para reintentar.
  • Si el enlace nunca se paga, deja de funcionar después de expires_on; la suscripción queda automáticamente disponible para aceptar una nueva solicitud de cambio de plan poco después.
  • Si ya existía un cambio programado (next_billing_date) y lo reemplazas por cancel_scheduled_change_plan: true, la programación original se mantiene mientras el enlace no esté pagado y solo se cancela cuando se paga el enlace, en la misma transacción que aplica el nuevo plan.
Una vez emitido un cambio inmediato mediante enlace de pago, cualquier solicitud posterior de cambio de plan para esa suscripción, incluida la vista previa sin efectos secundarios, queda bloqueada hasta que el enlace se resuelva. No emitas un enlace si no pretendes que el cliente lo pague de inmediato.

Gestionar addons

Al cambiar los planes de suscripción, también puedes modificar los addons:
Los addons se incluyen en el cálculo del prorrateo y se cobran según el modo de prorrateo seleccionado.

Aplicar códigos de descuento

Puedes aplicar uno o más códigos de descuento apilados al cambiar los planes de suscripción (máximo 20, aplicados en el orden de la matriz). Esto resulta útil para ofrecer precios promocionales en actualizaciones o migraciones.

Comportamiento de los descuentos al cambiar de plan

El campo singular discount_code de este endpoint está obsoleto, pero sigue funcionando por compatibilidad con versiones anteriores; las integraciones existentes no necesitan cambiar de inmediato. No se puede combinar con discount_codes en la misma solicitud. Migra al formato de matriz cuando te resulte conveniente.
Usa la Preview Plan Change API con discount_codes para mostrar a los clientes exactamente cuánto ahorrarán antes de confirmar el cambio de plan.

Modos de prorrateo

Elige cómo facturar al cliente al cambiar de plan:

prorated_immediately

  • Cobra la diferencia parcial del ciclo actual
  • Si está en periodo de prueba, cobra de inmediato y cambia ahora al nuevo plan
  • Reducción: puede generar un crédito prorrateado que se aplicará a futuras renovaciones

full_immediately

  • Cobra inmediatamente el importe completo del nuevo plan
  • Ignora el tiempo restante del plan anterior
Los créditos creados por reducciones mediante difference_immediately están asociados al ámbito de la suscripción y son distintos de las asignaciones de Credit-Based Billing. Se aplican automáticamente a futuras renovaciones de la misma suscripción y no se pueden transferir entre suscripciones.

difference_immediately

  • Actualización: cobra inmediatamente la diferencia de precio entre los planes anterior y nuevo
  • Reducción: añade el valor restante como crédito interno a la suscripción y lo aplica automáticamente en las renovaciones

do_not_bill

  • No se calculan cargos ni créditos
  • El cliente cambia inmediatamente al nuevo plan sin ningún ajuste de facturación
  • El ciclo de facturación no cambia
  • Ideal para migraciones de cortesía, cambios a planes gratuitos o para absorber diferencias de costes

Escenarios de ejemplo

Usa estos valores canónicos de forma coherente:
  • Plan actual: Basic a $30/mes
  • Objetivo de actualización: Pro a $80/mes
  • Objetivo de reducción (desde Pro): Starter a $20/mes
  • Ciclo de facturación: 30 días, iniciado el 1 de enero
  • El cambio de plan ocurre el 16 de enero (quedan 15 días y se han utilizado 15 días)

Cómo procesa la facturación cada modo

Elige prorated_immediately para una contabilidad justa basada en el tiempo; elige full_immediately para reiniciar la facturación; usa difference_immediately para actualizaciones simples y créditos automáticos en reducciones; o usa do_not_bill para cambiar de plan sin ningún ajuste de facturación.

Gestionar fallos de pago

Controla lo que sucede cuando falla el pago de un cambio de plan mediante el parámetro on_payment_failure.

Modos de fallo de pago

Si no se especifica, el parámetro on_payment_failure usa el valor predeterminado a nivel de empresa configurado en el dashboard.

Cuándo usar cada modo

Valores predeterminados de empresa y recopilación

En lugar de enviar parámetros de prorrateo en cada cambio de plan, puedes establecer una vez el comportamiento predeterminado de actualización y reducción a nivel de empresa. Estos valores predeterminados se aplican a todos los cambios de plan del portal del cliente y se pueden anular por colección de productos. Existen valores predeterminados independientes para actualizaciones y reducciones: Configura los valores predeterminados de la empresa en Settings → Subscriptions y las anulaciones de la colección en cada colección de productos. Cada campo de colección es independiente: déjalo sin establecer para heredarlo del valor predeterminado de la empresa o establece un valor para anularlo únicamente en esa colección.

Orden de resolución

Para cualquier cambio de plan, cada configuración se resuelve en este orden:
Un valor enviado explícitamente a la Change Plan API siempre tiene prioridad. Los valores predeterminados de empresa y colección solo se aplican cuando no se proporciona ningún valor explícito, que es el caso de todos los cambios de plan iniciados desde el portal del cliente.
Una configuración habitual es mantener las actualizaciones en immediately + difference_immediately para que los clientes paguen la diferencia y obtengan acceso de inmediato, y mantener las reducciones en next_billing_date para que conserven su plan actual hasta que termine el ciclo.

Gestionar webhooks

Realiza un seguimiento del estado de la suscripción mediante webhooks para confirmar los cambios de plan y los pagos.

Tipos de eventos que se deben gestionar

  • subscription.active: suscripción activada
  • subscription.plan_changed: plan de suscripción cambiado (actualización/reducción del plan o cambios en addons)
  • subscription.on_hold: cargo fallido, renovaciones detenidas
  • subscription.renewed: renovación exitosa
  • payment.succeeded: pago del cambio de plan o renovación exitoso
  • payment.failed: pago fallido
Recomendamos basar la lógica empresarial en los eventos de suscripción y usar los eventos de pago para la confirmación y la conciliación.

Verificar firmas y gestionar intents

Para consultar los esquemas detallados de las cargas útiles, revisa las cargas útiles de webhook de suscripción y las cargas útiles de webhook de pago.

Prácticas recomendadas

Sigue estas recomendaciones para realizar cambios de plan de suscripción fiables:

Estrategia de cambio de plan

  • Prueba exhaustivamente: prueba siempre los cambios de plan en modo de prueba antes de pasarlos a producción
  • Elige el prorrateo cuidadosamente: selecciona el modo de prorrateo que se ajuste a tu modelo de negocio
  • Gestiona los fallos correctamente: implementa un manejo de errores y una lógica de reintentos adecuados
  • Supervisa las tasas de éxito: realiza un seguimiento de las tasas de éxito y fallo de los cambios de plan e investiga los problemas

Implementación de webhooks

  • Verifica las firmas: valida siempre las firmas de los webhooks para garantizar su autenticidad
  • Implementa la idempotencia: gestiona correctamente los eventos de webhook duplicados
  • Procesa de forma asíncrona: no bloquees las respuestas de los webhooks con operaciones pesadas
  • Regístralo todo: mantén registros detallados para la depuración y la auditoría

Experiencia de usuario

  • Comunica claramente: informa a los clientes sobre los cambios de facturación y sus plazos
  • Proporciona confirmaciones: envía correos de confirmación para los cambios de plan exitosos
  • Gestiona los casos límite: considera los periodos de prueba, los prorrateos y los pagos fallidos
  • Actualiza la interfaz de usuario de inmediato: refleja los cambios de plan en la interfaz de tu aplicación

Problemas habituales y soluciones

Resuelve los problemas habituales que pueden surgir durante los cambios de plan de suscripción:
Síntomas: la llamada a la API se realiza correctamente, pero la suscripción permanece en el plan anteriorCausas habituales:
  • El procesamiento del webhook falló o se retrasó
  • El estado de la aplicación no se actualizó después de recibir los webhooks
  • Problemas con la transacción de la base de datos durante la actualización del estado
Soluciones:
  • Implementa un manejo sólido de webhooks con lógica de reintentos
  • Usa operaciones idempotentes para las actualizaciones de estado
  • Añade supervisión para detectar y alertar sobre eventos de webhook no recibidos
  • Verifica que el endpoint del webhook sea accesible y responda correctamente
Síntomas: el cliente reduce su plan, pero no ve el saldo de créditoCausas habituales:
  • Expectativas sobre el modo de prorrateo: las reducciones acreditan la diferencia de precio total del plan con difference_immediately, mientras que prorated_immediately crea un crédito prorrateado según el tiempo restante del ciclo
  • Los créditos son específicos de la suscripción y no se transfieren entre suscripciones
  • El saldo de crédito no es visible en el panel del cliente
Soluciones:
  • Usa difference_immediately para las reducciones cuando quieras créditos automáticos
  • Explica a los clientes que los créditos se aplican a futuras renovaciones de la misma suscripción
  • Implementa el portal del cliente para mostrar los saldos de crédito
  • Consulta la vista previa de la próxima factura para ver los créditos aplicados
Síntomas: los eventos de webhook se rechazan debido a una firma no válidaCausas habituales:
  • Clave secreta del webhook incorrecta
  • El cuerpo sin procesar de la solicitud se modificó antes de verificar la firma
  • Algoritmo de verificación de firma incorrecto
Soluciones:
  • Verifica que estás usando el DODO_WEBHOOK_SECRET correcto del dashboard
  • Lee el cuerpo sin procesar de la solicitud antes de cualquier middleware de análisis JSON
  • Usa la biblioteca estándar de verificación de webhooks para tu plataforma
  • Prueba la verificación de firmas de webhooks en el entorno de desarrollo
Síntomas: la API devuelve un error 422 Unprocessable EntityCausas habituales:
  • ID de suscripción o ID de producto no válido
  • La suscripción no está en estado activo
  • Faltan parámetros obligatorios
  • El producto no está disponible para cambios de plan
Soluciones:
  • Verifica que la suscripción exista y esté activa
  • Comprueba que el ID del producto sea válido y esté disponible
  • Asegúrate de proporcionar todos los parámetros obligatorios
  • Consulta la documentación de la API para conocer los requisitos de los parámetros
Síntomas: se inició el cambio de plan, pero el cargo inmediato fallaCausas habituales:
  • Fondos insuficientes en el método de pago del cliente
  • Método de pago caducado o no válido
  • El banco rechazó la transacción
  • La detección de fraude bloqueó el cargo
Soluciones:
  • Gestiona adecuadamente los eventos de webhook payment.failed
  • Notifica al cliente que debe actualizar su método de pago
  • Implementa una lógica de reintentos para fallos temporales
  • Considera permitir cambios de plan con cargos inmediatos fallidos
Síntomas: el cargo del cambio de plan falla y la suscripción pasa al estado on_holdQué sucede: Cuando falla el cargo de un cambio de plan, la suscripción pasa automáticamente al estado on_hold. La suscripción no se renovará automáticamente hasta que se actualice el método de pago.Solución: actualiza el método de pago para reactivar la suscripciónPara reactivar una suscripción en estado on_hold después de un cambio de plan fallido:
  1. Actualiza el método de pago mediante la Update Payment Method API
  2. Creación automática del cargo: la API crea automáticamente un cargo por las cantidades pendientes
  3. Generación de la factura: se genera una factura para el cargo
  4. Procesamiento del pago: el pago se procesa mediante el nuevo método de pago
  5. Reactivación: tras un pago exitoso, la suscripción se reactiva al estado active
Eventos de webhook que se deben supervisar:
  • subscription.on_hold: suscripción puesta en espera (se recibe cuando falla el cargo del cambio de plan)
  • payment.succeeded: pago de las cantidades pendientes exitoso (después de actualizar el método de pago)
  • subscription.active: suscripción reactivada tras un pago exitoso
Prácticas recomendadas:
  • Notifica inmediatamente a los clientes cuando falle el cargo de un cambio de plan
  • Proporciona instrucciones claras sobre cómo actualizar su método de pago
  • Supervisa los eventos de webhook para realizar un seguimiento del estado de reactivación
  • Considera implementar una lógica de reintentos automáticos para fallos de pago temporales

Update Payment Method API Reference

Consulta la documentación completa de la API para actualizar métodos de pago y reactivar suscripciones.

Probar tu implementación

Sigue estos pasos para probar exhaustivamente tu implementación de cambios de plan de suscripción:
1

Set up test environment

  • Usa API keys de prueba y productos de prueba
  • Crea suscripciones de prueba con distintos tipos de plan
  • Configura el endpoint de webhook de prueba
  • Configura la supervisión y el registro
2

Test different proration modes

  • Prueba prorated_immediately con distintas posiciones del ciclo de facturación
  • Prueba difference_immediately para actualizaciones y reducciones
  • Prueba full_immediately para restablecer los ciclos de facturación
  • Prueba do_not_bill para cambios de plan sin cargo ni crédito
  • Verifica que los cálculos de crédito sean correctos
3

Test webhook handling

  • Verifica que se reciban todos los eventos de webhook relevantes
  • Prueba la verificación de firmas de webhook
  • Gestiona correctamente los eventos de webhook duplicados
  • Prueba escenarios de fallo en el procesamiento de webhooks
4

Test error scenarios

  • Prueba con IDs de suscripción no válidos
  • Prueba con métodos de pago caducados
  • Prueba fallos de red y tiempos de espera agotados
  • Prueba con fondos insuficientes
5

Monitor in production

  • Configura alertas para cambios de plan fallidos
  • Supervisa los tiempos de procesamiento de webhooks
  • Realiza un seguimiento de las tasas de éxito de los cambios de plan
  • Revisa los tickets de soporte al cliente relacionados con problemas de cambios de plan

Gestión de errores

Gestiona correctamente los errores habituales de la API en tu implementación:

Códigos de estado HTTP

La solicitud de cambio de plan se procesó correctamente. El cuerpo de la respuesta está vacío, excepto en una solicitud collect_via_payment_link exitosa, que devuelve identificadores de checkout; consulta Recopilar pagos mediante un enlace de checkout. Si on_payment_failure=prevent_change, el cambio de plan permanece pendiente hasta que el pago se realice correctamente.
Parámetros de solicitud no válidos. Comprueba que todos los campos obligatorios se hayan proporcionado y tengan el formato correcto.
API key no válida o ausente. Verifica que tu DODO_PAYMENTS_API_KEY sea correcta y tenga los permisos adecuados.
No se encontró el ID de suscripción o no pertenece a tu cuenta.
Ya existe un cambio de plan pendiente para esta suscripción (PendingPlanChangeExists). Si se trata de un cambio programado, cancélalo con DELETE /subscriptions/{subscription_id}/change-plan/scheduled antes de enviar uno nuevo. Si se trata de un cambio mediante enlace de pago pendiente, no existe un endpoint de cancelación; la suscripción acepta una nueva solicitud de cambio de plan cuando el cliente paga o el enlace caduca.
La suscripción está inactiva o es bajo demanda, o la solicitud no cumple los requisitos para collect_via_payment_link: la empresa no tiene habilitada la capacidad, effective_at no es immediately o on_payment_failure no es prevent_change. Consulta Requisitos.
Se produjo un error del servidor. Vuelve a intentar la solicitud después de una breve espera.

Formato de respuesta de error

Próximos pasos

Última modificación el 26 de agosto de 2026