Recover recurring payments
When a recurring payment is rejected, the appropriate action depends on the rejection reason: some are temporary and can be resolved by retrying the charge, while others require the customer to update their payment method. This guide explains how to query a rejected payment, identify the reason through its status_detail field, and define a retry and communication strategy for each case.
Retry strategy
When a rejection occurs, Mercado Pago already runs automatic retries natively: an immediate synchronous retry using a different acquirer and, if the payment has binary_mode = false, a batch acquirer optimization.
If the payment is still rejected after these internal attempts, you must manage the retry strategy based on the reason for each rejection: you determine the cadence of the next attempts (for example, 24h, 48h, or 7 days), decide when to retry and when to ask the customer to update their payment method, and handle the communication in each case.
The steps below describe how to implement this retry strategy.
For the retry strategy to work, your system needs to know immediately when a payment fails and why. To do so, you need to configure your webhook notifications and receive alerts about the creation or update of a payment, which will allow you to take the appropriate actions.
Make sure you have configured your webhook notifications for the Payments topic (payment).
When a payment is created or updated, Mercado Pago will send a notification in the following format:
json{ "id": 12345, "live_mode": true, "type": "payment", "date_created": "2015-03-25T10:04:58.396-04:00", "user_id": 44444, "api_version": "v1", "action": "payment.created", "data": { "id": "132260878091" } }
This notification contains only the payment ID, not its status. Upon receiving it, your server must immediately query the Payments API to obtain the full payment details.
To query the status of a payment, send a /v1/payments/{id}GET request using the ID received in the notification.
curl -X GET \
'https://api.mercadopago.com/v1/payments/{id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {{YOUR_ACCESS_TOKEN}}'
In the response, locate the two fields that indicate the rejection code and determine your next action:
| Field | Description | Example |
status | Current payment status | "rejected" |
status_detail | Specific rejection reason | "cc_rejected_insufficient_amount" |
Not all rejections should be handled the same way. Correctly categorizing the error based on its status_detail determines whether to apply retry logic or to contact the payer.
Based on their nature, rejections fall into three categories:
- Soft Declines (temporary errors): the rejection is temporary and there is a high probability of approval on a retry. You should retry following a cadence.
- Hard Declines (permanent errors): the rejection is not resolved by retrying, and persisting may affect your reputation with acquirers. Do not retry; the customer must update their payment method.
- Fill-in or configuration errors: they require a prior correction, either from the customer or from your integration. Retry only after correcting the data or configuration.
See how to recognize each error type and what actions to implement below.
status_detail | What it means | Action | Recommended communication |
cc_rejected_insufficient_amount | Insufficient funds. The customer does not have available balance. | Retry. Prioritize billing dates, for example days 1–5 or 15–20 of the month. The suggested cadence is 24h, 48h, 72h. | Immediate (automatic): "Your payment failed due to insufficient funds. Make sure you have available balance. We will retry in 24h." |
cc_amount_rate_limit_exceeded | Daily limit exceeded. The customer exceeded their daily charge limit. | Retry. Wait 24 hours and retry. | Immediate (automatic): "Your payment failed because you exceeded your daily limit. We will retry automatically in 24h." |
cc_rejected_other_reason | Generic bank rejection. The issuer did not provide a specific reason. | Retry with caution. Retry once in 24h. If it fails again, treat it as a hard decline. | Immediate (automatic): "Your bank declined the payment without giving us a reason. We will retry in 24h. If the problem persists, contact your bank." |
cc_rejected_call_for_authorize | The bank requests the customer's authorization to validate the purchase. | Do not retry yet. The retry will fail until the customer authorizes the purchase with their bank. | Immediate (action required): "Your bank blocked the payment and requires your authorization. Please contact your bank to approve the charge from [Company Name]. Let us know when you have done so and we will retry." |
cc_rejected_time_out / cc_rejected_expired_operation | Processor timeout. Technical error or timeout. | Retry. Wait 5 to 15 minutes and retry the charge. | No communication is necessary yet. The customer is not responsible for the error. Retry 1 or 2 times; if it keeps failing, notify the customer. |
In most flows, Mercado Pago does not contact the end customer on your behalf. Managing the communication in case of rejections is the merchant's responsibility and is just as important as the technical retry.
For this reason, you need to define a communication strategy taking the following points into account:
-
Define a recovery window: determine how long the customer has to resolve the payment rejection reason before you suspend the service.
-
Segment communication by error type:
- Soft Declines: use a low-friction tone. Communicate that there was a temporary issue and that the retry will happen automatically.
- Hard Declines: use an urgent tone. Inform that the service is at risk of suspension and request an immediate payment method update.
-
Provide a secure update link: direct the customer to a secure portal where they can update their payment method; never request their data by other means. When the customer completes the update, charge the pending amount immediately.
For more information on how to improve payment approval, refer to the recommendations to improve approval.