Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt

Use this file to discover all available pages before exploring further.

Descripción general

Las suscripciones bajo demanda te permiten autorizar el método de pago de un cliente una vez y luego cobrar montos variables cuando lo necesites, en lugar de en un horario fijo. Esta función está disponible para todas las cuentas; no se requiere aprobación. Utiliza esta guía para:
  • Crear una suscripción bajo demanda (autorizar un mandato con un precio inicial opcional)
  • Activar cargos posteriores con montos personalizados
  • Rastrear resultados utilizando webhooks
Para una configuración general de suscripción, consulta la Guía de Integración de Suscripciones.

Requisitos previos

  • Cuenta de comerciante de Dodo Payments y clave API
  • Secreto de webhook configurado y un endpoint para recibir eventos
  • Un producto de suscripción en tu catálogo
Si deseas que el cliente apruebe el mandato mediante el pago alojado, establece payment_link: true y facilita un return_url.

Cómo funciona bajo demanda

  1. Creas una suscripción con el objeto on_demand para autorizar un método de pago y, opcionalmente, cobrar un cargo inicial.
  2. Más adelante, creas cargos contra esa suscripción con importes personalizados usando el endpoint dedicado de cargos.
  3. Escuchas webhooks (p. ej., payment.succeeded, payment.failed) para actualizar tu sistema.

Crear una suscripción bajo demanda

Endpoint: POST /checkouts Campos clave de la solicitud (cuerpo):
Consúltalos en Crear Sesión de Pago

Crear una suscripción bajo demanda

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'test_mode', // defaults to 'live_mode'
});

async function main() {
  const subscription = await client.checkoutSessions.create({
    product_cart: [{ product_id: 'pdt_123', quantity: 1 }],
    billing_address:  { city: 'SF', country: 'US', state: 'CA', street: '1 Market St', zipcode: '94105' },
    customer: { customer_id: 'cus_123' },
    return_url: 'https://example.com/billing/success',
    subscription_data: {
        on_demand: {
            mandate_only: true // set false to collect an initial charge
            // product_price: 1000, // optional: charge $10.00 now if mandate_only is false
            // product_currency: 'USD',
            // product_description: 'Custom initial charge',
            // adaptive_currency_fees_inclusive: false,
        }
    }
  });

  console.log(subscription.checkout_url);
}

main().catch(console.error);
Success
{
  "session_id": "cks_123",
  "checkout_url": "https://test.checkout.dodopayments.com/session/cks123"
}

Cargar una suscripción bajo demanda

Después de que se autorice el mandato, crea cargos según sea necesario. Endpoint: POST /subscriptions/{subscription_id}/charge Campos clave de la solicitud (cuerpo):
product_price
integer
requerido
Importe a cobrar (en la unidad monetaria más pequeña). Ejemplo: para cobrar $25.00, pasa 2500.
product_currency
string
Anulación opcional de moneda para el cargo.
product_description
string
Anulación opcional de descripción para este cargo.
adaptive_currency_fees_inclusive
boolean
Si es verdadero, incluye tarifas de moneda adaptativa dentro de product_price. Si es falso, las tarifas se agregan encima.
metadata
object
Metadatos adicionales para el pago. Si se omite, se utilizan los metadatos de la suscripción.
import DodoPayments from 'dodopayments';

const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY });

async function chargeNow(subscriptionId) {
  const res = await client.subscriptions.charge(subscriptionId, { product_price: 2500 });
  console.log(res.payment_id);
}

chargeNow('sub_123').catch(console.error);
Success
{ "payment_id": "pay_abc123" }
Cobrar una suscripción que no es bajo demanda puede fallar. Asegúrate de que la suscripción tenga on_demand: true en sus detalles antes de cobrar.

Manejo de cargos fallidos

Cuando un cargo contra una suscripción bajo demanda falla, decides qué ocurre a continuación. A diferencia de las suscripciones programadas — donde una renovación fallida detiene la facturación automática — las suscripciones bajo demanda permanecen cargables tras un fallo. Puedes llamar al endpoint de carga nuevamente como parte de tu propia lógica de reintento.

Qué sucede en caso de fallo

1

Charge attempt fails

