> ## 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.

# Reintento manual de pagos

> Reintenta manualmente el pago fallido de renovación de una suscripción desde el dashboard o la API, sin esperar al siguiente reintento automático.

<Info>
  Manual Retry vuelve a intentar un pago de **renovación** de una suscripción cuando lo solicitas, desde la página de detalles del pago o mediante la API. Cobra el método de pago guardado en la suscripción y se ejecuta de forma independiente del calendario de [Payment Retries](/features/recovery/payment-retries) automáticos.
</Info>

## ¿Qué es Manual Retry?

Cuando falla un pago de renovación, la suscripción pasa a `on_hold`. Si activaste [Payment Retries](/features/recovery/payment-retries), estos vuelven a intentar el cobro según un calendario con intervalos crecientes. A veces sabes que el pago se aprobará ahora: el cliente confirmó que recargó su cuenta o tu equipo de soporte está hablando con él. Manual Retry envía un intento de inmediato, en lugar de esperar horas o días hasta el siguiente intento programado.

* **Solo pagos de renovación**: Manual Retry se aplica a las facturas de renovación de suscripciones mientras la suscripción está en `on_hold`. Los primeros pagos, pagos únicos, cargos por cambios de plan y cargos bajo demanda no son aptos.
* **Sin acción del cliente**: el cobro se realiza al método de pago ya guardado en la suscripción.
* **Independiente de los reintentos automáticos**: un reintento manual no consume un intento del calendario automático, no cambia el siguiente reintento programado y funciona incluso cuando Payment Retries está desactivado.
* **Reintenta la factura, no el pago**: el pago fallido es solo el punto de entrada. Dodo Payments encuentra la factura de renovación abierta asociada y cobra esa deuda, por lo que no importa desde qué pago fallido de la factura realices el reintento.

## Reintentar desde el dashboard

Solo los usuarios con el rol Owner o Editor pueden enviar un reintento manual.