La solicitud POST /subscriptions/{subscription_id}/charge ya sea devuelve una respuesta de error o se completa de forma asincrónica y emite un webhook payment.failed con la razón del rechazo.
2

Subscription may transition to on_hold

La suscripción puede pasar al estado on_hold y emitir un webhook subscription.on_hold (ver Estados de Suscripción → En Espera). Esto es una señal, no un bloqueo. Para suscripciones bajo demanda, on_hold no impide que vuelvas a cobrar.
3

Retry the charge (your call)

Para flujos bajo demanda, Dodo no realiza reintentos automáticos. Puedes llamar a POST /subscriptions/{subscription_id}/charge en cualquier momento para intentar de nuevo. Aplica la política de reintentos segura a continuación: usa retroceso exponencial, omite rechazos fuertes y evita patrones de ráfaga, para que los reintentos no sean señalados por nuestros sistemas de fraude y riesgo.
4

Optionally, ask the customer for a new payment method

Si los reintentos siguen fallando porque el método de pago en sí está roto (tarjeta expirada, cuenta cerrada, etc.), usa POST /subscriptions/{id}/payment-method para recoger uno nuevo del cliente. Al tener éxito, la suscripción regresa a active y se emiten payment.succeeded seguido de subscription.active webhooks.
Bajo demanda vs programadas: Para suscripciones programadas, Dodo gestiona sus propios reintentos de renovación y gestión del cobro. Para suscripciones bajo demanda, tú controlas la política de reintentos porque solo tú sabes cuándo debe ocurrir el siguiente cobro (está impulsado por tus eventos de uso, no por un calendario).

Secuencia de webhook en un cobro fallido bajo demanda

OrdenEventoSignificado
1payment.failedEl intento de cobro bajo demanda no tuvo éxito (incluye la razón del rechazo)
2subscription.on_holdLa suscripción fue puesta en espera (informativo; no bloquea más cargos)
3*payment.succeededUn cobro posterior, ya sea tu reintento o después de una actualización del método de pago, tuvo éxito
4*subscription.activeLa suscripción regresó a active después de un cobro exitoso
Los eventos 3 y 4 solo se activan después de que un cobro de seguimiento tiene éxito.

Responsabilidad de reintentos

Dodo Payments no realiza reintentos automáticos de cargos fallidos bajo demanda. Tú controlas la política de reintentos. Sigue las pautas de reintentos seguros a continuación para evitar ser señalado por nuestros sistemas de detección de fraude como prueba de tarjetas.
Gestión del Cobro de Suscripciones — la secuencia de recuperación por correo electrónico integrada — se aplica a pagos de renovación fallidos en suscripciones programadas y cancelaciones iniciadas por el cliente. No está diseñada para fallos de cargos bajo demanda. Comunícate con el cliente directamente (por ejemplo, correo electrónico transaccional o mensaje en app) cuando decidas que se necesita actualizar el método de pago.

Reintentos de pago

Nuestro sistema de detección de fraude puede bloquear patrones de reintento agresivos (y puede señalarlos como posible prueba de tarjetas). Sigue una política de reintentos segura.
Patrones de reintentos en ráfaga pueden ser señalados como fraudulentos o sospechosos de ser pruebas de tarjetas por nuestros sistemas de riesgo y procesadores. Evita reintentos agrupados; sigue las guías de horario de retroceso y alineación de tiempo a continuación.

Principios para políticas de reintentos seguros

  • Mecanismo de retroceso: Usa retroceso exponencial entre reintentos.
  • Límites de reintentos: Limita los reintentos totales (máximo 3–4 intentos).
  • Filtrado inteligente: Reintenta solo en fallos que se pueden reintentar (por ejemplo, errores de red/emisor, fondos insuficientes); nunca reintentes rechazos fuertes.
  • Prevención de pruebas de tarjetas: No reintentes fallos como DO_NOT_HONOR, STOLEN_CARD, LOST_CARD, PICKUP_CARD, FRAUDULENT, AUTHENTICATION_FAILURE.
  • Varía metadatos (opcional): Si mantienes tu propio sistema de reintentos, diferencia los reintentos mediante metadatos (por ejemplo, retry_attempt).

Horario de reintentos sugerido (suscripciones)

  • 1er intento: Inmediato cuando creas el cargo
  • 2º intento: Después de 3 días
  • 3er intento: Después de 7 días más (10 días en total)
  • 4º intento (final): Después de otros 7 días (17 días en total)
Paso final: si aún está impago, marca la suscripción como impaga o cancélala, según tu política. Notifica al cliente durante el intervalo para que actualice su método de pago.

Evita reintentos en ráfaga; alinea con el tiempo de autorización

  • Ancla los reintentos a la marca de tiempo de la autorización original para evitar comportamiento de “ráfaga” en tu portafolio.
  • Ejemplo: Si el cliente inicia una prueba o mandato a la 1:10 pm hoy, programa reintentos de seguimiento a la 1:10 pm en días posteriores según tu retroceso (por ejemplo, +3 días → 1:10 pm, +7 días → 1:10 pm).
  • Alternativamente, si almacenas el tiempo del último pago exitoso T, programa el siguiente intento en T + X days para preservar la alineación del tiempo del día.
Zona horaria y DST: usa un estándar de tiempo consistente para programar y convierte para mostrar solo para mantener los intervalos.

Códigos de rechazo que no deberías volver a intentar

  • STOLEN_CARD
  • DO_NOT_HONOR
  • FRAUDULENT
  • PICKUP_CARD
  • AUTHENTICATION_FAILURE
  • LOST_CARD
Para una lista completa de razones de rechazo y si son corregibles por el usuario, consulta la documentación de Fallos de Transacciones.
Solo reintente en problemas suaves/temporales (por ejemplo, insufficient_funds, issuer_unavailable, processing_error, tiempos de espera de red). Si el mismo rechazo se repite, pausa más reintentos.

Pautas de implementación (sin código)

  • Usa un programador/cola que persista marcas de tiempo precisas; calcula el próximo intento con el mismo desfase de hora del día (por ejemplo, T + 3 days a la misma HH:MM).
  • Mantén y consulta la última marca de tiempo de pago exitoso T para calcular el próximo intento; no agrupe múltiples suscripciones al mismo instante.
  • Siempre evalúa la última razón de rechazo; detén los reintentos para rechazos fuertes en la lista de omisión arriba.
  • Límite de reintentos concurrentes por cliente y por cuenta para prevenir aumentos accidentales.
  • Comunica proactivamente: envía correo electrónico/SMS al cliente para actualizar su método de pago antes del próximo intento programado.
  • Usa metadatos solo para observabilidad (por ejemplo, retry_attempt); nunca intentes “evadir” sistemas de fraude/riesgo rotando campos inconsecuentes.

Rastrear resultados con webhooks

Implementa la gestión de webhooks para rastrear el recorrido del cliente. Consulta Implementación de Webhooks.
  • subscription.active: Mandato autorizado y suscripción activada
  • subscription.failed: Creación fallida (por ejemplo, fallo de mandato)
  • subscription.on_hold: Suscripción puesta en espera (por ejemplo, estado no pagado)
  • payment.succeeded: Cobro exitoso
  • payment.failed: Cobro fallido
Para flujos bajo demanda, enfócate en payment.succeeded y payment.failed para conciliar cargos basados en uso. Cuando payment.failed es seguido por subscription.on_hold, consulta Manejo de cargos fallidos para recuperar la suscripción.

Pruebas y próximos pasos

1

Create in test mode

Usa tu clave API de prueba para crear la suscripción con payment_link: true, luego abre el enlace y completa el mandato.
2

Trigger a charge

Llama al endpoint de carga con un pequeño product_price (por ejemplo, 100) y verifica que recibes payment.succeeded.
3

Go live

Cambia a tu clave API en vivo una vez que hayas validado eventos y actualizaciones de estado interno.

Solución de problemas

  • 422 Solicitud Inválida: Asegúrate de que on_demand.mandate_only se proporciona al crear y product_price se proporciona para cargos.
  • Errores de moneda: Si sobrescribes product_currency, confirma que está soportado para tu cuenta y cliente.
  • No se recibieron webhooks: Verifica la configuración de URL de webhook y el secreto de firma.
Last modified on May 14, 2026