<Steps>
  <Step title="Open the failed payment">
    Ve a **Transactions → Payments** y haz clic en el pago de renovación fallido para abrir su página de **Transaction details**.
  </Step>

  <Step title="Click Retry Payment Manually">
    Haz clic en **Retry Payment Manually** en la esquina superior derecha. El botón solo está disponible mientras el pago sea [eligible](#eligibility).
  </Step>

  <Step title="Check the result">
    Dodo Payments crea un nuevo pago para el intento, que aparece en el **Activity Log**. Si el cobro se realiza correctamente, la suscripción vuelve a `active` y la siguiente fecha de facturación pasa a ser un periodo de facturación posterior al reintento correcto. Si el procesador de pagos aún no ha liquidado el cobro, el pago aparece como en progreso hasta que el webhook `payment.succeeded` o `payment.failed` informe del resultado.
  </Step>
</Steps>

<Frame caption="Retry Payment Manually on the transaction details page of a failed renewal">
  <img src="https://mintcdn.com/dodopayments/0duTS18kYi2NwQ3m/images/recovery/manual-retry-transaction-details.png?fit=max&auto=format&n=0duTS18kYi2NwQ3m&q=85&s=5537fa5eff17cbe91a53599f887a26e7" alt="Transaction details page for a failed payment showing the error code and message, an Activity Log, and a Retry Payment Manually button" style={{ maxHeight: '500px', width: 'auto' }} width="1285" height="698" data-path="images/recovery/manual-retry-transaction-details.png" />
</Frame>

## Elegibilidad

Dodo Payments solo envía un reintento manual cuando se cumplen todas las comprobaciones de esta tabla. La columna **Reason code** muestra lo que devuelve la API: en `reason` sobre `GET /payments/{payment_id}/retry` y como el error `code` sobre `POST /payments/{payment_id}/retry`.

| Comprobación | Requisito | Reason code |
| - | - | - |
| Tipo de pago | Un pago de **renovación** de una suscripción cuya factura aún está abierta. Los pagos sin factura, los primeros pagos, los pagos únicos, los cargos por cambios de plan y los cargos bajo demanda no se pueden reintentar. | `PAYMENT_NOT_RETRYABLE` |
| Estado de la suscripción | `on_hold` | `SUBSCRIPTION_INACTIVE` |
| Cancelación programada | La suscripción no está programada para cancelarse en la próxima fecha de facturación. | `CHARGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION` |
| Método de pago guardado | La suscripción tiene un método de pago guardado que se puede cobrar. | `SUBSCRIPTION_HAS_NO_PAYMENT_METHOD` |
| Último fallo | El fallo más reciente es un **soft decline**. Un hard decline o un fallo sin un código de error clasificado no se puede reintentar. | `MANUAL_RETRY_HARD_DECLINE` |
| Nada en curso | Ningún pago de la factura está `processing` ni sigue sin un estado registrado. Dicho pago es un intento, manual o automático, que se acaba de enviar y aún no ha informado de su resultado. Espera primero a que finalice. | `MANUAL_RETRY_IN_FLIGHT` |
| El pago más reciente falló | El pago más reciente de la factura tiene el estado `failed`. Cualquier otro estado, como `requires_customer_action`, `requires_payment_method` o `cancelled`, bloquea el reintento aunque no haya nada en curso. | `PREVIOUS_PAYMENT_PENDING` |
| No se ha pagado ya | Ningún pago de la factura se ha completado correctamente. | `MANUAL_RETRY_ALREADY_PAID` |
| Límite de reintentos | Se han enviado menos de 3 reintentos manuales en la factura y ha pasado el periodo de espera. Consulta [Retry Limits](#retry-limits). | `MANUAL_RETRY_LIMIT_REACHED` |
| Cliente | El cliente no está en tu [blocklist](/features/customer-blocklist). | `PAYMENT_NOT_RETRYABLE` |
| Conector de pagos | Para las suscripciones [BYOP](/features/byop), el conector está activado. | `BYOP_CONNECTOR_DISABLED` |
| Modo live | En live mode, tu negocio tiene activados los pagos live. | `MERCHANT_NOT_LIVE` |

<Note>
  Manual Retry es más restrictivo que los reintentos automáticos en un aspecto: requiere que la suscripción esté en `on_hold`. Una suscripción `past_due` en un periodo de gracia no supera esta comprobación. Los reintentos automáticos siguen ejecutándose para otros estados no activos. Consulta [Subscription Status Transitions](/features/recovery/payment-retries#subscription-status-transitions).
</Note>

<Warning>
  Reintentar un hard decline contra la misma tarjeta no puede tener éxito, y los rechazos repetidos perjudican tu tasa de autorización. Cuando el motivo es `MANUAL_RETRY_HARD_DECLINE`, pide al cliente que actualice su método de pago. [Subscription Dunning](/features/recovery/subscription-dunning) lo hace automáticamente.
</Warning>

## Límites de reintentos

Cada factura de renovación permite **3** reintentos manuales, con un periodo de espera entre ellos:

| Reintento manual | Disponible |
| - | - |
| 1 | En cuanto el pago sea apto |
| 2 | 1 hora después del primero |
| 3 | 3 horas después del segundo |

Los límites se aplican tanto en test mode como en live mode. Cuando el límite rechaza un reintento, la API devuelve `MANUAL_RETRY_LIMIT_REACHED` (HTTP `429`) y el cuerpo del error contiene solo `code` y `message`. Para saber cuándo se habilita el siguiente reintento, [consulta el estado del reintento](#check-whether-a-payment-can-be-retried) y lee `retry_available_at`. Es `null` una vez consumidos los tres reintentos.

Los reintentos automáticos no cuentan para este límite y los reintentos manuales no cuentan para los 8 intentos del calendario automático.

## Reintentos manuales y automáticos

Las dos vías de reintento se diferencian en los siguientes aspectos:

| | Manual Retry | Payment Retries |
| - | - | - |
| **Activador** | Tú, desde el dashboard o la API | Dodo Payments, según un calendario con intervalos crecientes |
| **Momento** | Inmediatamente | 12 horas después del fallo y, después, progresivamente más tarde |
| **Intentos** | 3 por factura, con un periodo de espera de 1 hora y después de 3 horas | Hasta 8 por factura, dentro de tu ventana de recuperación |
| **Requiere Payment Retries activado** | No | Sí |
| **Efecto sobre el otro** | Ninguno. Un fallo manual no programa ni desplaza un intento automático. | Ninguno. La cadena automática continúa independientemente de los envíos manuales. |
| **Analytics** | Se contabiliza en las métricas de **Payment Retries**, en **Analytics → Recovery** | Se contabiliza en las mismas métricas |

## Reintentar mediante la API

Comprueba primero la elegibilidad y después envía el reintento. Ambos endpoints reciben el ID de un pago fallido.

### Comprobar si se puede reintentar un pago

`GET /payments/{payment_id}/retry` no devuelve un error para un pago que no es apto. En su lugar, devuelve `can_retry: false` con el código `reason`, para que tu propio dashboard o herramienta de soporte pueda mostrar el mismo estado que el dashboard de Dodo Payments. Requiere el rol **Viewer**.

<CodeGroup>
  ```typescript Node.js theme={null}
  import DodoPayments from 'dodopayments';

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

  const state = await client.payments.retrieveRetryState('pay_0NmDtkE0iRvmeTcT6t0ol');

  if (state.can_retry) {
    console.log(`Retry available. ${state.sends_used}/${state.sends_allowed} used.`);
  } else {
    console.log(`Cannot retry: ${state.reason}. Next window: ${state.retry_available_at}`);
  }
  ```

  ```python Python theme={null}
  import os
  from dodopayments import DodoPayments

  client = DodoPayments(bearer_token=os.environ["DODO_PAYMENTS_API_KEY"])

  state = client.payments.retrieve_retry_state("pay_0NmDtkE0iRvmeTcT6t0ol")

  if state.can_retry:
      print(f"Retry available. {state.sends_used}/{state.sends_allowed} used.")
  else:
      print(f"Cannot retry: {state.reason}. Next window: {state.retry_available_at}")
  ```

  ```bash cURL theme={null}
  curl https://live.dodopayments.com/payments/pay_0NmDtkE0iRvmeTcT6t0ol/retry \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY"
  ```
</CodeGroup>

```json Response theme={null}
{
  "can_retry": false,
  "reason": "MANUAL_RETRY_LIMIT_REACHED",
  "sends_used": 1,
  "sends_allowed": 3,
  "retry_available_at": "2026-08-26T16:51:00Z"
}
```

| Campo | Descripción |
| - | - |
| `can_retry` | `true` cuando se enviaría un reintento en ese momento. |
| `reason` | El código con el que fallaría el reintento. `null` cuando `can_retry` es `true`. |
| `sends_used` | Reintentos manuales ya enviados en esta factura. |
| `sends_allowed` | Siempre `3`. |
| `retry_available_at` | Cuándo se habilita el siguiente reintento manual. `null` cuando no queda ningún reintento o cuando el rechazo no está relacionado con el periodo de espera. |

### Enviar un reintento manual

`POST /payments/{payment_id}/retry` crea un nuevo pago y cobra el método de pago guardado. Requiere el rol **Editor**. Los ejemplos del SDK reutilizan `client` del ejemplo anterior.

<CodeGroup>
  ```typescript Node.js theme={null}
  // `client` is the DodoPayments instance from the previous example.
  const retry = await client.payments.retry('pay_0NmDtkE0iRvmeTcT6t0ol');

  console.log(retry.payment_id, retry.status);
  ```

  ```python Python theme={null}
  # `client` is the DodoPayments instance from the previous example.
  retry = client.payments.retry("pay_0NmDtkE0iRvmeTcT6t0ol")

  print(retry.payment_id, retry.status)
  ```

  ```bash cURL theme={null}
  curl -X POST https://live.dodopayments.com/payments/pay_0NmDtkE0iRvmeTcT6t0ol/retry \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY"
  ```
</CodeGroup>

```json Response theme={null}
{
  "payment_id": "pay_2IjeQm4hqU6RA4Z4kwDee",
  "invoice_id": "inv_9Kp2mQ7vRt4LxYw3",
  "status": "processing",
  "retry_attempt": 1,
  "is_manual_retry": true,
  "sends_used": 1,
  "sends_allowed": 3,
  "retry_available_at": "2026-08-26T16:51:00Z"
}
```

| Campo | Descripción |
| - | - |
| `payment_id` | El nuevo pago creado para este intento. |
| `invoice_id` | La factura de renovación que se cobró. |
| `status` | Resultado del cobro. `processing` significa que el procesador aún no lo ha liquidado. `null` significa que no se registró ningún resultado antes de devolver la respuesta. En ambos casos, los webhooks de pago informan del resultado final. |
| `retry_attempt` | Posición de este intento entre los reintentos manuales de la factura, empezando por `1`. |
| `is_manual_retry` | Siempre `true` en este endpoint. |
| `sends_used`, `sends_allowed`, `retry_available_at` | Estado del límite de reintentos después de este envío. `retry_available_at` corresponde únicamente al periodo de espera. Se establece incluso cuando este cobro se realiza correctamente; en ese caso, la factura está pagada y no se habilita ningún otro reintento. |

### Respuestas de error

Cuando no se permite un reintento, `POST` devuelve uno de estos estados HTTP:

| Estado HTTP | Códigos | Qué hacer |
| - | - | - |
| `404` | `NOT_FOUND` | El pago no pertenece a tu negocio. |
| `409` | `MANUAL_RETRY_IN_FLIGHT`, `PREVIOUS_PAYMENT_PENDING`, `CHARGE_NOT_ALLOWED_FOR_SCHEDULED_CANCELLATION` | El bloqueo es temporal o primero debe cambiar algo más. Espera a que el pago en curso o pendiente alcance un estado final, o elimina la cancelación programada. |
| `422` | `PAYMENT_NOT_RETRYABLE`, `SUBSCRIPTION_INACTIVE`, `SUBSCRIPTION_HAS_NO_PAYMENT_METHOD`, `MANUAL_RETRY_HARD_DECLINE`, `MANUAL_RETRY_ALREADY_PAID`, `BYOP_CONNECTOR_DISABLED`, `MERCHANT_NOT_LIVE` | Este pago no se puede reintentar. No repitas la llamada. |
| `429` | `MANUAL_RETRY_LIMIT_REACHED` | [Consulta el estado del reintento](#check-whether-a-payment-can-be-retried) y espera hasta `retry_available_at`, o detente cuando se hayan consumido los tres reintentos. |

La referencia de [Error Codes](/api-reference/error-codes) describe todos los códigos.

## Webhooks

Un reintento manual crea un pago normal, por lo que se activan los mismos webhooks que para cualquier intento de renovación:

| Evento | Se activa cuando |
| - | - |
| `payment.succeeded` | Se cobró el reintento. `subscription.active` se activa después, cuando se reactiva la suscripción. |
| `payment.failed` | Se rechazó el reintento. La suscripción permanece en `on_hold` y un fallo manual no programa un reintento automático. |
| `payment.processing` | El procesador ha aceptado el cobro, pero aún no lo ha liquidado. |

En el objeto de pago de estos eventos, `retry_attempt` es `1` o superior y `subscription_id` está establecido, igual que en un reintento automático. El objeto de pago no tiene ningún campo que marque un intento manual, así que conserva `payment_id` de la respuesta del reintento si necesitas distinguir un intento manual de uno programado.

<Card title="Payment Webhook Payloads" icon="webhook" href="/developer-resources/webhooks/intents/payment">
  Esquemas completos de payload para eventos de pago.
</Card>

## Relacionado

<CardGroup cols={2}>
  <Card title="Subscription Payment Retries" icon="arrow-rotate-right" href="/features/recovery/payment-retries">
    El calendario automático con intervalos crecientes que se ejecuta junto con los reintentos manuales.
  </Card>

  <Card title="Subscription Dunning" icon="repeat" href="/features/recovery/subscription-dunning">
    Envía un correo al cliente para que actualice su método de pago después de un hard decline.
  </Card>

  <Card title="Handle Payment Failures" icon="screwdriver-wrench" href="/developer-resources/handle-payment-failures">
    Lee los códigos de rechazo y decide cuándo merece la pena reintentar.
  </Card>

  <Card title="Error Codes" icon="triangle-exclamation" href="/api-reference/error-codes">
    Cada código `MANUAL_RETRY_*`, su activador y su mensaje.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.